关于 Docker Compose 的常见问题
docker compose 与 docker-compose 有何区别?
Docker Compose 命令行二进制文件的版本一于 2014 年首次发布。它用 Python 编写,并通过 docker-compose 调用。通常,Compose v1 项目在 compose.yaml 文件中包含一个顶级版本元素,其值范围从 2.0 到 3.8,指代特定的文件格式。
Docker Compose 命令行二进制文件的版本二于 2020 年宣布,它用 Go 编写,并通过 docker compose 调用。Compose v2 忽略 compose.yaml 文件中的版本顶级元素。
欲了解更多信息,请参阅 Compose 的历史与发展。
up、run 和 start 有何区别?
通常,你会使用 docker compose up。使用 up 来启动或重新启动 compose.yaml 中定义的所有服务。在默认的“附加”模式下,你会看到所有容器的所有日志。在“分离”模式(-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 文件中覆盖了命令或入口点,请不用担心。如果可能,修改你正在运行的应用程序,为
SIGTERM添加一个显式信号处理器。将
stop_signal设置为应用程序知道如何处理的信号。services: web: build: . stop_signal: SIGINT如果无法修改应用程序,请将应用程序包装在一个轻量级 init 系统(如 s6)或信号代理(如 dumb-init 或 tini)中。这些包装器都可以妥善处理
SIGTERM。
如何在同一主机上运行多个 Compose 文件副本?
Compose 使用项目名称为项目的所有容器和其他资源创建唯一的标识符。要运行项目的多个副本,请使用 -p 命令行选项或 COMPOSE_PROJECT_NAME 环境变量 设置自定义项目名称。
我可以使用 JSON 而不是 YAML 作为我的 Compose 文件吗?
是的。YAML 是 JSON 的超集,因此任何 JSON 文件都应该是有效的 YAML。要将 JSON 文件与 Compose 一起使用,请指定要使用的文件名,例如:
$ docker compose -f compose.json up
我应该使用 COPY/ADD 还是卷来包含我的代码?
您可以使用 Dockerfile 中的 COPY 或 ADD 指令将代码添加到镜像中。这在您需要将代码与 Docker 镜像一起重新定位时很有用,例如在将代码发送到其他环境(生产、CI 等)时。
如果您想对代码进行更改并立即看到它们反映出来,请使用 volume,例如在开发代码并且您的服务器支持热代码重载或实时重载时。
在某些情况下,您可能希望两者都使用。您可以让镜像使用 COPY 包含代码,并在 Compose 文件中使用 volume 在开发期间包含来自主机的代码。卷会覆盖镜像的目录内容。