556

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?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
J John
  • 5,591
  • 3
  • 11
  • 9
  • 2
    "docker run hello-world" <== works perfectly, but if I run "docker run -d hello-world", I still cannot get a running container. – J John May 13 '15 at 08:50
  • 8
    I had a similar issue but I got it working by using `docker run -it -d /bin/bash` this starts a bash shell interactively and doesn't close the container because the shell process is active. – Rtsne42 Jun 20 '17 at 17:16

23 Answers23

804

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 running 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).


However, as noted by bviktor in the comments:

Overriding entrypoint will mess up with your Dockerfile if it has anything specified.
systemd is of particular interest.

Tailing /dev/null also doesn't sound very convincing: in essence you bombard your system with completely unnecessary system calls.
The other solution with sleep looks much better.

That relies on sleep infinity, a GNU coreutils extension not contemplated in POSIX.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 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? – J John May 13 '15 at 10:03
  • @JJohn yes, you can COPY (http://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. – VonC May 13 '15 at 10:30
  • 1
    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? – Guruprasad GV Mar 05 '16 at 05:04
  • 6
    @GuruprasadGV That is expected. Instead of using docker attach, use `docker exec -it bash`. – VonC Mar 05 '16 at 07:01
  • 4
    This also works if you add the tail command at the end of an entrypoint file. – yara Jan 20 '17 at 18:12
  • 2
    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. – andrew pate Mar 15 '17 at 15:07
  • @andrewpate Nice. Generally, when I use Ansible on a container, it is for committing that container and make a new image. – VonC Mar 15 '17 at 15:09
  • if someone kill that tail process from the main shell your container will be stopped. – Putnik Jun 01 '17 at 20:40
  • The command is completely optional. What's important here is the -t and/or -i options, combined with -d option. – jersey bean Sep 27 '17 at 08:21
  • @jerseybean Good point. I have amended the answer accordingly, and reference both your answer and kalyani chaudhari's, for more visibility. – VonC Sep 27 '17 at 08:36
  • @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`. – wisbucky Dec 22 '17 at 00:39
  • `docker run -t -d alpine/git` does not keep the process up. Had to do: `docker run --entrypoint "/bin/sh" -it alpine/git` – Marinos An Mar 14 '19 at 11:34
  • @MarinosAn Thank you. I have included your comment in the answer for more visibility. – VonC Mar 14 '19 at 13:19
  • 1
    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" – Geordie Sep 09 '19 at 21:34
  • @Mercury Thank you for the edit. None of the comments of http://kimh.github.io/blog/en/docker/gotchas-in-writing-dockerfile-en/#hack_to_run_container_in_the_background seemed to have noticed that. – VonC Oct 29 '20 at 16:41
  • Overriding entrypoint will mess up with your Dockerfile if it has anything specified. systemd is of particular interest. Tailing `/dev/null` also doesn't sound very convincing, in essence you bombard your system with completely unnecessary system calls. The other solution with `sleep` looks much better. – bviktor Apr 15 '23 at 10:08
  • @bviktor Thank you for your comment, good point. I have included your comment in the answer for more visibility. – VonC Apr 15 '23 at 16:20
96

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."

Community
  • 1
  • 1
cjsimon
  • 1,121
  • 12
  • 22
  • 15
    Nice. Seems less hacky than appending `tail -f /dev/null` – Scarysize Jan 05 '17 at 15:38
  • Thanks! On the slim chance this helps someone, this doesn't behave nicely in Emacs Eshell. – Peter Becich Feb 01 '17 at 22:35
  • 7
    `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 Jun 01 '17 at 20:06
  • I found that you don't need 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 Sep 27 '17 at 08:11
  • The `` should be container's name, right? – CyberPlayerOne Aug 31 '21 at 07:06
  • 1
    @CyberPlayerOne... should be image name. "docker run" is an old command and they are keeping it for backward compatibility. You can find more @ https://stackoverflow.com/a/51247809/6536853 and https://www.docker.com/blog/whats-new-in-docker-1-13/ – babybob Sep 15 '21 at 06:04
88

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.

mkasberg
  • 16,022
  • 3
  • 42
  • 46
24

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

Pratik
  • 1,216
  • 11
  • 18
19

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

jersey bean
  • 3,321
  • 4
  • 28
  • 43
15

I have this code snippet run from the ENTRYPOINT in my docker file:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

Run the built docker image as:

docker run -td <image name>

Log in to the container shell:

docker exec -it <container id> /bin/bash
Binita Bharati
  • 5,239
  • 1
  • 43
  • 24
12

execute command as follows :

docker run -t -d <image-name>

if you want to specify port then command as below:

docker run -t -d -p <port-no> <image-name>

verify the running container using following command:

docker ps
kalyani chaudhari
  • 7,515
  • 3
  • 24
  • 21
  • 1
    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 Sep 27 '17 at 08:13
  • Is there any advantage of using `-t -d` vs `-i -d`? Both will keep the container running. – wisbucky Dec 22 '17 at 00:15
11

Docker container exits if task inside is done, so if you want to keep it alive even if it does not have any job or already finished them, you can do docker run -di image. After you do docker container ls you will see it running.

Vrangz
  • 285
  • 3
  • 13
7

Docker requires your command to keep running in the foreground. Otherwise, it thinks that your applications stops and shutdown the container.

So if your docker entry script is a background process like following:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

The '&' makes the container stop and exit if there are no other foreground process triggered later. So the solution is just remove the '&' or have another foreground CMD running after it, such as

tail -f server.log
Peiming Hu
  • 517
  • 6
  • 8
  • Might want to `touch` that file first, in case you couldn't find a log file. – Ismail Jan 03 '19 at 23:19
  • Usually the log file I tail is the current server log or redirection output, which should already be there after the process is started. – Peiming Hu Feb 20 '19 at 09:50
6

If you are using CMD at the end of your Dockerfile, what you can do is adding the code at the end. This will only work if your docker is built on ubuntu, or any OS that can use bash.

&& /bin/bash

Briefly the end of your Dockerfile will look like something like this.

...

CMD ls && ... && /bin/bash

So if you have anything running automatically after you run your docker image, and when the task is complete the bash terminal will be active inside your docker. Thereby, you can enter you shell commands.

Ekin
  • 407
  • 1
  • 6
  • 17
5

Maybe it is just me but on CentOS 7.3.1611 and Docker 1.12.6 but I ended up having to use a combination of the answers posted by @VonC & @Christopher Simon to get this working reliably. Nothing I did before this would stop the container from exiting after it ran CMD successfully. I am starting oracle-xe-11Gr2 and sshd.

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

Then adding -d -t and -i to run

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

Finally after hours of bashing my head against the wall

ssh -v root@127.0.0.1 -p 5022
...
root@127.0.0.1's password: 
debug1: Authentication succeeded (password).

For whatever reason the above will exit after executing CMD if the tail -f is removed, or any of the -t -d -i options are omitted.

steven87vt
  • 500
  • 7
  • 6
3

You can simply use:

docker container run -d -it <container name or id> /bin/bash
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
3

Quick answer to the issue:

Just execute the following command:

docker run -d image_name sleep infinity

See image below:

enter image description here

What is sleep infinity, and how does it work?

The sleep command is a Unix command that causes the shell to wait for a specified amount of time.

The sleep infinity command is used in Docker to keep a container running indefinitely. When you run a container in Docker, it will run the command you specify in the container and then exit once the command is finished. If you want to keep the container running even after the command has finished, you can use the sleep infinity command.

STerliakov
  • 4,983
  • 3
  • 15
  • 37
2

I had the same issue, just opening another terminal with a bash on it worked for me :

create container:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

start container:

docker start 52bbc9b30557

start bash to keep container running:

docker exec -it 52bbc9b30557 bash

start process you need:

docker exec -it 52bbc9b30557 /path_to_cool_your_app
Steef
  • 569
  • 5
  • 21
2

Running docker with interactive mode might solve the issue.

Here is the example for running image with and without interactive mode

chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker run -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18

chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker run -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c812fb2b7ce2105d7ff5

chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c3d6a9529fd7 test_again1.0 "bash" 2 seconds ago Up 1 second awesome_haibt

Hegde
  • 234
  • 2
  • 3
1

I have explained it in the following post that has the same question.

How to retain docker alpine container after "exit" is used?

vimal krishna
  • 2,886
  • 28
  • 22
0

Argument order matters

Jersey Beans answer (all 3 examples) worked for me. After quite a bit of trial and error I realized that the order of the arguments matter.

Keeps the container running in the background: docker run -t -d <image-name>

Keeps the container running in the foreground: docker run <image-name> -t -d

It wasn't obvious to me coming from a Powershell background.

HVL71
  • 251
  • 2
  • 5
0

I was also facing the same problem but in a different manner. When I create the docker containers. it automatically stops the unused containers which are just running in the background. Sometimes it also stops the containers that are in the use. In my situation, this is because of the permission of the docker.sock files it earlier has. what you have to do is :-

  1. Install docker again.(As i work on ubuntu i install it from here)

  2. Run the command to change the permissions.

    sudo chmod 666 /var/run/docker.sock

  3. Install docker-compose (this is optional as I have compose file to create many containers together)

    sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

    sudo chmod +x /usr/local/bin/docker-compose

  4. check for the version to ensure that I have the latest one and not get problem with some deprications.

  5. Then I run the docker container build.

-1

if you want to operate on the container, you need to run it in foreground to keep it alive.

Jackie
  • 25,199
  • 6
  • 33
  • 24
-1

There are multiple options out there to run the container in foreground/detached state. But if you still feel the issue is not resolved, you can try troubleshooting the issue by viewing the logs.

sudo docker logs -f >> container.log

additionally you can also use --details to show extra details provided to logs.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 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? – abestrad Jan 21 '22 at 11:48
-1

Incorrect Path to App in Dockerfile:

I was migrating an application from a RHEL server to a Docker container using Alpine Linux.

No errors during the build, so I was surprised to see the container immediately exit!

First port of call:

docker logs <containerID>

This revealed the path of the binary I had supplied to CMD in the Dockerfile was bogus:

line 0: /sbin/postfix: not found

Well that told me how things were broken, but not specifically where: I still required the correct path for the binary in Alpine Linux...

Troubleshooting:

Googling didn't reveal the correct path to it, so I added the following line to my Dockerfile:

RUN which postfix

I then reviewed my build logging- provided by the below command appended to my build command- to retrieve the value of RUN which postfix

 --progress=plain > /path/to/build.log 2>&1

The Fix:

I deleted this test build, supplied the correct path- /usr/sbin/postfix - to CMD in the Dockerfile, deleted RUN which postfix and ran another build.

Voila; the process now remained up.

So a duff path was causing the container to immediately exit...

F1Linux
  • 3,580
  • 3
  • 25
  • 24
-2

These 4 commands all work to keep your docker container running:

docker run -td centos
docker run -dt centos
docker run -t -d centos
docker run -d -t centos
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
-3
  • Firstly, You need to check if any container is running Type command,

docker ps -all

  • If any container is running then stop them Type command,

docker stop Container Id

  • Now, Finally run the docker by using below command..........

  • docker run -t -p 2020:3000 dockerImageName

Hence, Open your google chrome and visit on localhost:2020

Congrats :)

Saurabh Kumar
  • 37
  • 1
  • 5