Skip to content

Instructions for Google Cloud Build & Run #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.git
.gitignore
.github
.mvn
.gradle
gradle
target

45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,48 @@ docker run -it --rm -p 8080:8080 example-spring-boot

The most important part of the Dockerfile is invoking the checkpoint with `RUN --security=insecure`. Also, when creating your own Dockerfiles don't forget to enable the experimental syntax using `# syntax=docker/dockerfile:1.3-labs`.

## Building and running in Google Cloud

It is possible to build the image in Google Cloud Build and later create a service in Google Cloud Run, with a minor modification of the steps above. Start with logging in and creating a repository for the images:

```sh
gcloud auth login
export PROJECT_ID=$(gcloud config list --format 'value(core.project)')
# Setup default region
gcloud config set artifacts/location us-west1
gcloud config set run/region us-west1
gcloud artifacts repositories create crac-examples --repository-format=docker
```

You might need to use service accounts to perform the builds and deploy service; create these through IAM & Admin console and add necessary roles:
* cloud-build: 'Cloud Build Service Account', 'Cloud Build WorkerPool User', 'Service Account User'
* cloud-run: 'Cloud Run Admin', 'Service Account User'

We present two ways to perform the build: `cloudbuild-builder.yaml` uses the single Dockerfile steps shown above, performing the checkpoint in a BuildKit builder. You can also apply the steps from 'Preparing a container image' directly, with several modifications as used in `cloudbuild-direct.yaml`. The main difference vs. local build is that in Cloud Build the commands are executed from a container that provides access to the Docker server where it runs: volume mounts and port mapping works differently. Here is a list of differences:

* For checkpoint image we don't mount `target/cr` directly, but use a named volume `cr`. After checkpoint we need to copy the image out to pass it to restoring image Docker build.
* Ports are not bound to localhost; checkpoint container must use network `cloudbuild` and we connect to the container using its name as hostname.
* We use `--privileged` rather than fine-grained list of capabilities; Docker version used in Cloud Build does not allow capability `CHECKPOINT_RESTORE`.

You can submit the build(s) using these commands:
```sh
gcloud builds submit --config cloudbuild-builder.yaml --service-account=projects/$PROJECT_ID/serviceAccounts/cloud-builder@$PROJECT_ID.iam.gserviceaccount.com
gcloud builds submit --config cloudbuild-direct.yaml --service-account=projects/$PROJECT_ID/serviceAccounts/cloud-builder@$PROJECT_ID.iam.gserviceaccount.com
```

When the build completes, you can create the service in Cloud Run:

```sh
gcloud run deploy example-spring-boot-direct \
--image=us-west1-docker.pkg.dev/$PROJECT_ID/crac-examples/example-spring-boot-direct \
--execution-environment=gen2 --allow-unauthenticated \
--service-account=cloud-runner@$PROJECT_ID.iam.gserviceaccount.com
```

Note that we're using Second generation Execution environment; our testing shows that it is not possible to restore in First generation. Now you can test your deployment:

```sh
export URL=$(gcloud run services describe example-spring-boot-direct --format 'value(status.address.url)')
curl $URL
Greetings from Spring Boot!
```
10 changes: 10 additions & 0 deletions cloudbuild-builder.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
steps:
- name: 'gcr.io/cloud-builders/docker'
script: |
docker buildx create --buildkitd-flags '--allow-insecure-entitlement security.insecure' --name privileged-builder
docker buildx build --load --builder privileged-builder --allow=security.insecure -f Dockerfile.privileged -t us-west1-docker.pkg.dev/$PROJECT_ID/crac-examples/example-spring-boot-builder .
automapSubstitutions: true
images:
- us-west1-docker.pkg.dev/$PROJECT_ID/crac-examples/example-spring-boot-builder
options:
logging: CLOUD_LOGGING_ONLY
29 changes: 29 additions & 0 deletions cloudbuild-direct.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
steps:
- name: maven:3.8.7-openjdk-18
entrypoint: mvn
args: [ "-B", "install" ]
- name: 'gcr.io/cloud-builders/docker'
env:
- CHECKPOINT_IMG=example-spring-boot-checkpoint
- CONTAINER=example-spring-boot-checkpoint
script: |
apt-get update && apt-get install siege
docker build -f Dockerfile.checkpoint -t $CHECKPOINT_IMG .
docker run -d --rm -v cr:/cr --privileged --network cloudbuild -p 8080:8080 --name $CONTAINER $CHECKPOINT_IMG
# Wait until the application is up and serving requests
until curl --output /dev/null --silent --head --fail http://$CONTAINER:8080; do
sleep 0.1
done
# Warm-up the server by executing 100k requests against it
siege -c 1 -r 100000 -b http://$CONTAINER:8080
docker exec $CONTAINER jcmd example-spring-boot JDK.checkpoint
# Wait until the container finishes writing the image to volume 'cr'
docker container wait $CONTAINER
# Copy contents of the 'cr' volume into target/cr
docker run --rm -v cr:/cr --entrypoint tar $CHECKPOINT_IMG -cf - /cr | tar -C target -xvf -
docker build -f Dockerfile.restore -t us-west1-docker.pkg.dev/$PROJECT_ID/crac-examples/example-spring-boot-direct .
automapSubstitutions: true
images:
- us-west1-docker.pkg.dev/$PROJECT_ID/crac-examples/example-spring-boot-direct
options:
logging: CLOUD_LOGGING_ONLY