Compose常见问题
docker compose
和 docker-compose
之间有什么区别?
Docker Compose命令行二进制文件的第一个版本于2014年发布。它使用Python编写,并通过 docker-compose
调用。通常,Compose V1项目在 compose.yaml 文件中包含一个顶级的 version 元素,其值范围从2.0到3.8,这些值引用特定的文件格式。
Docker Compose命令行二进制文件的第二个版本于2020年宣布,使用Go编写,并通过 docker compose
调用。Compose V2忽略 compose.yaml 文件中的顶级 version 元素。
更多信息,请参阅Compose的历史与发展。
up
、run
和 start
有什么区别?
通常,你会使用 docker compose up
。使用 up
来启动或重启 compose.yaml
中定义的所有服务。在默认的“附加”(attached)模式下,你会看到所有容器的所有日志。在“分离”(detached)模式 (-d
) 下,Compose在启动容器后退出,但容器会继续在后台运行。
docker compose run
命令用于运行“一次性”或“即时”任务。它需要指定你想运行的服务名称,并且只启动被运行服务依赖的服务容器。使用 run
可以运行测试或执行管理任务,例如从数据卷容器中删除或向其添加数据。run
命令的行为类似于 docker run -ti
,因为它会打开一个交互式终端连接到容器,并返回与容器中进程退出状态匹配的退出状态。
docker compose start
命令仅用于重启先前已创建但已停止的容器。它从不创建新容器。
为什么我的服务需要10秒才能重新创建或停止?
docker compose stop
命令通过发送 SIGTERM
来尝试停止容器。然后它会等待默认的10秒超时。超时后,会向容器发送 SIGKILL
以强制杀死它。如果你遇到了这个超时,意味着你的容器在收到 SIGTERM
信号时没有正常关闭。
关于容器中进程处理信号的问题,已经有很多文章进行了阐述。
要解决此问题,请尝试以下方法:
确保在 Dockerfile 中使用
CMD
和ENTRYPOINT
的 exec 格式。例如,使用
["program", "arg1", "arg2"]
而不是"program arg1 arg2"
。使用字符串格式会导致 Docker 使用bash
运行你的进程,而bash
无法正确处理信号。Compose 总是使用 JSON 格式,因此如果你在 Compose 文件中覆盖了 command 或 entrypoint,不必担心。如果可能,修改你正在运行的应用程序,为其添加一个显式的
SIGTERM
信号处理程序。将
stop_signal
设置为应用程序知道如何处理的信号。services: web: build: . stop_signal: SIGINT
如果你无法修改应用程序,可以将应用程序封装在一个轻量级的init系统(如 s6) 或信号代理(如 dumb-init 或 tini)。这些封装程序都可以正确处理
SIGTERM
。
如何在同一主机上运行Compose文件的多个副本?
Compose 使用项目名称为其所有容器和其他资源创建唯一标识符。要运行一个项目的多个副本,可以使用 -p
命令行选项或 COMPOSE_PROJECT_NAME
环境变量设置一个自定义项目名称。
我的Compose文件可以使用JSON而不是YAML吗?
是的。YAML 是 JSON 的超集,因此任何JSON文件都应该是有效的YAML。要在Compose中使用JSON文件,需要指定文件名,例如:
$ docker compose -f docker-compose.json up
我应该使用 COPY
/ADD
还是卷来包含我的代码?
你可以使用 Dockerfile 中的 COPY
或 ADD
指令将代码添加到镜像中。这在你需要将代码与 Docker 镜像一起迁移时很有用,例如将代码发送到其他环境(生产、CI 等)时。
如果你想在开发代码时立即看到修改的效果(例如你的服务器支持热代码重载或实时重载),可以使用 volume
。
有些情况下你可能想同时使用这两种方法。你可以使用 COPY
将代码包含在镜像中,然后在开发期间使用 Compose 文件中的 volume
来包含宿主机的代码。卷会覆盖镜像中的目录内容。