在容器启动时启动一个进程
当你在开发容器中工作时,你可能希望在每次容器启动时执行一个命令或启动某些东西。最简单的方法是使用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
很方便,允许你在源代码树中执行命令,但你也可以使用自定义的ENTRYPOINT或CMD将这些步骤添加到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,请确保您的容器没有设置 entrypoint 或 command 属性。