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,该工具可获取预安装的公钥的最新版本并重新导入它们。
列出已安装的 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。此脚本会定期发送保持活动状态消息,从而防止工作站在您运行后台进程而没有直接互动时因空闲超时而关闭。
使用您自己的容器映像
您还可以使用自己的容器映像或外部容器映像,前提是这些映像基于 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 服务器。
扩展 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)。如需详细了解这些关键字,请参阅 OpenBSD 网页上关于 AddressFamily 和 X11Forwarding 的内容。
以下是经过必要修改的 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
将 Cloud Workstations 的 Code OSS 复制到另一个容器映像中
多阶段构建允许您在 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 extension /opt/code-oss/extensions/java-dependency
RUN wget https://open-vsx.org/api/redhat/java/1.6.0/file/redhat.java-1.6.0.vsix && \
unzip redhat.java-1.6.0.vsix "extension/*" &&\
mv extension /opt/code-oss/extensions/redhat-java
RUN wget https://open-vsx.org/api/vscjava/vscode-maven/0.35.2/file/vscjava.vscode-maven-0.35.2.vsix && \
unzip vscjava.vscode-maven-0.35.2.vsix "extension/*" &&\
mv extension /opt/code-oss/extensions/java-maven
RUN wget https://open-vsx.org/api/vscjava/vscode-java-test/0.35.0/file/vscjava.vscode-java-test-0.35.0.vsix && \
unzip vscjava.vscode-java-test-0.35.0.vsix "extension/*" &&\
mv extension /opt/code-oss/extensions/java-test
RUN chmod a+rwx -R /opt/code-oss/extensions/
如果您预安装扩展程序,这些扩展程序会被视为内置扩展程序。
您将无法更新这些扩展程序,并且它们可能不会显示在
扩展程序市场的“已安装”部分中。
不过,您可以搜索
@builtin 来查找内置扩展程序。
在启动时安装扩展程序的另一种方法是运行启动脚本。例如,在 /etc/workstation-startup.d/120_install_extensions.sh 下添加以下启动脚本:
sudo -u user /opt/code-oss/bin/codeoss-cloudworkstations --install-extension vscjava.vscode-java-debug@0.40.1 \
--install-extension vscjava.vscode-java-dependency@0.19.1 \
--install-extension redhat.java@1.6.0 \
--install-extension vscjava.vscode-maven@0.35.2 \
--install-extension vscjava.vscode-java-test@0.35.0
使用此方法,扩展程序会显示在 Extensions Marketplace 中,您可以从那里进行更新。
将 JetBrains IDE 和插件安装到基础映像中
在为工作站配置自定义 Docker 映像时,您可以将 JetBrains IDE 和插件(例如 Cloud Code for IntelliJ)安装到基本映像中。JetBrains 产品的 Cloud Workstations 基础映像包含以下脚本,可帮助您:
jetbrains-installer.sh:安装 JetBrains IDEplugin-installer.sh:安装插件,例如 Cloud Code for IntelliJ
您可以根据需要使用这些脚本来自定义基础映像,通过启动脚本调用这些脚本,或在启动工作站后运行这些脚本。
安装程序脚本
如需查看 jetbrains-installer.sh 和 plugin-installer.sh 脚本的源文件,请使用采用某个 JetBrains 预定义映像的工作站配置启动工作站,通过 JetBrains Gateway 或 SSH 连接到工作站,然后浏览根目录中的 installer-scripts 目录中的脚本文件。
我们建议您在容器构建时运行这些脚本。避免在已启动的工作站中运行它们。
使用插件安装程序脚本
plugin-installer.sh 脚本使用以下语法:
plugin-installer.sh [-v VERSION] [-d DESTINATION-DIRECTORY] [-c CHECKSUM] [-f] PLUGIN_ID
替换以下内容:
VERSION:要安装的插件的可选版本号。DESTINATION-DIRECTORY:插件应安装到的可选目录。如果未指定,则使用工作目录。CHECKSUM:所请求插件的可选 SHA-256 校验和。-f:如果指定,则会覆盖所有现有插件。PLUGIN_ID:JetBrains 市场中的必需数字插件标识符。例如,如需添加 Dart,请使用6351作为 PLUGIN_ID。如需添加 Cloud Code for IntelliJ,请使用8079作为 PLUGIN_ID。
例如,如需在 IntelliJ 中安装最新版本的 Dart 插件,请运行以下命令:
/installer-scripts/plugin-installer.sh -d /opt/ideaIU/plugins/ 6351
使用 JetBrains 安装程序脚本
我们建议您在扩展 JetBrains IDE 的预配置基础映像时使用 JetBrains 安装程序脚本。
jetbrains-installer.sh 脚本使用以下语法:
jetbrains-installer.sh IDE [ pinned|latest ]
替换以下内容:
IDE:要安装的 JetBrains IDE。您必须使用以下某个 IDE 缩写:IDE 已安装的产品 clCLion clionCLion goGoLand golandGoLand iiuIntellij Ultimate intellijIntellij Ultimate pcpPyCharm Professional pycharmPyCharm Professional psPHPStorm phpstormPHPStorm rd骑手 rider骑手 rmRubyMine rubymineRubyMine wsWebStorm webstormWebStorm pinned|latest:可选 - 使用固定版本或最新版本的 IDE。默认设置为latest。
例如,如需安装最新版本的 Clion,请运行以下命令:
/installer-scripts/jetbrains-installer.sh clion
自定义 JetBrains IDE 配置文件
如果工作站配置中指定了持久性主目录,则带有 JetBrains IDE 的 Cloud Workstations 基本映像会自动保留 $IDE.vmoptions 和 $IDE.properties 配置文件。如需替换这些文件的默认位置,请指定 CLOUD_WORKSTATIONS_JETBRAINS_PERISTED_CONFIG_DIR 环境变量。
如需了解详情,请参阅任何 JetBrains 基础映像中的 /etc/workstation-startup.d/120_persist-jetbrains-configs.sh,了解 Cloud Workstations 如何默认设置此项。
使用 Cloud Code for IntelliJ 扩展基础 Docker 映像
以下 Dockerfile 代码段通过包含 8079 作为必需的插件标识符,使用 Cloud Code for IntelliJ 扩展了基础 Docker 映像。该示例还可选择性地指定 version 22.9.3-222 作为版本号、/opt/ideaIU/plugins/ 作为目标目录,以及 89628279ed9042c526a81facc09bf53f8fb8b83b4595b0d329d94c1611e0c379 作为校验和:
...
# Install IDE and Plugins
RUN bash /installer-scripts/jetbrains-installer.sh intellij pinned && \
# Install Cloud Code - https://plugins.jetbrains.com/plugin/8079-cloud-code
bash /installer-scripts/plugin-installer.sh \
-v 22.9.3-222 \
-d /opt/ideaIU/plugins/ \
-c 89628279ed9042c526a81facc09bf53f8fb8b83b4595b0d329d94c1611e0c379 \
8079
# Register IDE with JetBrains Gateway
RUN echo 'runuser user -c "/opt/ideaIU/bin/remote-dev-server.sh registerBackendLocationForGateway"' > /etc/workstation-startup.d/110_register-intellij-with-gateway.sh \
echo 'echo "IntelliJ-Ultimate ready for incoming gateway connection"' >> /etc/workstation-startup.d/110_register-intellij-with-gateway.sh
...
在 Code OSS 中为 Cloud Workstations 安装其他 IDE 扩展程序
您可以在 Open VSX Registry 上找到其他 IDE 扩展程序。
您还可以通过复制任何扩展程序的下载链接中的网址来查找 .vsix 文件的网址。
如果您从工作站打开
扩展程序市场,则会显示安装,而不是下载。
Cloud Workstations 的默认 Code OSS 设置
如需详细了解如何在 Code OSS 中存储 Cloud Workstations 的设置,请参阅自定义设置。
如果您在工作站配置中指定了持久性主目录,则可以通过添加将设置写入 $HOME/.codeoss-cloudworkstations/data/Machine/settings.json 的启动脚本,为 Cloud Workstations 配置 Code OSS 的默认设置。
例如,如果您想将默认颜色主题设置为“深色”,请扩展基本编辑器映像,以在 /etc/workstation-startup.d/150_default-ide-color-theme.sh 下包含以下脚本
cat <<< $(jq '. += {"workbench.colorTheme": "Default Dark Modern"}' settings.json) > settings.json
构建自定义容器映像
如需详细了解 Docker 命令,请参阅 Docker 参考文档。 输入以下命令以构建容器:
docker build CUSTOM_IMAGE_FOLDER -t TARGET_IMAGE
请注意,替换修改 修改图标之前的文字会更新此页面上的其他示例。
替换以下内容:
CUSTOM_IMAGE_FOLDER:您创建的用于存储自定义映像的文件夹的路径。TARGET_IMAGE:映像在 Artifact Registry 中的路径。例如,
TARGET_IMAGE可能指向类似于以下路径的目标映像路径:*.pkg.dev/cloud-workstations-external/customimage:latest根据需要将 * 替换为区域的名称和任何其他标识符。
您还可以更新 CLOUD_WORKSTATIONS_CUSTOM_IMAGE 环境变量,以指向相应代码库。
如需详细了解如何在 Artifact Registry 中存储 Docker 映像,请参阅以下部分:
托管自定义容器映像
如需托管自定义容器映像,我们建议并支持使用 Artifact Registry。 如果您使用 GitHub 或任何其他公共或私有代码库,Cloud Workstations 可能无法按预期运行。如需了解详情,请参阅使用自定义容器映像部分中的重要提示。
测试自定义容器映像
容器构建完成后,您可以使用以下命令对其进行测试:
docker run --privileged -p LOCAL_PORT:CONTAINER_PORT TARGET_IMAGE
替换以下内容:
LOCAL_PORT:本地端口号CONTAINER_PORT:容器端口号
例如,将 LOCAL_PORT:CONTAINER_PORT 替换为 8080:80 会分配端口 8080 以供本地使用,并分配端口 80 以供容器使用。
如果您要扩展 Cloud Workstations 基础编辑器映像,请运行 docker 命令,然后通过本地浏览器连接到工作站或运行 ssh 连接到容器,以测试工作站映像:
- 如果您通过浏览器连接,请确保将
-p 8080:80传递给docker run命令,然后打开localhost:8080。 - 如果您希望通过 SSH 进行连接,请确保将
-p 2222:22传递给docker run命令,然后运行ssh user@localhost -p 2222。
使用自定义容器映像
在本地构建并测试自定义容器映像后,如需使用该映像,请使用以下命令将容器推送到 Artifact Registry:
docker push TARGET_IMAGE
现在,您可以使用刚刚创建并推送的容器映像创建工作站配置。
如需了解详情,请参阅使用 Artifact Registry 创建 Docker 代码库。
调试问题
如需查找并调试运行容器映像时出现的问题,请查看正在运行的工作站的容器输出日志。
建议:帮助保护您的映像流水线
您有责任维护和更新自定义映像上添加的自定义软件包和依赖项。
如果您要创建自定义图片,我们建议您执行以下操作:
运行容器扫描工具(例如 Artifact Analysis)来检查您添加的任何其他依赖项。
安排构建以每周重新构建映像,或了解如何自动重新构建容器映像。
后续步骤
- 自动重建容器映像,以使用 Cloud Build 和 Cloud Scheduler 同步基础映像更新。
- 设置安全性最佳实践。
- 详细了解 Artifact Analysis。