Compose常见问题

docker composedocker-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的历史与发展

uprunstart 有什么区别?

通常,你会使用 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 中使用 CMDENTRYPOINT 的 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-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 还是卷来包含我的代码?

你可以使用 Dockerfile 中的 COPYADD 指令将代码添加到镜像中。这在你需要将代码与 Docker 镜像一起迁移时很有用,例如将代码发送到其他环境(生产、CI 等)时。

如果你想在开发代码时立即看到修改的效果(例如你的服务器支持热代码重载或实时重载),可以使用 volume

有些情况下你可能想同时使用这两种方法。你可以使用 COPY 将代码包含在镜像中,然后在开发期间使用 Compose 文件中的 volume 来包含宿主机的代码。卷会覆盖镜像中的目录内容。

页面选项