在容器启动时启动一个进程

当你在开发容器中工作时,你可能希望在每次容器启动时执行一个命令或启动某些东西。最简单的方法是使用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很方便,允许你在源代码树中执行命令,但你也可以使用自定义的ENTRYPOINTCMD将这些步骤添加到Dockerfile中。

当在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 属性。