Docker container will automatically stop after "docker run -d"

649,040

Solution 1

The centos dockerfile has a default command bash.

That means, when run in background (-d), the shell exits immediately.

Update 2017

More recent versions of docker authorize to run a container both in detached mode and in foreground mode (-t, -i or -it)

In that case, you don't need any additional command and this is enough:

docker run -t -d centos

The bash will wait in the background.
That was initially reported in kalyani-chaudhari's answer and detailed in jersey bean's answer.

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

Note that for alpine, Marinos An reports in the comments:

docker run -t -d alpine/git does not keep the process up.
Had to do: docker run --entrypoint "/bin/sh" -it alpine/git


Original answer (2015)

As mentioned in this article:

Instead of running with docker run -i -t image your-command, using -d is recommended because you can run your container with just one command and you don’t need to detach terminal of container by hitting Ctrl + P + Q.

However, there is a problem with -d option. Your container immediately stops unless the commands keep running in foreground.
Docker requires your command to keep running in the foreground. Otherwise, it thinks that your applications stops and shutdown the container.

The problem is that some application does not run in the foreground. How can we make it easier?

In this situation, you can add tail -f /dev/null to your command.
By doing this, even if your main command runs in the background, your container doesn’t stop because tail is keep running in the foreground.

So this would work:

docker run -d centos tail -f /dev/null

Or in Dockerfile:

ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]

A docker ps would show the centos container still running.

From there, you can attach to it or detach from it (or docker exec some commands).

Solution 2

According to this answer, adding the -t flag will prevent the container from exiting when running in the background. You can then use docker exec -i -t <image> /bin/bash to get into a shell prompt.

docker run -t -d <image> <command>

It seems that the -t option isn't documented very well, though the help says that it "allocates a pseudo-TTY."

Solution 3

Background

A Docker container runs a process (the "command" or "entrypoint") that keeps it alive. The container will continue to run as long as the command continues to run.

