尝试以扩展 VS Code 中的代理模式!

当容器启动时启动进程

当你在开发容器中工作时,你可能希望在每次容器启动时执行一个命令或启动一些东西。最简单的方法是使用 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 属性。