现已推出!阅读 10 月份的新功能和修复。

容器启动时启动进程

在开发容器中工作时,您可能希望每次容器启动时执行命令或启动某些内容。最简单的方法是使用 devcontainer.json 中的 postStartCommand 属性。例如,如果您希望每次连接到容器时运行 yarn install 以保持依赖项更新,则可以添加以下内容:

"postStartCommand": "yarn install"

视频:容器创建时运行 npm install



在其他情况下,您可能希望启动一个进程并保持运行状态。这可以通过使用 nohup 并将进程放入后台使用 & 来完成。例如:

"postStartCommand": "nohup bash -c 'your-command-here &'"

视频:容器启动时运行“npm start”



熟悉 Linux 的用户可能会期望能够使用 systemctl 命令启动和停止由名为 systemd 的东西管理的后台服务。不幸的是,systemd 具有开销,因此通常不使用它在容器中。

在许多情况下,您可以运行其他命令(例如,sshd)。在 Debian/Ubuntu 上,通常在 /etc/init.d 下有您可以直接运行的脚本。

"postStartCommand": "/etc/init.d/ssh start"

这些系统还包含 service 命令,该命令将根据安装内容使用 systemctl/etc/init.d 脚本。

"postStartCommand": "service ssh start"

视频:在容器中启动 SSH 服务

改而将启动命令添加到 Docker 镜像中

虽然 postStartCommand 很方便,并且允许您在源代码树中执行命令,但您也可以将这些步骤添加到 Dockerfile 中,使用自定义的 ENTRYPOINTCMD

devcontainer.json 中引用 Dockerfile 时,将覆盖默认入口点和命令。首先,使用 overrideCommand 属性禁用此行为。

"overrideCommand": false

overrideCommand 属性默认为 true,因为许多镜像如果未指定命令将立即退出。相反,我们需要在我们的 Dockerfile 中处理它。

接下来,考虑这个 Dockerfile:

FROM mcr.microsoft.com/devcontainers/base:1-ubuntu

COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "sleep", "infinity" ]

此处的 CMD 确保容器默认情况下保持运行状态。将启动步骤保留在 ENTRYPOINT 中,允许您在使用 docker run 运行镜像或使用 Docker Compose 时安全地覆盖命令。这将解析为以下内容:

/docker-entrypoint.sh sleep infinity

接下来,创建一个 docker-entrypoint.sh 脚本:

#!/usr/bin/env bash

echo "Hello from our entrypoint!"

exec "$@"

您在此文件中执行的任何内容都将在每次容器启动时触发。但是,重要的是要包含最后一行 exec "$@",因为这将导致我们的示例中命令 sleep infinity 触发。

最后,如果您使用的是 Docker Compose,请确保您的容器未设置 entrypointcommand 属性。