Docker container will automatically stop after "docker run -d"
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:
J John
Updated on February 18, 2022Comments
-
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 about 9 yearsSorry, 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 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 about 8 yearsAfter 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 about 8 years@GuruprasadGV That is expected. Instead of using docker attach, use
docker exec -it <yourContainer> bash
. -
Scarysize over 7 yearsNice. Seems less hacky than appending
tail -f /dev/null
-
yara over 7 yearsThis also works if you add the tail command at the end of an entrypoint file.
-
Peter Becich over 7 yearsThanks! On the slim chance this helps someone, this doesn't behave nicely in Emacs Eshell.
-
andrew pate about 7 yearsI 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 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 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 almost 7 yearsif someone kill that tail process from the main shell your container will be stopped.
-
jersey bean over 6 yearsI 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 over 6 yearsI 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 over 6 yearsThe command is completely optional. What's important here is the -t and/or -i options, combined with -d option.
-
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 over 6 yearsIs there any advantage of using
-t -d
vs-i -d
? Both will keep the container running. -
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 over 5 yearsMight want to
touch
that file first, in case you couldn't find a log file. -
Peiming Hu about 5 yearsUsually 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 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 about 5 years@MarinosAn Thank you. I have included your comment in the answer for more visibility.
-
John Kugelman about 5 yearsNote that this doesn't work on alpine as BusyBox's sleep doesn't accept
infinity
. -
Geordie over 4 yearsI 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 over 4 yearsis this the solution that you created infinite loop for this? :D
-
influent about 4 yearsthis helped me troubleshoot an amazon-linux image, thank you
-
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 over 2 yearsThe
<image>
should be container's name, right? -
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 over 2 yearsIt'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 about 2 yearsFor me the command requires an image name, so it doesn't work