保持集装箱运行

我想启动一个服务与码头组成,并保持容器运行,这样我可以得到其 IP 地址通过’码头检查’。但是,容器始终在启动后立即退出。

我试图添加“ command: [“ sleep”,“60”]”和其他东西到 docker-compest 中。Yml,但是每当我添加带有“ command: ...”的行时,我不能调用“ docker-compose up”,因为我将得到消息“ Can not start Container... ...”。系统错误: 无效字符‘ k’正在查找值的开头

我还尝试将“ CMD sleep 60”和诸如此类的命令添加到 Dockerfile 本身,但这些命令似乎不会被执行。

有没有一个简单的方法来保持容器活着或解决我的问题之一?

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

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

它的工作正常如果我开始这与 docker-撰写在 OS X 下,但如果我尝试同样在 Ubuntu 16.04下,它给我上述错误消息。

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

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

看起来没什么用

编辑2: 我不得不纠正自己,原来 Dockerfile 和 docker 也有同样的问题: 每次将“ CMD...”添加到 Dockerfile 或将“ command...”添加到撰写文件时,都会得到上面的错误,其中包含无效字符。如果我删除这两个命令,它会完美地工作。

178878 次浏览

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

好吧,我找到我的错误了。在用于组合的图像的 Dockerfile 中,我指定基本图像应该是 ubuntu: last,但是我之前自己创建了一个名为 ubuntu 的图像,这个图像不能工作。因此,我没有使用原始的 ubuntu 图像,而是使用了我自己的图像的一个腐败版本,也叫做 ubuntu。

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

command: tail -F anything

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

所以你的码头作曲。 yml 成为

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

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

docker exec -i -t composename_my-test_1 bash

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

在 Dockerfile 中,您可以使用以下命令:

{CMD sleep infinity}

基于 2015年8月26日@aanand 在 GitHub 上的评论,可以在 docker-compose 中使用 tail -f /dev/null来保持容器运行。

Docker-comse.yml 示例

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

为什么是这个命令?

选择这个选项的唯一原因是它在 GitHub 上得到了很多赞誉,但是得票最多的答案并不意味着它就是最好的答案。第二个原因是务实的,因为由于最后期限的关系,必须尽快解决问题。

可以使用 tty配置选项。

version: '3'


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


注意: 如果你在 Dockerfile 使用 Dockerfile 处理图像和 CMD,这个选项是不起作用的,但是你可以使用 comose 文件中的 entrypoint选项来清除 Dockerfile 中的 CMD

  • 创建一个名为 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 组合文件,运行容器,登录到容器,然后在注销时清理 docker 容器和 docker 组合文件。

#!/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

就说一句

我已经测试了基于 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

有些人在这里写的覆盖 entrypoint,使 command也可以有其效果。但没人举例说明。然后我:

返回文章页面

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

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

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

你只需要封锁指令。

这个问题我已经纠结了半天了。 。下面有许多答案,但不够清楚。没有人说为什么。

总之,有两种方法,但也可以说只有一种,在后台运行 Blocking processes


第一个是使用 COMMAND:

version: '3'
services:
some-app:
command: ["some block command"]

把一些块命令,如 sleep infinitytail -f /dev/nullwatch anythingwhile true..。

这里我推荐 sleep infinity


第二种是启用 tty=true,然后在命令中打开一个 shell,如 /bin/bash

services:
ubuntu:
image: ubuntu:latest
tty: true
command: "/bin/bash"

由于 tty 是启用的,所以 bash 将继续运行后台,如果需要的话,您可以在它之前放置一些其他块命令。

小心 ,必须在末尾执行 shell 命令,如

command: /bin/bash -c "/root/.init-service && /bin/bash"

正如您所看到的,所有您需要的就是阻塞命令。