Docker Compose保持容器运行


101

我想使用docker-compose启动服务并保持容器运行,以便我可以通过“ docker inspect”获取其IP地址。但是,容器始终在启动后立即退出。

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

我还尝试向Dockerfile本身添加“ CMD sleep 60”和诸如此类的东西,但是这些命令似乎并未执行。

有没有一种简单的方法来保持容器的寿命或解决我的问题之一?

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

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的相同问题:每次我向Dockerfile添加“ CMD ...”或向其中添加“ command ...”撰写文件时,出现无效字符并出现上述错误。如果我删除了这两个命令,它会完美地工作。


1
请包括docker-compose.yml,Dockerfile以及您要调试的所有脚本。
BMitch

针对感兴趣的人员的相关讨论:使用Docker Compose的服务器和客户端开发工作流程?

Answers:


128

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

command: tail -F anything

所以你的docker-compose.yml变成

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

您可以使用以下命令运行外壳程序以进入容器

docker exec -i -t composename_my-test_1 bash

容器前面composename的名称在哪里docker-compose


1
完成后如何停止容器?是否有Ctrl + C,Ctrl + Z类型的命令?现在我必须关闭终端才能退出。
mac10688 '18

如果您在容器内,则可以键入exit以返回到主机。如果您在主机上,则可以使用Docker(docker stop composename_my-test_1)或Docker Compose(docker-compose stop)停止容器。
Nick Settje

2
@ Alexis.Rolland如果您愿意提出一个新的SO问题并分享更多详细信息,那么我将非常乐意看一下。我的猜测是,您的错误与您其中一个容器的内部有关,而不是与Docker或您的主机操作系统有关。
尼克·塞捷

1
@ mac10688如果在您连接的容器会话没有任何提示,然后尝试按ctrl-d离开
斯塔克

7
/dev/nullanything对于尾部命令参考会更好。stackoverflow.com/a/48732671/248616
Nam G VU

90

您可以使用tty配置选项。

version: '3'

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

注意:如果您将Dockerfile用于映像和CMDDockerfile中,则此选项将不起作用;但是,您可以entrypoint在撰写文件中使用该选项,以CMD从Dockerfile中清除。


9
这行得通,而且似乎不如hacky tail -f /dev/null。有了这个,我就可以运行一个容器化的dev环境,docker-compose up并通过连接一个postgres数据库,并使用来通过另一个终端运行一个shell docker exec
Psiloc

1
虽然目前尚无据可查。这是一个官方选项,将实现与tail -f /dev/null或相同的效果tail -f anything,请参阅此处:docs.docker.com/compose/compose-file
b01

2
@ABMRuman&Psiloc,仅当您在docker-compose.yml文件中不使用“命令”时才起作用。当使用“命令”时,您需要另一个技巧-因此尾巴-F技巧非常适合这里。
asafel

1
如果您在dockerfile中使用入口点,这必须是最佳答案。
DDKV587

54

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

docker-compose.yml示例

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

为什么使用此命令?

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


2
为什么是这个命令?是什么让它比其他人更好?以我为例,刚开始
击打

@ N4ppeL好问题。我选择此选项的唯一原因是它在github上获得了很多好评,但是投票率最高的答案并不意味着它是最佳答案。第二个原因是务实的原因,由于截止日期我不得不尽快解决该问题。
030

17
  • 创建一个名为 docker-compose.yml
  • 将以下内容添加到文件中
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • 停留在同一目录中,docker-compose up -d从终端运行
  • 运行docker ps以获取容器ID或名称
  • 你可以跑 docker inspect $container_id
  • 您可以进入容器并运行bash shelldocker-compose exec ubuntu /bin/bashdocker-compose exec ubuntu /bin/sh
  • 完成后,确保您在容器外面并运行 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

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

8

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

{CMD sleep infinity}

2

正如评论者所述,我们必须查看有问题的Dockerfile才能为您提供完整的答案,但这是一个非常常见的错误。我可以保证您要运行的命令正在启动后台进程。这可能是您在非Docker情况下运行的命令,但是在Dockerfile中执行此操作是错误的。例如,如果通常将正在运行的内容定义为系统服务,则可以使用“ systemctl start”之类的东西。那将在后台启动该过程,将无法正常工作。您必须在前台运行该进程,因此整个进程将阻塞。


0

只是一个简短的说明

我已经测试了基于的单张图片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

-3

好吧,我发现了我的错误。在用于镜像的Dockerfile中,我指定了基本镜像应为ubuntu:latest,但是我之前自己创建了一个名为ubuntu的镜像,该镜像无法正常工作。因此,我没有使用原始的ubuntu映像,而是使用了自己的映像(也称为ubuntu)的损坏版本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.