Sample Cloud Foundry to Cloud Run migration: Spring Music

This sample migration uses the Spring Music project to show how a Cloud Foundry application can be built as an OCI-compliant application image. This sample is using the lift and shift strategy , which uses open source components from the Cloud Foundry ecosystem. After you create the application image, you need to configure the application for deployment to Cloud Run.

Before you start

  • Make sure you have set up a new project for Cloud Run as described in the setup page.
  • Make sure you have a REGISTRY_URI for storing containers. Cloud Run recommends using Artifact Registry.
  • If you are under a domain restriction organization policy restricting unauthenticated invocations for your project, you will need to access your deployed service as described under Testing private services .

  • Install Docker on your workstation. Docker is used to create intermediate images to build the project.

Permissions required to deploy

For this guide you need permissions to build, store the built container image and deploy.

You must have the following roles:

Project Structure

For this guide we suggest that you create a project directory e.g. cr-spring-music/ and create sub-directories as you progress through the guide.

 cr-spring-music/
├── build
├── run
└── spring-music 

Create the build Image

This section creates a build image using cflinux3 as the base image. The build image is used as the build environment for creating the application image.

  1. Create a directory called build/ and cd into it:

     mkdir  
    build && 
     cd 
      
    build 
    
  2. In the build/ folder, create a new file called Dockerfile and paste in the following code:

      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 
    
  3. Use Cloud Build to build and publish the builder image

     gcloud  
    builds  
     \ 
      
    submit  
    --tag  
     " REGISTRY_URI 
    /builder:stable" 
     
    

    Replace REGISTRY_URI with the address of the Artifact Registry where you want to publish the build image. For example: REGION -docker.pkg.dev/ PROJECT_ID / REPOSITORY /builder:stable .

Create the runtime Image

This section creates a run image using cflinux3 as the base image. The run image is used as the base image when you create the final application image.

  1. Create a directory called run/ and cd into it:

     mkdir  
    run && 
     cd 
      
    run 
    
  2. In the run/ folder, create a new shell script called entrypoint.bash with the following code:

      #!/usr/bin/env bash 
     set 
      
    -e if 
      
     [[ 
      
     " 
     $@ 
     " 
      
     == 
      
     "" 
      
     ]] 
     ; 
      
     then 
     exec 
      
    /lifecycle/launcher  
     "/home/vcap/app" 
      
     "" 
      
     "" 
     else 
     exec 
      
    /lifecycle/launcher  
     "/home/vcap/app" 
      
     " 
     $@ 
     " 
      
     "" 
     fi 
     
    
  3. In the run/ folder, create a new file called Dockerfile and paste in the following code:

      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 
     ={} 
     
    
  4. Use Cloud Build to build and publish the runtime image:

     gcloud  
    builds  
    submit  
     \ 
      
    --tag  
     " REGISTRY_URI 
    /runtime:stable" 
     
    

    Replace REGISTRY_URI with the address to the Artifact Registry where you want to publish the build image. For example: REGION -docker.pkg.dev/ PROJECT_ID / REPOSITORY /runtime:stable.

Build Spring Music for Cloud Foundry

To clone the Spring Music project and run the build commands as if we were deploying the project to Cloud Foundry:

  1. Clone the Spring Music repository:

     git  
    clone  
    https://github.com/cloudfoundry-samples/spring-music.git 
    
  2. For the purposes of this guide, we will be using an older version of the Spring Music application that uses Java 8 and Spring Boot 2. To do this we will move to an older revision of the Spring Music project:

     git  
    checkout  
    610ba471a643a20dee7a62d88a7879f13a21d6a3 
    
  3. Move into the repository:

      cd 
      
    spring-music 
    
  4. Build the Spring Music binary:

     ./gradlew  
    clean  
    assemble 
    

You now have a build/ folder with the compiled Spring Music app ready to be pushed into a Cloud Foundry instance.

Convert Spring Music into a Cloud Run compatible application

You must take the output of the build command to prepare the Spring Music artifact for deployment into Cloud Run.

  1. Create a staging directory cr-app and a src sub-directory inside of it:

     mkdir  
    -p  
    cr-app/src 
    
  2. Mimic cf push by extracting the contents of the compiled JAR into the src directory:

     unzip  
    build/libs/spring-music-1.0.jar  
    -d  
    cr-app/src 
    
  3. Change directory into cr-app/ :

      cd 
      
    cr-app/ 
    
  4. Create a new file called Dockerfile . This Dockerfile will use the build image and runtime image created in the previous steps to create the runnable application image for Spring Music, using the Java buildpack.

  5. Paste the following code into the 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 
    

Build Spring Music as an OCI compliant image

In this step, you instruct Cloud Build how to construct an OCI-compliant image using the build image, runtime image, and application Dockerfile created in the previous steps.

To create the OCI-compliant image:

  1. Create a file called cloudbuild.yaml . This is a build configuration that will instruct Cloud Build how to build the application.

  2. Paste the following configuration into 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 
    
    • Replace REGISTRY_URI with the URI of the container registry where you have published the builder and runner.
  3. Build the application image using Cloud Build:

     gcloud  
    builds  
    submit  
    . 
    

    When the build completes, make note of the resulting image URI. You will need it when deploying the application in the next steps. The resulting image will be an OCI-compliant container image for running the Spring Music app, built using open source Cloud Foundry components.

Deploy to Cloud Run

You must create a service definition file to use in Cloud Run:

  1. Create a service account for your application:

     gcloud  
    iam  
    service-accounts  
    create  
    spring-music 
    
  2. Create a service.yaml file with the following code:

      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 
     
    
  3. Deploy the service to Cloud Run:

     gcloud  
    run  
    services  
    replace  
    service.yaml 
    

    Once the deployment completes, you will be able to visit the running Spring Music application at the deployed URL.

What's Next

Create a Mobile Website
View Site in Mobile | Classic
Share by: