Docker Compose 保持容器运行

Posted

技术标签:

【中文标题】Docker Compose 保持容器运行【英文标题】:Docker Compose keep container running 【发布时间】:2016-11-27 13:20:58 【问题描述】:

我想用 docker-compose 启动一个服务并保持容器运行,这样我就可以通过 'docker inspect' 获取它的 IP 地址。但是,容器总是在启动后立即退出。

我尝试在 docker-compose.yml 中添加“command: ["sleep", "60"]" 和其他内容,但是每当我添加带有“command:...”的行时,我都无法调用“docker-撰写”,因为我将收到消息“无法启动容器.....系统错误:无效字符'k'正在寻找值的开头”

我还尝试在 Dockerfile 本身中添加“CMD sleep 60”等,但这些命令似乎没有被执行。

有没有一种简单的方法可以让容器保持活力或解决我的一个问题?

编辑: 这是我要运行的 Compose 文件:

version: '2'
services:
  my-test:
    image: ubuntu
    command: bash -c "while true; do echo hello; sleep 2; done"

如果我在 OS X 下使用 docker-compose 启动它,它工作正常,但如果我在 Ubuntu 16.04 下尝试相同,它会给我上面的错误消息。

如果我尝试使用 Dockerfile 的方法,Dockerfile 看起来像这样:

FROM ubuntu:latest
CMD ["sleep", "60"]

似乎什么都没做

编辑 2: 我必须纠正自己,结果发现 Dockerfile 和 docker-compose.yml 存在同样的问题: 每次我将“CMD ...”添加到 Dockerfile 或将“command ...”添加到撰写文件时,我都会遇到无效字符的错误。如果我删除这两个命令,它会完美运行。

【问题讨论】:

请包含 docker-compose.yml、Dockerfile 以及您尝试调试的任何脚本。 相关讨论,感兴趣的朋友:Development workflow for server and client using Docker Compose? 【参考方案1】:

要在使用docker-compose 启动容器时保持容器运行,请使用以下命令

command: tail -F anything

在上面的命令中,最后一部分anything 应该包含在字面上,并且假设容器中不存在这样的文件,但使用-F 选项(大写-F 不要与-f 相反,如果找不到文件,则会立即终止)tail 命令将永远等待文件 anything 出现。基本上我们需要一个永远等待的过程。

所以你的 docker-compose.yml 变成了

version: '2'
services:
  my-test:
    image: ubuntu
    command: tail -F anything

您可以使用以下命令运行 shell 进入容器

docker exec -i -t composename_my-test_1 bash

其中composenamedocker-compose 附加到您的容器的名称。

【讨论】:

完成后如何停止容器?是否有 Ctrl+C、Ctrl+Z 类型的命令?现在我必须关闭终端才能退出。 如果你在容器内,你可以输入exit 回到你的主机。如果您在主机上,则可以使用 Docker (docker stop composename_my-test_1) 或 Docker Compose (docker-compose stop) 停止容器。 @Alexis.Rolland 如果您愿意提出一个新的 SO 问题并分享更多详细信息,那么我很乐意看一看。我的猜测是你的错误与你的一个容器的内部有关,而不是 Docker 或你的主机操作系统的问题。 @mac10688 如果您附加的容器会话中没有提示,请尝试 ctrl-d 分离 /dev/null 对于尾部命令参考的anything 会更好。 ***.com/a/48732671/248616【参考方案2】:

您可以使用tty 配置选项。

version: '3'

services:
  app:
    image: node:8
    tty: true           # <-- This option

注意:如果你使用 Dockerfile 作为镜像并且在 Dockerfile 中使用CMD,这个选项将不起作用;但是,您可以在 compose 文件中使用 entrypoint 选项,从 Dockerfile 中清除 CMD

【讨论】:

这行得通,而且似乎没有tail -f /dev/null 那么老套。有了这个,我可以运行一个容器化的开发环境,通过docker-compose up附加一个postgres数据库,并使用docker exec通过另一个终端运行一个shell。 虽然目前没有很好的记录。这是一个官方选项,将达到与tail -f /dev/nulltail -f anything 相同的效果,请参见此处:docs.docker.com/compose/compose-file @ABMRuman & Psiloc,仅当您不在 docker-compose.yml 文件中使用“命令”时才有效。使用“命令”时,您需要另一个 hack - 因此 tail -F hack 非常适合这里。 如果你在dockerfile中使用入口点,这一定是最好的答案。 对我不起作用,容器仍然死机。如果我在我的入口点 bash 脚本中添加 tail -F /dev/null 它可以工作,但是当我只想在容器启动时运行一些初始命令时,依赖那个 bash 脚本是很奇怪的。【参考方案3】:

