Cloud 工作站提供的预配置基础映像仅包含包含 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 工作站会将 Docker 映像存储在
/home/.docker_data的主目录中,以便在会话之间保留映像。
如需在工作站启动期间添加其他功能,请在 /etc/workstation-startup.d/ 目录中添加脚本:
默认情况下,此目录中的脚本会以 root 用户身份运行。如需以其他用户身份执行脚本,请使用
runuser命令。由于脚本按字典顺序执行,因此我们建议您在脚本前面添加一个大于 200 的三位数。
或者,如果您不想扩展工作站映像,可以在主目录中创建 customize_environment 脚本。
主目录修改
当工作站配置指定永久性主目录(这是默认行为)时,支持主目录的永久性磁盘会在运行时动态附加到容器。此过程会覆盖在容器映像构建时对 /home 目录所做的修改。
如需保留更新,请在容器运行时修改 /home 目录,方法是在 /etc/workstation-startup.d 目录中添加脚本,或在 /etc/profile.d 目录中添加每位用户的配置。为了加快流程速度,不妨考虑将设置脚本作为后台进程运行(在命令末尾添加一个 &),以免阻塞容器启动。
以下是一些应移至容器运行时环境的构建时配置示例:
- 按用户的
git配置 - 克隆到主目录中的
git代码库 - 直接用户配置,例如将文件放置在
$HOME/.config目录中 - 创建用户
创建和修改用户
由于永久性磁盘会在运行时动态附加到容器,因此必须在工作站启动时添加用户,而不是在 Dockerfile 中添加。如需修改或创建其他用户,我们建议您更新 /etc/workstation-startup.d/010_add-user.sh,或创建在启动时执行的自定义脚本。
此外,您还可以通过更新 /etc/profile.d 中的文件来修改用户的默认 bash 配置文件。
更新预配置的安全 APT 密钥
Cloud Workstations 基础映像预安装了使用安全 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 会与工作站启动并行运行,因此脚本安装的软件包最早可在工作站启动后几分钟内使用。
使用您自己的容器映像
您还可以使用自己的容器映像或外部容器映像,前提是它们基于 Linux 且在容器启动时运行阻塞进程。
设置 Dockerfile 时,ENTRYPOINT 指令必须运行 sleep infinity 等阻塞进程,以便容器继续运行,而不是立即退出。或者,您也可以在工作站配置中设置 config.container.args 字段以指定阻塞进程。
使用您自己的容器映像时,请注意以下事项:
Cloud Workstations 不需要 Cloud Workstations 基础映像中的其他脚本。
不过,您可以查看运行 Cloud Workstations 基础映像的容器内的
/etc/workstation-startup.d/目录中的脚本。文件名指示每个脚本的用途。我们建议您在容器中运行 SSH 服务器。请参阅默认基础映像中的
/etc/workstation-startup.d/020_start-sshd.sh,了解 Cloud Workstations 默认如何进行此设置。我们建议您在端口
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 阶段之间复制工件。如需将适用于 Cloud Workstations 的 Code OSS 添加到其他容器映像,请使用多阶段 build 将应用文件夹 /opt/code-oss 复制到您的映像中。如果您想在容器启动时启动适用于 Cloud 工作站的 Code OSS,请另外将脚本 /etc/workstation-startup.d/110_start-code-oss.sh 复制到容器中。
下面是一个将 Code OSS 复制到 JetBrains IntelliJ Ultimate 映像的 Dockerfile 示例。然后,您可以与任一 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 for Cloud Workstations 中预安装 IDE 扩展程序以进行 Java 开发的容器映像
如需创建一个容器映像,以便在构建时在 Code OSS for Cloud Workstations 中预安装 IDE 扩展程序以进行 Java 开发,请运行以下命令:
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
使用此方法时,扩展程序会显示在 扩展程序市场中,您可以从中进行更新。
将 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 Marketplace 中必需的数字插件标识符。例如,如需添加 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 rdRider riderRider rmRubyMine rubymineRubyMine wsWebStorm webstormWebStorm pinned|latest:可选 - 使用固定的 IDE 版本或最新版本的 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 添加为必需的插件标识符,将基础 Docker 映像扩展为 Cloud Code for IntelliJ。该示例还可选择将 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 for Cloud Workstations 中安装其他 IDE 扩展程序
在 Open VSX 注册表中查找其他 IDE 扩展程序。您还可以通过复制任何扩展程序的下载链接中的网址,找到 .vsix 文件的网址。
如果您在工作站上打开
Extensions Marketplace,系统会显示安装,而不是下载。
适用于 Cloud Workstations 的默认 Code OSS 设置
如需详细了解如何在 Cloud Workstations 专用 Code OSS 中存储设置,请参阅自定义设置。
如果您在工作站配置中指定了永久性主目录,则可以通过添加将设置写入 $HOME/.codeoss-cloudworkstations/data/Machine/settings.json 的启动脚本,为 Cloud 工作站专用 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。