In your case, the command (/bin/bash, by default, on centos:latest) is exiting immediately (as bash does when it's not connected to a terminal and has nothing to run).

Normally, when you run a container in daemon mode (with -d), the container is running some sort of daemon process (like httpd). In this case, as long as the httpd daemon is running, the container will remain alive.

What you appear to be trying to do is to keep the container alive without a daemon process running inside the container. This is somewhat strange (because the container isn't doing anything useful until you interact with it, perhaps with docker exec), but there are certain cases where it might make sense to do something like this.

(Did you mean to get to a bash prompt inside the container? That's easy! docker run -it centos:latest)

Solution

A simple way to keep a container alive in daemon mode indefinitely is to run sleep infinity as the container's command. This does not rely doing strange things like allocating a TTY in daemon mode. Although it does rely on doing strange things like using sleep as your primary command.

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

Alternative Solution

As indicated by cjsimon, the -t option allocates a "pseudo-tty". This tricks bash into continuing to run indefinitely because it thinks it is connected to an interactive TTY (even though you have no way to interact with that particular TTY if you don't pass -i). Anyway, this should do the trick too:

$ docker run -t -d centos:latest

Not 100% sure whether -t will produce other weird interactions; maybe leave a comment below if it does.

Solution 4

Hi this issue is because docker containers exit if there is no running application in the container.

-d 

option is just to run a container in deamon mode.

So the trick to make your container continuously running is point to a shell file in docker which will keep your application running.You can try with a start.sh file

Eg: docker run -d centos sh /yourlocation/start.sh

This start.sh should point to a never ending application.

In case if you dont want any application to be running,you can install monit which will keep your docker container running. Please let us know if these two cases worked for you to keep your container running.

All the best

Solution 5

You can accomplish what you want with either:

docker run -t -d <image-name>

or

docker run -i -d <image-name>

or

docker run -it -d <image-name>

The command parameter as suggested by other answers (i.e. tail -f /dev/null) is completely optional, and is NOT required to get your container to stay running in the background.

Also note the Docker documentation suggests that combining -i and -t options will cause it to behave like a shell.

See:

https://docs.docker.com/engine/reference/run/#foreground

Share:
649,040
J John
Author by

J John

Updated on February 18, 2022

Comments

  • J John
    J John about 2 years

    According to tutorial I read so far, use "docker run -d" will start a container from image, and the container will run in background. This is how it looks like, we can see we already have container id.

    root@docker:/home/root# docker run -d centos
    605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d
    

    But if I ran "docker ps", nothing was returned.

    So I tried "docker ps -a", I can see container already exited:

    root@docker:/home/root# docker ps -a
    CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
    605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz
    

    Anything I did wrong? How can I troubleshoot this issue?

  • J John
    J John about 9 years
    Sorry, one more question, I have a script need to run at startup, looks like /etc/rc.d/rc.local no longer works(my mindset still treating docker like OS), I assume docker file is better option in this case?
  • VonC
    VonC about 9 years
    @JJohn yes, you can COPY (docs.docker.com/reference/builder/#copy) the script in your image, and then use it in your default CMD in order for that script to run when starting the container.
  • Guruprasad GV
    Guruprasad GV about 8 years
    After adding tail -f /dev/null, I can't attach back to the shell, though I understand why, is there way to get that working somehow?
  • VonC
    VonC about 8 years
    @GuruprasadGV That is expected. Instead of using docker attach, use docker exec -it <yourContainer> bash.
  • Scarysize
    Scarysize over 7 years
    Nice. Seems less hacky than appending tail -f /dev/null
  • yara
    yara over 7 years
    This also works if you add the tail command at the end of an entrypoint file.
  • Peter Becich
    Peter Becich over 7 years
    Thanks! On the slim chance this helps someone, this doesn't behave nicely in Emacs Eshell.
  • andrew pate
    andrew pate about 7 years
    I used sshd as my last (long running) command. You can then ssh on too your container as you would on a VM (once you set .ssh/authorized_keys etc)... You can also go on to configure the container using ansible.
  • VonC
    VonC about 7 years
    @andrewpate Nice. Generally, when I use Ansible on a container, it is for committing that container and make a new image.
  • Putnik
    Putnik almost 7 years
    docker run -t -d --name mysql -p 3306:3306 mysql - doesn't work for me (ubuntu 14.04.5): STATUS=Exited (1) 4 seconds ago
  • Putnik
    Putnik almost 7 years
    if someone kill that tail process from the main shell your container will be stopped.
  • jersey bean
    jersey bean over 6 years
    I found that you don't need <command> here, unless you want. Strangely, it also works to replace -t with -i (interactive). The doc does mention using -t and -i combined will behave like a shell.
  • jersey bean
    jersey bean over 6 years
    I actually like this answer the best, because the most popular answer suggests that you need a command (i.e. tail -f /dev/null). The command is completely optional. The key here is to use -t. I also found -i work in place of -t, or you can also use both -it combined (as the documentation suggests it will run as a shell).
  • jersey bean
    jersey bean over 6 years
    The command is completely optional. What's important here is the -t and/or -i options, combined with -d option.
  • VonC
    VonC over 6 years
    @jerseybean Good point. I have amended the answer accordingly, and reference both your answer and kalyani chaudhari's, for more visibility.
  • wisbucky
    wisbucky over 6 years
    Is there any advantage of using -t -d vs -i -d? Both will keep the container running.
  • wisbucky
    wisbucky over 6 years
    @jersey The command does matter. Try docker run -t -d centos ls, it will not stay running. The reason no command works is because it uses the default CMD for the image, which is /bin/bash.
  • Ismail
    Ismail over 5 years
    Might want to touch that file first, in case you couldn't find a log file.
  • Peiming Hu
    Peiming Hu about 5 years
    Usually the log file I tail is the current server log or redirection output, which should already be there after the process is started.
  • Marinos An
    Marinos An about 5 years
    docker run -t -d alpine/git does not keep the process up. Had to do: docker run --entrypoint "/bin/sh" -it alpine/git
  • VonC
    VonC about 5 years
    @MarinosAn Thank you. I have included your comment in the answer for more visibility.
  • John Kugelman
    John Kugelman about 5 years
    Note that this doesn't work on alpine as BusyBox's sleep doesn't accept infinity.
  • Geordie
    Geordie over 4 years
    I ended up doing this to execute my command plus the older fix listed above: docker run image_name /bin/bash -c "my/command && tail -f /dev/null"
  • Salman Saleem
    Salman Saleem over 4 years
    is this the solution that you created infinite loop for this? :D
  • influent
    influent about 4 years
    this helped me troubleshoot an amazon-linux image, thank you
  • VonC
    VonC over 3 years
    @Mercury Thank you for the edit. None of the comments of kimh.github.io/blog/en/docker/gotchas-in-writing-dockerfile-‌​en/… seemed to have noticed that.
  • CyberPlayerOne
    CyberPlayerOne over 2 years
    The <image> should be container's name, right?
  • babybob
    babybob over 2 years
    @CyberPlayerOne...<image> should be image name. "docker run" is an old command and they are keeping it for backward compatibility. You can find more @ stackoverflow.com/a/51247809/6536853 and docker.com/blog/whats-new-in-docker-1-13
  • abestrad
    abestrad over 2 years
    It's not an internal issue/error. The issue seems to be related to the fact the command the OP is using to run the container is exiting because it's not running an app and/or is not waiting for user input. So, how is that displaying the logs value will help with that?
  • Kureteiyu
    Kureteiyu about 2 years
    For me the command requires an image name, so it doesn't work