简体   繁体   English

Docker 编写保持容器运行

[英]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.其中composenamecomposename 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.第二个原因是务实的,因为由于截止日期,必须尽快解决问题。

  • Create a file called docker-compose.yml创建一个名为docker-compose.yml的文件
  • Add the following to the file将以下内容添加到文件中
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • Staying in the same directory, run docker-compose up -d from the terminal留在同一目录中,从终端运行docker-compose up -d
  • Run docker ps to get the container id or name运行docker ps以获取容器 id 或名称
  • You can run docker inspect $container_id你可以运行docker inspect $container_id
  • You can enter the container and get a bash shell running docker-compose exec ubuntu /bin/bash or docker-compose exec ubuntu /bin/sh您可以进入容器并获取运行docker-compose exec ubuntu /bin/bashdocker-compose exec ubuntu /bin/sh的 bash shell
  • When done, make sure you are outside the container and run docker-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 infinitytail -f /dev/nullwatch anythingwhile 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM