此示例迁移使用 Spring Music 项目来展示如何将 Cloud Foundry 应用构建为符合 OCI 规范的应用映像。此示例使用直接原样迁移策略,该策略使用 Cloud Foundry 生态系统中的开源组件。创建应用映像后,您需要配置应用以部署到 Cloud Run。
前期准备
- 确保您已按照设置页面中的说明为 Cloud Run 设置了新项目。
- 确保您拥有用于存储容器的
REGISTRY_URI
。Cloud Run 建议使用 Artifact Registry。 - 在您的工作站上安装 Docker。Docker 用于创建中间映像以构建项目。
部署所需的权限
在本指南中,您需要拥有构建、存储构建的容器映像以及进行部署的权限。
您必须拥有以下角色:
项目结构
对于本指南,我们建议您创建一个项目目录(例如 cr-spring-music/
),并在完成本指南的过程中创建子目录。
cr-spring-music/
├── build
├── run
└── spring-music
创建构建映像
本部分使用 cflinux3
作为基础映像来创建构建映像。该构建映像用作创建应用映像的构建环境。
创建名为
build/
的目录并通过cd
命令进入该目录:mkdir build && cd build
在
build/
文件夹中,创建一个名为Dockerfile
的新文件并粘贴以下代码:ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3 FROM golang:1.20-bullseye AS builder_build WORKDIR /build RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"] WORKDIR /build/buildpackapplifecycle RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"] RUN ["go", "mod", "tidy"] RUN CGO_ENABLD=0 go build -o /builder ./builder/ FROM $CF_LINUX_FS # Set up container tools related to building applications WORKDIR /lifecycle COPY --from=builder_build /builder /lifecycle/builder # Set up environment to match Cloud Foundry's build. # https://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#app-system-env WORKDIR /staging/app WORKDIR /tmp ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \ CF_INSTANCE_IP=127.0.0.1 \ CF_INSTANCE_INTERNAL_IP=127.0.0.1 \ VCAP_APP_HOST=127.0.0.1 \ CF_INSTANCE_PORT=8080 \ LANG=en_US.UTF-8 \ INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \ VCAP_APPLICATION={} \ VCAP_SERVICES={} \ CF_STACK=cflinuxfs3
使用 Cloud Build 构建和发布
builder
映像gcloud builds \ submit --tag "REGISTRY_URI/builder:stable"
将
REGISTRY_URI
替换为要发布构建映像的 Artifact Registry 的地址。例如:REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable
。
创建运行时映像
本部分使用 cflinux3
作为基础映像来创建运行映像。当您创建最终应用映像时,运行映像被用作基础映像。
创建名为
run/
的目录并通过cd
命令进入该目录:mkdir run && cd run
在
run/
文件夹中,使用以下代码创建名为entrypoint.bash
的新 Shell 脚本:#!/usr/bin/env bash set -e if [[ "$@" == "" ]]; then exec /lifecycle/launcher "/home/vcap/app" "" "" else exec /lifecycle/launcher "/home/vcap/app" "$@" "" fi
在
run/
文件夹中,创建一个名为Dockerfile
的新文件并粘贴以下代码:ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3 FROM golang:1.20-bullseye AS launcher_build WORKDIR /build RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"] WORKDIR /build/buildpackapplifecycle RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"] RUN ["go", "mod", "tidy"] RUN CGO_ENABLD=0 go build -o /launcher ./launcher/ FROM $CF_LINUX_FS # Set up container tools related to launching the application WORKDIR /lifecycle COPY entrypoint.bash /lifecycle/entrypoint.bash RUN ["chmod", "+rx", "/lifecycle/entrypoint.bash"] COPY --from=launcher_build /launcher /lifecycle/launcher # Set up environment to match Cloud Foundry WORKDIR /home/vcap USER vcap:vcap ENTRYPOINT ["/lifecycle/entrypoint.bash"] # Expose 8080 to allow app to be run on Cloud Foundry, # and PORT so the container can be run locally. # These do nothing on Cloud Run. EXPOSE 8080/tcp # Set up environment variables similar to Cloud Foundry. ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \ CF_INSTANCE_IP=127.0.0.1 \ INSTANCE_IP=127.0.0.1 \ CF_INSTANCE_INTERNAL_IP=127.0.0.1 \ VCAP_APP_HOST=127.0.0.1 \ CF_INSTANCE_PORT=80 \ LANG=en_US.UTF-8 \ CF_INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \ INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \ CF_INSTANCE_INDEX=0 \ INSTANCE_INDEX=0 \ PORT=8080 \ VCAP_APP_PORT=8080 \ VCAP_APPLICATION={} \ VCAP_SERVICES={}
使用 Cloud Build 构建和发布
runtime
映像:gcloud builds submit \ --tag "REGISTRY_URI/runtime:stable"
将
REGISTRY_URI
替换为要发布构建映像的 Artifact Registry 的地址例如:REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.
为 Cloud Foundry 构建 Spring Music
如需克隆 Spring Music 项目并运行构建命令(就好像我们将该项目部署到 Cloud Foundry 一样),请执行以下操作:
克隆 Spring Music 代码库:
git clone https://github.com/cloudfoundry-samples/spring-music.git
在本教程中,我们将使用旧版 Spring Music 应用,它使用 Java 8 和 Spring Boot 2。为此,我们将迁移到旧版 Spring Music 项目:
git checkout 610ba471a643a20dee7a62d88a7879f13a21d6a3
进入代码库:
cd spring-music
构建 Spring Music 二进制文件:
./gradlew clean assemble
您现在已经有了 build/
文件夹,其中包含已编译的 Spring Music 应用,可推送到 Cloud Foundry 实例。
将 Spring Music 转换为与 Cloud Run 兼容的应用
您必须获取构建命令的输出,以准备 Spring Music 制品来部署到 Cloud Run。
创建一个暂存目录
cr-app
并在其中创建一个src
子目录:mkdir -p cr-app/src
通过将已编译的 JAR 的内容提取到
src
目录中来模拟cf push
:unzip build/libs/spring-music-1.0.jar -d cr-app/src
转到
cr-app/
目录:cd cr-app/
创建一个名为
Dockerfile
的新文件。 此Dockerfile
将使用在之前步骤中创建的构建映像和运行时映像,通过 Java Buildpack 为 Spring Music 创建可运行的应用映像。将以下代码粘贴到
Dockerfile
中:ARG BUILD_IMAGE ARG RUN_IMAGE FROM $BUILD_IMAGE as build COPY src /staging/app COPY src /tmp/app ARG BUILDPACKS RUN /lifecycle/builder \ -buildArtifactsCacheDir=/tmp/cache \ -buildDir=/tmp/app \ -buildpacksDir=/tmp/buildpacks \ -outputBuildArtifactsCache=/tmp/output-cache \ -outputDroplet=/tmp/droplet \ -outputMetadata=/tmp/result.json \ "-buildpackOrder=${BUILDPACKS}" \ "-skipDetect=true" FROM $RUN_IMAGE COPY --from=build /tmp/droplet droplet RUN tar -xzf droplet && rm droplet
将 Spring Music 构建为符合 OCI 规范的映像
在此步骤中,您将指示 Cloud Build 如何使用之前步骤中创建的构建映像、运行时映像和应用 Dockerfile 来构建符合 OCI 规范的映像。
如需创建符合 OCI 规范的映像,请执行以下操作:
创建名为
cloudbuild.yaml
的文件。 这是一项构建配置,将指示 Cloud Build 如何构建应用。将以下配置粘贴到
cloudbuild.yaml
中:steps: - name: gcr.io/cloud-builders/docker args: - 'build' - '--network' - 'cloudbuild' - '--tag' - '${_TAG}' - '--build-arg' - 'BUILD_IMAGE=${_BUILD_IMAGE}' - '--build-arg' - 'RUN_IMAGE=${_RUN_IMAGE}' - '--build-arg' - 'BUILDPACKS=${_BUILDPACKS}' - '.' images: - "${_TAG}" options: # Substitute build environment variables as an array of KEY=VALUE formatted strings here. env: [] substitutions: _BUILD_IMAGE: REGISTRY_URI/builder:stable _RUN_IMAGE: REGISTRY_URI/runtime:stable _BUILDPACKS: https://github.com/cloudfoundry/java-buildpack _TAG: REGISTRY_URI/spring-music:latest
- 将
REGISTRY_URI
替换为发布构建器和运行程序的容器仓库的 URI。
- 将
使用 Cloud Build 构建应用映像:
gcloud builds submit .
构建完成后,记下生成的映像 URI。在后续步骤中部署应用时,您将用到它。生成的映像将是一个符合 OCI 规范的容器映像,用于运行 Spring Music 应用,使用开源 Cloud Foundry 组件构建。
部署到 Cloud Run
您必须创建一个服务定义文件以在 Cloud Run 中使用:
为您的应用创建服务账号:
gcloud iam service-accounts create spring-music
创建一个包含以下代码的
service.yaml
文件。apiVersion: serving.knative.dev/v1 kind: Service metadata: name: "spring-music" # Set this to be the project number of the project you're deploying to. namespace: "PROJECT_NUMBER" labels: cloud.googleapis.com/location: us-central1 migrated-from: cloud-foundry annotations: run.googleapis.com/ingress: all spec: template: metadata: annotations: autoscaling.knative.dev/minScale: '1' autoscaling.knative.dev/maxScale: '1' run.googleapis.com/cpu-throttling: 'true' run.googleapis.com/startup-cpu-boost: 'true' run.googleapis.com/sessionAffinity: 'false' spec: containerConcurrency: 1000 timeoutSeconds: 900 serviceAccountName: spring-music@PROJECT_NUMBER.iam.gserviceaccount.com containers: - name: user-container # Set the following value to either: # - The image you built for your application in the last section of the guide. image: SPRING_IMAGE_URI ports: - name: http1 containerPort: 8080 env: - name: VCAP_APPLICATION value: |- { "application_id": "00000000-0000-0000-0000-000000000000", "application_name": "spring-music", "application_uris": [], "limits": { "disk": 0, "mem": 1024 }, "name": "spring-music", "process_id": "00000000-0000-0000-0000-000000000000", "process_type": "web", "space_name": "none", "uris": [] } - name: MEMORY_LIMIT value: '1024M' resources: limits: memory: 1024Mi cpu: "1" startupProbe: httpGet: path: / port: 8080 timeoutSeconds: 1 failureThreshold: 30 successThreshold: 1 periodSeconds: 2 livenessProbe: httpGet: path: / port: 8080 timeoutSeconds: 1 failureThreshold: 1 successThreshold: 1 periodSeconds: 30 traffic: - percent: 100 latestRevision: true
- 将
PROJECT_NUMBER
替换为您的项目编号。 - 将
SPRING_IMAGE_URI
替换为将 Spring Music 构建为符合 OCI 规范的映像下创建的应用映像的 URI。
- 将
将服务部署到 Cloud Run:
gcloud run services replace service.yaml
部署完成后,您将能够通过部署的网址访问正在运行的 Spring Music 应用。
后续步骤
- 如需深入了解容器化过程,请参阅迁移到 OCI 容器。