基于the comment of @aanand on GitHub Aug 26, 2015,可以在docker-compose中使用tail -f /dev/null来保持容器运行。

docker-compose.yml 示例

version: '3'
services:
  some-app:
    command: tail -f /dev/null

为什么是这个命令?

选择此选项的唯一原因是它在 GitHub 上获得了很多赞,但投票最高的答案并不意味着它是最佳答案。第二个原因是务实的,因为由于截止日期,问题必须尽快解决。

【讨论】:

为什么是这个命令?是什么让它比其他人更好?在我的情况下,刚开始一个 bash 也可以做到这一点...... @N4ppeL 好问题。我选择这个选项的唯一原因是它在 github 上获得了很多赞,但投票最高的答案并不意味着它是最佳答案。第二个原因是务实的,因为由于截止日期,我必须尽快解决问题。【参考方案4】: 创建一个名为docker-compose.yml的文件 将以下内容添加到文件中
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
留在同一目录,从终端运行docker-compose up -d 运行 docker ps 获取容器 ID 或名称 你可以运行docker inspect $container_id 您可以进入容器并获得运行docker-compose exec ubuntu /bin/bashdocker-compose exec ubuntu /bin/sh 的bash shell 完成后,确保您在容器外并运行docker-compose down

这是一个小 bash 脚本 (my-docker-shell.sh),用于创建 docker 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

【讨论】:

虽然这不是问题的实际答案,但我发现它非常有价值!我进一步为这种方法使用了全局 bashrc 函数:gist.github.com/loopmode/4d59a4e9a0a2ffacaec2dd14db4ae8bd【参考方案5】:

在 Dockerfile 中你可以使用命令:

CMD sleep infinity

【讨论】:

【参考方案6】:

这里有些人写了关于覆盖entrypoint 以便command 也可以发挥作用。但是没有人举一个例子。然后我:

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

# ...

我不确定此时是否需要tty。做两次更好吗?就我而言,它没有任何伤害并且运行良好。没有entrypoint 它对我不起作用,因为那时command 没有效果。所以我猜这个解决方案tty 是可选的。

要了解启动时执行的命令,只需阅读command 之前的entrypoint(与空格连接):/usr/bin/tail -f /dev/null

【讨论】:

【参考方案7】:

正如评论者所说,我们必须查看有问题的 Dockerfile 才能给您一个完整的答案,但这是一个非常常见的错误。我几乎可以保证您尝试运行的命令正在启动后台进程。这可能是您在非 Docker 情况下运行的命令,但在 Dockerfile 中执行此操作是错误的。例如,如果您正在运行的通常被定义为系统服务,您可能会使用“systemctl start”之类的东西。这将在后台启动该过程,这是行不通的。你必须在前台运行进程,所以整个进程都会阻塞。

【讨论】:

【参考方案8】:

只是一个简短的说明

我已经基于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.

我的系统信息:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659

【讨论】:

【参考方案9】:

我迟到了,但你可以简单地使用:stdin_open: true

version: '2'
services:
  my-test:
    image: ubuntu
    stdin_open: true

【讨论】:

【参考方案10】:

好的,我发现了我的错误。在用于 compose 的图像的 Dockerfile 中,我指定基础图像应该是 ubuntu:latest,但我之前自己创建了一个名为 ubuntu 的图像,但该图像不起作用。所以我没有使用原始的 ubuntu 映像,而是使用我自己的映像的损坏版本,也称为 ubuntu。

【讨论】:

以上是关于Docker Compose 保持容器运行的主要内容,如果未能解决你的问题,请参考以下文章

在 gitlab ci 中查找在 docker-compose 中运行的容器的 url/ip

保持 Redis 数据在 Docker 容器中的 docker-compose down 和 up 之间保持活跃

从不同的docker-compose从一个容器连接到另一个容器[重复]

Docker Compose with Rails docker-compose up 失败

Zuul 网关无法连接到 Docker-Compose 下的 Eureka 服务注册表

使用 docker-compose up 运行时如何优雅地停止 Dockerized Python ROS2 节点?