Compose 常见问题解答

docker composedocker-compose 之间有什么区别?

Docker Compose 命令行Binaries的第一个版本于 2014 年首次发布。它使用 Python 编写,并通过 docker-compose 调用。通常,Compose V1 项目在 compose.yml 文件中包含一个顶层的 version 元素,其值范围从 2.0 到 3.8,这些值对应特定的文件格式。

Docker Compose 命令行Binaries的第二版于 2020 年发布,采用 Go 语言编写,并通过 docker compose 调用。Compose V2 会忽略 compose.yml 文件中的顶层 version 元素。

如需更多信息,请参阅 Compose 的历史与发展

uprunstart 之间有什么区别?

通常,您希望使用 docker compose up。使用 up 可启动或重启在 compose.yml 中定义的所有服务。在默认的“附加”模式下,您可以看到所有容器的全部日志。在“分离”模式(-d)下,Compose 在启动容器后会退出,但容器会继续在后台运行。

docker compose run 命令用于运行“一次性”或“临时”任务。它需要您想要运行的服务名称,并且仅启动该运行服务所依赖的服务的容器。使用 run 来运行测试或执行管理任务,例如向数据卷容器中添加或删除数据。run 命令的作用类似于 docker run -ti,它会打开一个到容器的交互式终端,并返回与容器中进程退出状态相匹配的退出状态。

docker compose start 命令仅用于重启之前已创建但已停止的容器。它绝不会创建新容器。

为什么我的服务需要 10 秒才能重新创建或停止?

docker compose stop 命令尝试通过发送 SIGTERM 来停止容器。随后,它将等待 默认的 10 秒超时时间。超时后, 会向容器发送 SIGKILL 以强制终止它。如果您正在等待此超时, 这意味着您的容器在收到 SIGTERM 信号时未能正常关闭。

关于容器中 进程处理信号 这一问题,已有大量论述。

要解决此问题,请尝试以下操作:

  • 请确保在 Dockerfile 中使用 CMDENTRYPOINT 的 exec 形式。

    例如,请使用 ["program", "arg1", "arg2"] 而不是 "program arg1 arg2"。 使用字符串形式会导致 Docker 使用 bash 运行您的进程,而该形式无法正确处理信号。Compose 始终使用 JSON 形式,因此如果您在 Compose 文件中覆盖了 command 或 entrypoint,也无需担心。

  • 如果可能,请修改您正在运行的应用程序, 为 SIGTERM 添加一个显式的信号处理程序。

  • stop_signal 设置为应用程序能够处理的信号:

    services:
      web:
        build: .
        stop_signal: SIGINT
  • 如果您无法修改应用程序,请将应用程序封装在一个轻量级的 init 系统(如 s6)或信号代理(如 dumb-inittini)中。这些封装工具中的任何一种都能妥善处理好 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 一起包含,还是使用卷?

您可以使用 COPYADD 指令在 Dockerfile 中将代码添加到镜像中。如果您需要随 Docker 镜像一起迁移代码,例如将代码发送到另一个环境(生产环境、持续集成环境等),这将非常有用。

如果您希望更改代码后立即看到效果(例如在开发代码且服务器支持热代码重载或实时重载时),请使用 volume

可能存在您希望同时使用两者的情况。您可以让镜像通过 COPY 包含代码,并在开发过程中通过 Compose 文件中的 volume 来包含主机上的代码。数据卷将覆盖镜像中的目录内容。