[英]Docker Compose keep container running
I want to start a service with docker-compose and keep the container running so I can get its IP-address via 'docker inspect'.我想用 docker-compose 启动服务并保持容器运行,这样我就可以通过“docker inspect”获取它的 IP 地址。 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"我尝试在 docker-compose.yml 中添加“command: ["sleep", "60"]" 和其他内容,但是每当我添加带有“command:...”的行时,我都无法调用“docker-compose up”将收到消息“无法启动容器......系统错误:无效字符'k'正在寻找值的开头”
I also tried adding "CMD sleep 60" and whatnot to the Dockerfile itself but these commands do not seem to be executed.我还尝试将“CMD sleep 60”等添加到 Dockerfile 本身,但这些命令似乎没有被执行。
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:编辑:这是我要运行的 Compose 文件:
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.它工作正常如果我在 OS X 下使用 docker-compose 开始,但如果我在 Ubuntu 16.04 下尝试相同的操作,它会给我上面的错误消息。
If I try the approach with the Dockerfile, the Dockerfile looks like this:如果我尝试使用 Dockerfile 的方法,则 Dockerfile 看起来像这样:
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.编辑 2:我必须纠正自己,结果发现它与 Dockerfile 和 docker-compose.yml 是相同的问题:每次我将“CMD ...”添加到 Z3254677A7917C6C01F55212F8...文件,我得到了无效字符的上述错误。 If I remove both commands, it works flawlessly.
如果我删除这两个命令,它会完美运行。
To keep a container running when you start it with docker-compose
, use the following command要在使用
docker-compose
启动容器时保持容器运行,请使用以下命令
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.在上面的命令中,最后一部分应该从字面上包含
anything
,并且假设这样的文件不存在于容器中,而是使用-F
选项(大写-F
不要与-f
混淆,相比之下,它会终止如果找不到文件,则立即使用) tail
命令将永远等待文件出现anything
。 A forever waiting process is basically what we need.一个永远等待的过程基本上就是我们所需要的。
So your docker-compose.yml becomes所以你的 docker-compose.yml 变成
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您可以使用以下命令运行 shell 以进入容器
docker exec -i -t composename_my-test_1 bash
where composename
is the name that docker-compose
prepends to your containers.其中
composename
是composename
docker-compose
预先添加到您的容器的名称。
You can use tty
configuration option.您可以使用
tty
配置选项。
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;注意:如果你在Dockerfile中使用Dockerfile作为镜像和
CMD
,这个选项将不起作用; however, you can use the entrypoint
option in the compose file which clears the CMD
from the Dockerfile.但是,您可以在撰写文件中使用
entrypoint
选项,该选项可从 Dockerfile 中清除CMD
。
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.根据@aanand 于 2015 年 8 月 26 日在 GitHub上的评论,可以在 docker -compose 中使用
tail -f /dev/null
来保持容器运行。
docker-compose.yml example docker-compose.yml 示例
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.选择这个选项的唯一原因是它在 GitHub 上获得了很多赞,但投票最高的答案并不意味着它是最佳答案。 The second reason was a pragmatic one as issues had to be solved as soon as possible due to deadlines.
第二个原因是务实的,因为由于截止日期,必须尽快解决问题。
docker-compose.yml
docker-compose.yml
的文件version: "3"
services:
ubuntu:
image: ubuntu:latest
tty: true
docker-compose up -d
from the terminaldocker-compose up -d
docker ps
to get the container id or namedocker ps
以获取容器 id 或名称docker inspect $container_id
docker inspect $container_id
docker-compose exec ubuntu /bin/bash
or docker-compose exec ubuntu /bin/sh
docker-compose exec ubuntu /bin/bash
或docker-compose exec ubuntu /bin/sh
的 bash shelldocker-compose down
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.这是一个小的 bash 脚本(
my-docker-shell.sh
),用于创建my-docker-shell.sh
compose 文件,运行容器,登录到容器,然后最后在您注销时清理 docker 容器和 docker compose 文件。
#!/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
在 Dockerfile 中,您可以使用以下命令:
{CMD sleep infinity}
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.正如评论者所说,我们必须查看有问题的 Dockerfile 才能为您提供完整的答案,但这是一个非常常见的错误。 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.
这可能是您在非 Docker 情况下运行的命令,但在 Dockerfile 中这样做是错误的。 For instance, if what you're running is typically defined as a system service, you might use something like "systemctl start".
例如,如果您正在运行的内容通常被定义为系统服务,您可能会使用“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.
您必须在前台运行该进程,因此整个进程将被阻塞。
I have been struggling in this problem half of the day.我在这个问题上苦苦挣扎了半天。 There are many answers here, but I think it is not clear enough.
这里有很多答案,但我认为还不够清楚。
There are two ways, but it can also be said that there is only one, which is running a Blocking processes
in background.有两种方式,但也可以说只有一种,就是在后台运行一个
Blocking processes
。
This first method is using COMMAND
:第一种方法是使用
COMMAND
:
version: '3'
services:
some-app:
command: ["some block command"]
you can put some block command like sleep infinity
, tail -f /dev/null
, watch anything
, while true
...您可以放置一些块命令,例如
sleep infinity
, tail -f /dev/null
, watch anything
, while true
...
Here I recommend sleep infinity
.这里我推荐
sleep infinity
。
The second method is using tty=true
, and the command could be /bin/bash
.第二种方法是使用
tty=true
,命令可以是/bin/bash
。
services:
ubuntu:
image: ubuntu:latest
tty: true
command: "/bin/bash"
Since bash is running with tty, it will keep running background, you can put some other block commands as well.由于 bash 是用 tty 运行的,所以它会一直在后台运行,你也可以放一些其他的块命令。
Be careful , you still need a command call some a shell, and if you want to run some other command, you must pull a shell at the end.注意,你仍然需要一个命令调用一些 shell,如果你想运行一些其他命令,你必须在最后拉一个 shell。
command: /bin/bash -c "/root/.init-service && /bin/bash"
As you can see, all you need a is blocking command.如您所见,您所需要的只是阻塞命令。
Just a quick note只是一个快速的笔记
I have tested single image based on golang
, so when I call docker-compose down
here what I get:我已经测试了基于
golang
单个图像,所以当我在这里调用golang
docker-compose down
,我得到了:
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
Some people here write about overwriting the entrypoint
so that the command
can also have its effect.这里有些人写到覆盖
entrypoint
以便command
也能发挥作用。 But no one gives an example.但是没有人举例。 I then:
然后我:
docker-compose.yml
: 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.我不确定此时是否需要
tty
。 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.没有
entrypoint
它对我不起作用,因为然后command
无效。 So I guess for this solution tty
is optional.所以我想这个解决方案
tty
是可选的。
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
.要了解启动时执行的命令,只需阅读
command
前的entrypoint
(用空格连接): /usr/bin/tail -f /dev/null
。
I'm late to the party, but you can simply use: stdin_open: true
我迟到了,但你可以简单地使用:
stdin_open: true
version: '2'
services:
my-test:
image: ubuntu
stdin_open: true
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.
在用于 compose 的映像的 Dockerfile 中,我指定基本映像应为 ubuntu:latest,但我之前自己创建了一个名为 ubuntu 的映像,但该映像不起作用。 So I did not use the original ubuntu image but rather a corrupt version of my own image also called ubuntu.
所以我没有使用原始的 ubuntu 映像,而是使用了我自己的映像的损坏版本,也称为 ubuntu。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.