Reputation: 2833
I want to start a service with docker-compose and keep the container running so I can get its IP-address via 'docker inspect'. However, the container always exits right after starting up.
I tried to add "command: ["sleep", "60"]" and other things to the docker-compose.yml but whenever I add the line with "command:..." I cant call "docker-compose up" as I will get the message "Cannot start container ..... System error: invalid character 'k' looking for beginning of value"
I also tried adding "CMD sleep 60" and whatnot to the Dockerfile itself but these commands do not seem to be executed.
Is there an easy way to keep the container alive or to fix one of my problems?
EDIT: Here is the Compose file I want to run:
version: '2'
services:
my-test:
image: ubuntu
command: bash -c "while true; do echo hello; sleep 2; done"
It's working fine If I start this with docker-compose under OS X, but if I try the same under Ubuntu 16.04 it gives me above error message.
If I try the approach with the Dockerfile, the Dockerfile looks like this:
FROM ubuntu:latest
CMD ["sleep", "60"]
Which does not seem to do anything
EDIT 2: I have to correct myself, turned out it was the same problem with the Dockerfile and the docker-compose.yml: Each time I add either "CMD ..." to the Dockerfile OR add "command ..." to the compose file, I get above error with the invalid character. If I remove both commands, it works flawlessly.
Upvotes: 246
Views: 294589
Reputation: 21011
If you want a quick docker run
option, in a tiny busybox image, as a one-liner:
docker run --rm --name forever busybox sh -c 'trap : TERM INT; tail -f /dev/null & wait'
If you want to exec into that container:
docker exec -it forever sh
You can stop it with CTRL + Z and it will stop gracefully and without delay.
If you prefer a docker-compose.yml
file:
services:
forever:
image: busybox
command: 'sh -c "trap : TERM INT; tail -f /dev/null & wait"'
Based on this.
Upvotes: 2
Reputation: 1396
This was the only way I could get it to work without using something like tail -f /dev/null
. I read many of the answers here saying that adding init
to the compose file should be enough and confirmed the same in Docker's documentation but I could not get it to work with init
alone.
# compose.yml
services:
my-test:
build:
context: .
dockerfile: dockerfile
tty: true
init: true
# dockerfile
FROM node:20-alpine
RUN apk add --no-cache --update bash
CMD ["/bin/sh"]
Upvotes: 0
Reputation: 1599
Add entrypoint to docker-compose file
entrypoint: ["tail", "-f", "/dev/null"]
Upvotes: 3
Reputation: 1501
I have used some of the solutions above which works for ubuntu
or nodejs
images. However they don't work with the bitnami/azure-cli
image. Whatever specified in command
becomes argument(s) for the az
command of that image. After a bit of struggling, this is how the docker-compose.yml
file should be:
version: "2.4"
services:
azure-cli:
image: "bitnami/azure-cli:latest"
container_name: az-container
entrypoint: tail -f /dev/null
As @highjump points out above, this entrypoint
option overrides the internal command
option, and keeps the container running.
Upvotes: -1
Reputation: 824
Blocking command is all you need.
I have been struggling with this problem for half a day. . There are many answers below, but not clear enough. And nobody said why.
In short, there are two methods, but it can also be said that there is only one, running a Blocking processes
in background.
This first one is using COMMAND
:
version: '3'
services:
some-app:
command: ["some block command"]
put some block command like sleep infinity
, tail -f /dev/null
, watch anything
, while true
...
Here I recommend sleep infinity
.
The second is enable tty=true
, then open a shell in command like /bin/bash
.
services:
ubuntu:
image: ubuntu:latest
tty: true
command: "/bin/bash"
Since the tty is enabled, bash will keep running background, you can put some other block commands before it if you want.
Be careful, you must excute shell command at the end, like
command: /bin/bash -c "/root/.init-service && /bin/bash"
As you can see, all you need is blocking command.
Upvotes: 12
Reputation: 9207
I'm late to the party, but you can simply use: stdin_open: true
version: '2'
services:
my-test:
image: ubuntu
stdin_open: true
Upvotes: 25
Reputation: 3342
To keep a container running when you start it with docker-compose
, use the following command
command: tail -F anything
In the above command the last part anything
should be included literally, and the assumption is that such a file is not present in the container, but with the -F
option (capital -F
not to be confused with -f
which in contrast will terminate immediateley if the file is not found) the tail
command will wait forever for the file anything
to appear. A forever waiting process is basically what we need.
So your docker-compose.yml becomes
version: '2'
services:
my-test:
image: ubuntu
command: tail -F anything
and you can run a shell to get into the container using the following command
docker exec -i -t composename_my-test_1 bash
where composename
is the name that docker-compose
prepends to your containers.
Upvotes: 295
Reputation: 3031
Some people here write about overwriting the entrypoint
so that the command
can also have its effect. But no one gives an example. I then:
docker-compose.yml
:
version: '3'
services:
etfwebapp:
# For messed up volumes and `sudo docker cp`:
command: "-f /dev/null"
entrypoint: /usr/bin/tail
tty: true
# ...
I am not sure if tty
is needed at this point. Is it better to do it twice? In my case it did no harm and worked perfectly. Without entrypoint
it didn't work for me because then command
had no effect. So I guess for this solution tty
is optional.
To understand which command is executed at start-up, simply read the entrypoint
before the command
(concat with space): /usr/bin/tail -f /dev/null
.
Upvotes: 16
Reputation: 910
Just a quick note
I have tested single image based on golang
, so when I call docker-compose down
here what I get:
version: "3.1"
...
command: tail -f /dev/null # stopping container takes about 10 sec.
tty: true # stopping container takes about 2 sec.
My system info:
Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659
Upvotes: 5
Reputation: 3065
You can use tty
configuration option.
version: '3'
services:
app:
image: node:8
tty: true # <-- This option
Note: If you use Dockerfile for image and CMD
in Dockerfile, this option won't work; however, you can use the entrypoint
option in the compose file which clears the CMD
from the Dockerfile.
Upvotes: 275
Reputation: 1521
docker-compose.yml
version: "3"
services:
ubuntu:
image: ubuntu:latest
tty: true
docker-compose up -d
from the terminaldocker ps
to get the container id or namedocker inspect $container_id
docker-compose exec ubuntu /bin/bash
or docker-compose exec ubuntu /bin/sh
docker-compose down
Here's a small bash script (my-docker-shell.sh
) to create the docker compose file, run the container, login to the container and then finally cleanup the docker container and the docker compose file when you log out.
#!/bin/bash
cat << 'EOF' > ./docker-compose.yml
---
version: "3"
services:
ubuntu:
image: ubuntu:latest
command: /bin/bash
# tty: true
...
EOF
printf "Now entering the container...\n"
docker-compose run ubuntu bash
docker-compose down
rm -v ./docker-compose.yml
Upvotes: 29
Reputation: 11719
Based on the comment of @aanand on GitHub Aug 26, 2015, one could use tail -f /dev/null
in docker-compose to keep the container running.
docker-compose.yml example
version: '3'
services:
some-app:
command: tail -f /dev/null
Why this command?
The only reason for choosing this option was that it received a lot of thumbs up on GitHub, but the highest voted answer does not mean that it is the best answer. The second reason was a pragmatic one as issues had to be solved as soon as possible due to deadlines.
Upvotes: 92
Reputation: 2833
Okay I found my mistake. In the Dockerfile for the image used for compose I specified that the base image should be ubuntu:latest, but I previously created an image called ubuntu by myself and that image did not work. So I did not use the original ubuntu image but rather a corrupt version of my own image also called ubuntu.
Upvotes: -3
Reputation: 15235
As the commenter stated, we'd have to see the Dockerfile in question to give you a complete answer, but this is a very common mistake. I can pretty much guarantee that the command you're trying to run is starting a background process. This might be the command you'd run in non-Docker situations, but it's the wrong thing to do in a Dockerfile. For instance, if what you're running is typically defined as a system service, you might use something like "systemctl start". That would start the process in the background, which will not work. You have to run the process in the foreground, so the entire process will block.
Upvotes: 3