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
其中composename
是docker-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/null
或tail -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/bash
或docker-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 失败