Cloud Workstations 提供的预配置基础映像仅包含一个极简环境,其中包含 IDE、基本 Linux 终端和语言工具以及 sshd 服务器。为了加快特定开发用例的环境设置,您可以创建自定义容器映像,这些映像可扩展这些基础映像以预安装工具和依赖项,并运行自动化脚本。
对于自定义容器映像,我们建议您设置一个流水线,以便在 Cloud Workstations 基础映像更新时自动重新构建这些映像,此外,还应运行 Artifact Analysis 等容器扫描工具来检查您添加的任何其他依赖项。您有责任维护和更新添加到自定义映像中的自定义软件包和依赖项。
准备工作
您需要一台机器,其中包含用于构建容器映像(例如 Docker)的工具,以及用于使用 Google Cloud CLI 将映像推送到 Artifact Registry 的工具。您可以使用 Cloud Workstations 或 Cloud Shell Editor 来执行这些步骤,因为这些工具已预安装在其中。
从受支持的基础映像列表中选择要使用的基础映像,例如
us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest。或者,您可以按照使用您自己的容器映像中的说明使用自己的容器映像或外部容器映像。
创建一个文件夹(例如
CUSTOM_IMAGE_FOLDER),并在该文件夹内创建一个 Dockerfile,用于扩展所选的基础映像,如以下示例所示。
Cloud Workstations 基础映像结构
Cloud Workstations 基础映像具有以下定义的结构:
- 基础映像入口点文件设置为
/google/scripts/entrypoint.sh。 在启动时,基础映像会按字典顺序运行
/etc/workstation-startup.d/*下的文件,以初始化工作站环境。文件及其行为如下:
000_configure-docker.sh:在工作站内配置和运行 Docker。010_add-user.sh:在 Cloud Workstations 中创建默认用户。由于永久性磁盘是动态附加到容器的,因此必须在工作站启动时添加用户,而不是在 Dockerfile 中添加。
020_start-sshd.sh:在容器中启动sshd服务。030_customize-environment.sh:以user的身份执行/home/user/.workstation/customize_environment。110_start-$IDE.sh:启动映像的 IDE。
Cloud Workstations 会将 Docker 映像存储在主目录中的
/home/.docker_data中,以便在会话之间保留映像。
如需在工作站启动期间添加其他功能,请将脚本添加到 /etc/workstation-startup.d/ 目录中:
此目录中的脚本默认以 root 身份运行。如需以其他用户身份执行脚本,请使用
runuser命令。由于脚本按字典顺序执行,因此我们建议您为脚本添加一个大于 200 的三位数前缀。
或者,如果您不想扩展工作站映像,可以在主目录中创建 customize_environment 脚本。
主目录修改
当工作站配置指定了永久性主目录(这是默认行为)时,支持主目录的永久性磁盘会在运行时动态附加到容器。此流程会覆盖在容器映像构建时对 /home 目录所做的修改。
如需保留更新,请在容器运行时修改 /home 目录,方法是在 /etc/workstation-startup.d 目录中添加脚本,或在 /etc/profile.d 目录中添加用户专用配置。为了加快此过程,请考虑将设置脚本作为后台进程运行(在命令末尾添加“&”符号 [&]),以避免阻塞容器启动。
以下是一些应移至容器运行时的 build 时配置示例:
- 按用户进行
git配置 - 克隆到主目录中的
git代码库 - 直接用户配置,例如将文件放置在
$HOME/.config目录中 - 创建用户
用户创建和修改
由于永久性磁盘在运行时动态附加到容器,因此必须在工作站启动时添加用户,而不能在 Dockerfile 中添加。如需修改或创建其他用户,我们建议您更新 /etc/workstation-startup.d/010_add-user.sh,或创建在启动时执行的自定义脚本。
此外,您还可以通过更新 /etc/profile.d 中的文件来修改用户的默认 bash 配置文件。
更新预配置的安全 APT 密钥
Cloud Workstations 基础映像预安装了许多通过 Secure APT 从各种第三方代码库获取的工具。在安装过程中,使用 gpg 导入代码库所有者提供的公钥,并将其放置在 /usr/share/keyrings/ 下的各个文件中。这些文件是从 /etc/apt/sources.list.d/ 下的相应 list 文件引用的。
这样,apt 就可以在与给定代码库互动时验证其完整性。
有时,第三方代码库所有者可能会决定更改用于验证其代码库完整性的公钥,这会导致 apt 在与其互动时显示错误。如需解决此潜在问题,您可以使用 /google/scripts/refresh-preinstalled-apt-keys.sh,该工具可获取预安装的公钥的最新版本并重新导入它们。
您也可以在运行 apt-get update 之前,直接在自定义 Dockerfile 中运行此脚本:
# Refresh the preinstalled APT keys
RUN /google/scripts/refresh-preinstalled-apt-keys.sh
RUN apt-get update
列出已安装的 IDE 版本
部分 Cloud Workstations 基本映像预安装了 IDE。为方便起见,请参阅随附的 /google/scripts/preinstalled-ide-versions.sh 脚本,该脚本会列出映像中安装的 IDE 的名称和版本信息。
关闭 sudo root 权限
默认工作站用户在这些容器中拥有 sudo root 访问权限。如需关闭对 Docker 容器的 root 访问权限,请在创建工作站配置时将 CLOUD_WORKSTATIONS_CONFIG_DISABLE_SUDO 环境变量设置为 true。
如需在创建工作站配置时通过 Google Cloud 控制台设置此环境变量,请按以下步骤操作:
- 创建工作站配置时,请完成“基本信息”和“机器配置”的配置。
- 在环境自定义对话框中,展开高级容器选项部分,然后选择环境变量。
- 依次点击添加添加变量。
- 输入
CLOUD_WORKSTATIONS_CONFIG_DISABLE_SUDO和true作为值。
自定义但不扩展映像
为方便起见,所有 Cloud Workstations 基本映像都会检查 /home/user/.workstation/customize_environment 中是否存在可执行文件,如果存在,则在后台以 user 身份运行该文件。这样,您就可以在启动时运行任何脚本或二进制文件。与 .profile 或 .bashrc 不同,此脚本仅在工作站启动时运行一次,而不是每次登录 shell 时运行一次。
由于 customize_environment 脚本以 user 身份运行,因此在编写脚本时,请务必根据需要更新权限。例如,如果您想在工作站每次启动时都安装 Emacs,则 customize_environment 的内容可能类似于以下内容:
#!/bin/bash
sudo apt-get update
sudo apt-get install -y emacs
customize_environment 的执行日志位于容器中的 /var/log/customize_environment,也会写入容器输出日志。成功执行 customize_environment 后,系统会在 /var/run/customize_environment_done 中创建一个文件。由于 customize_environment 与工作站启动并行运行,因此脚本安装的软件包最早可以在工作站启动后不久就可供使用。
防止空闲超时
为方便起见,所有 Cloud Workstations 基础映像都包含一个预安装的脚本,位于 /google/scripts/keep_alive.sh。此脚本会定期发送 keep-alive 消息,从而防止工作站在您运行后台进程而没有直接互动时因空闲超时而关闭。
利用 AI 智能体防止空闲超时
此外,Cloud Workstations 基本映像在 /google/samples/agents/keepalive/ 下包含示例代理配置脚本。借助这些示例配置,您可以在工作站内配置 AI 编码智能体(例如 Claude Code 和 Antigravity CLI),以便在这些智能体积极处理任务时自动保持工作站处于运行状态。当代理完成任务或暂停等待用户输入时,脚本会停止发送 keep-alive 消息,从而允许工作站因不活动而超时。当工作站配置设置为使用工作站挂起(idleAction 设置为 SUSPEND)时,这些配置效果最佳,这样工作站就可以保存内存状态,并在您返回时无缝恢复。
如需详细了解如何设置代理辅助工作流和 keep-alive 钩子,请参阅代理优化开发。
使用您自己的容器映像
您还可以使用自己的容器映像或外部容器映像,前提是这些映像基于 Linux 且在容器启动时运行阻塞进程。
设置 Dockerfile 时,ENTRYPOINT 指令必须运行阻塞进程(例如 sleep infinity),以便容器继续运行,而不是立即退出。或者,您可以在工作站配置中设置 config.container.args 字段以指定阻塞进程。
使用您自己的容器映像时,请注意以下事项:
Cloud Workstations 不需要 Cloud Workstations 基本映像中的其他脚本。
不过,您可以查看运行 Cloud Workstations 基础映像的容器内
/etc/workstation-startup.d/目录中的脚本。文件名指明了每个脚本的作用。我们建议您在容器中运行 SSH 服务器。如需了解 Cloud Workstations 如何默认设置此功能,请参阅默认基础映像中的
/etc/workstation-startup.d/020_start-sshd.sh。我们建议您在端口
80上运行默认 IDE 或 Web 服务器。
Google Cloud 提供标准基础映像,您可以使用这些映像来构建完全自定义的容器映像。
扩展 Cloud Workstations 基础映像
在扩展 Cloud Workstations 基础映像以创建工作站环境的自定义映像时,您可以采用以下三种方法:
- 更新
Dockerfile以添加您想要添加的任何其他静态资源。 - 在
/etc/workstation-startup.d/下添加其他可执行文件,以自定义正在运行的容器。此目录下的文件会在容器启动时按字典顺序自动运行,因此您可以在文件名中添加前缀,以便在工作站启动期间的适当时间运行该文件。 - 替换 Dockerfile 中的
ENTRYPOINT以完全自定义容器启动。
自定义 Dockerfile 示例
本部分提供了示例场景和有关创建您自己的 Dockerfile 的说明。
预安装了 emacs 的容器映像
如需创建预安装了 emacs 的容器映像,请运行以下命令:
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest
RUN sudo apt update
RUN sudo apt install -y emacs
包含用户自定义设置的容器映像
如需自定义容器映像,请按以下步骤操作:
在
/etc/workstation-startup.d/*中创建一个在010_add-user.sh之后运行的脚本,例如011_customize-user.sh:#!/bin/bash # Create new group groupadd $GROUP # Add the user to a new group usermod -a -G $GROUP $USERNAME将
$GROUP替换为新群组名称,并将$USERNAME替换为用户的用户名。假设您将脚本命名为
011_customize-user.sh,请在 Dockerfile 中将以下内容添加到映像,并使其可执行:FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest COPY 011_customize-user.sh /etc/workstation-startup.d/ RUN chmod +x /etc/workstation-startup.d/011_customize-user.sh
在 SSH 会话中设置容器环境变量的容器映像
在工作站配置或工作站级别设置的环境变量会通过入口点命令传递给直接子进程。这包括预配置基础映像中的 IDE。不过,SSH 会话不是入口点的子进程,并且未设置这些自定义环境变量。
如需在 SSH 会话中设置这些环境变量,请设置一个自定义容器映像,该映像会将这些环境变量从容器的入口点命令中继到 /etc/environment 文件。
为此,请按以下步骤操作:
在
/etc/workstation-startup.d/*中创建一个在010_add-user.sh之后运行的脚本,例如011_add-ssh-env-variables.sh:#!/bin/bash # echo "CUSTOM_ENV_VAR=$CUSTOM_ENV_VAR" >> /etc/environment将
CUSTOM_ENV_VAR替换为所需的环境变量名称。假设您将脚本命名为
011_add-ssh-env-variables.sh,请在 Dockerfile 中将以下内容添加到映像,并使其可执行:FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest COPY 011_add-ssh-env-variables.sh /etc/workstation-startup.d/ RUN chmod +x /etc/workstation-startup.d/011_add-ssh-env-variables.sh
可为 SSH 会话启用 X11 转发的容器映像
借助 X11 转发,您可以启动远程应用并将应用显示转发到本地机器。
如需创建支持 X11 转发的容器映像,请修改 Cloud Workstations 基础映像提供的 OpenSSH 精灵配置文件 (/etc/ssh/sshd_config),方法是附加 X11Forwarding yes(以允许 X11 转发)和 AddressFamily inet(以确保仅使用 IPv4)。如需详细了解这些关键字,请参阅有关 AddressFamily 和 X11Forwarding 的 OpenBSD 网页。
以下是经过必要修改的 Dockerfile 示例:
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest
# Permit X11 forwarding using only IPv4
RUN cat >> /etc/ssh/sshd_config <<-EOF
AddressFamily inet
X11Forwarding yes
EOF
将 Code OSS for Cloud Workstations 复制到另一个容器映像
借助多阶段构建,您可以在 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础映像,并支持在 build 阶段之间复制制品。如需将 Code OSS for Cloud Workstations 添加到其他容器映像,请使用多阶段构建将应用文件夹 /opt/code-oss 复制到您的映像中。如果您想在容器启动时启动 Cloud Workstations 的 Code OSS,请额外将脚本 /etc/workstation-startup.d/110_start-code-oss.sh 复制到容器中。
以下是一个示例 Dockerfile,用于将 Code OSS 复制到 JetBrains IntelliJ Ultimate 映像中。然后,您可以与任一 IDE 进行互动:
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest as code-oss-image
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/jetbrains-intellij:latest
# Copy Code OSS for Cloud Workstations and startup scripts into our custom image
COPY --from=code-oss-image /opt/code-oss /opt/code-oss
COPY --from=code-oss-image /etc/workstation-startup.d/110_start-code-oss.sh /etc/workstation-startup.d/110_start-code-oss.sh
# Use the existing entrypoint script which will execute all scripts in /etc/workstation-startup.d/
ENTRYPOINT ["/google/scripts/entrypoint.sh"]
在 Code OSS 中预安装了 IDE 扩展程序的容器映像,适用于 Cloud Workstations 中的 Java 开发
如需创建在构建时预安装了 Code OSS 中用于 Java 开发的 Cloud Workstations IDE 扩展程序的容器映像,请运行以下命令:
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest
RUN wget https://open-vsx.org/api/vscjava/vscode-java-debug/0.40.1/file/vscjava.vscode-java-debug-0.40.1.vsix && \
unzip vscjava.vscode-java-debug-0.40.1.vsix "extension/*" &&\
mv extension /opt/code-oss/extensions/java-debug
RUN wget https://open-vsx.org/api/vscjava/vscode-java-dependency/0.19.1/file/vscjava.vscode-java-dependency-0.19.1.vsix && \
unzip vscjava.vscode-java-dependency-0.19.1.vsix "extension/*" &&\
mv