This document explains how to build and configure a Jenkins CI server container image to run an Apigee deployment pipeline.
You can choose between two different setups:
Jenkins Web
: Builds an image for running Jenkins with a web UI.Jenkinsfile Runner
Builds an ephemeral runtime for running a specific Jenkinsfile without having to configure the full UI. We use this version for our continuous testing in Apigee DevRel.
To have a common base for the two setups, we have a common base image that is extended to suit both of the two setups above.
Follow these instructions to build and run a fully configured Jenkins UI instance.
docker pull ghcr.io/apigee/devrel-jenkins:latest
docker tag ghcr.io/apigee/devrel-jenkins:latest apigee/devrel-jenkins:latest
docker build -t apigee/devrel-jenkins-base:latest .
docker build -f ./jenkins-web/Dockerfile -t apigee/devrel-jenkins:latest .
PROJECT_ID=<my-project>
gcloud builds submit --config ./cloudbuild.yml --project $PROJECT_ID
gcloud builds submit --config ./jenkins-web/cloudbuild.yml --project $PROJECT_ID
docker pull europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest
docker tag europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest apigee/devrel-jenkins:latest
In this section we describe how to setup Jenkins on either a GCP VM or locally via Docker.
To run Jenkins on a Compute Engine VM first make sure you have the Container Image in GCR. If you have not used Cloud Build to build your Image then push it to GCR like so:
docker tag apigee/devrel-jenkins:latest europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest
docker push europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest
If you are building for Apigee X or hybrid you should create a dedicated service account for your Jenkins VM that has all required permission to deploy to Apigee.
JENKINS_SA_NAME="jenkins"
JENKINS_SA_EMAIL="$JENKINS_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"
gcloud iam service-accounts create "$JENKINS_SA_NAME" --project "$PROJECT_ID"
# Permissions to deploy to Apigee
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:$JENKINS_SA_EMAIL" \
--role="roles/apigee.environmentAdmin"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:$JENKINS_SA_EMAIL" \
--role="roles/apigee.apiAdmin"
# Permission to pull the jenkins image from GCR
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:$JENKINS_SA_EMAIL" \
--role="roles/storage.objectViewer"
To restrict access to only your machine set the firewall to only allow your
external IP (Otherwise replace it with --source-ranges='0.0.0.0/0'
).
gcloud compute firewall-rules create allow-me-jenkins --allow=tcp:8080 \
--description="Allow only my IP to access jenkins" \
--direction=INGRESS --target-tags=jenkins --source-ranges="$(curl ipecho.net/plain)/32" \
--project $PROJECT_ID
To start your jenkins with credentials for Apigee X/hybrid run the following command:
CONTAINER_ENVS="JENKINS_ADMIN_PASS=password"
CONTAINER_ENVS+=",API_VERSION=google"
CONTAINER_ENVS+=",APIGEE_ORG=$APIGEE_X_ORG"
CONTAINER_ENVS+=",APIGEE_TEST_ENV=test1"
CONTAINER_ENVS+=",APIGEE_PROD_ENV=prod1"
CONTAINER_ENVS+=",TEST_HOST=$APIGEE_X_HOSTNAME"
gcloud compute instances create-with-container jenkins --tags jenkins \
--container-image europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest \
--container-env "$CONTAINER_ENVS" \
--machine-type e2-standard-2 \
--service-account "$JENKINS_SA_EMAIL" \
--scopes cloud-platform \
--project $PROJECT_ID
echo "Starting Jenkins Container. Once Jenkins is ready you can visit: http://$(gcloud compute instances describe jenkins --format json | jq -r ".networkInterfaces[0].accessConfigs[0].natIP"):8080"
To start your jenkins with credentials for Apigee Edge run the following command:
CONTAINER_ENVS="JENKINS_ADMIN_PASS=password"
CONTAINER_ENVS+=",API_VERSION=apigee"
CONTAINER_ENVS+=",APIGEE_ORG=$APIGEE_ORG"
CONTAINER_ENVS+=",APIGEE_TEST_ENV=test"
CONTAINER_ENVS+=",APIGEE_PROD_ENV=prod"
CONTAINER_ENVS+=",APIGEE_USER=$APIGEE_USER"
CONTAINER_ENVS+=",APIGEE_PASS=$APIGEE_PASS"
CONTAINER_ENVS+=",TEST_HOST=$APIGEE_ORG-$APIGEE_ENV.apigee.net"
gcloud compute instances create-with-container jenkins --tags jenkins \
--container-image europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkins:latest \
--container-env "$CONTAINER_ENVS" \
--machine-type e2-standard-2 \
--service-account "$JENKINS_SA_EMAIL" --scopes cloud-platform
echo "Starting Jenkins Container. Once Jenkins is ready you can visit: http://$(gcloud compute instances describe jenkins --format json | jq -r ".networkInterfaces[0].accessConfigs[0].natIP"):8080"
You can also run a local Docker image as follows:
docker run \
-p 8080:8080 \
-e APIGEE_USER \
-e APIGEE_PASS \
-e APIGEE_ORG \
-e APIGEE_TEST_ENV="test" \
-e APIGEE_PROD_ENV="prod" \
-e TEST_HOST="$APIGEE_ORG-$APIGEE_ENV.apigee.net" \
-e API_VERSION="apigee" \
-e JENKINS_ADMIN_PASS="password" \
apigee/devrel-jenkins:latest
docker run \
-p 8080:8080 \
-e APIGEE_TOKEN="$(gcloud auth print-access-token)" \
-e GCP_SA_AUTH="token" \
-e APIGEE_ORG \
-e APIGEE_TEST_ENV="test1" \
-e APIGEE_PROD_ENV="prod1" \
-e TEST_HOST="api.example.apigee.com" \
-e API_VERSION="google" \
-e JENKINS_ADMIN_PASS="password" \
apigee/devrel-jenkins:latest
Note: for long running jenkins deployments consider mounting the gcloud service account credential file from the host filesystem instead of passing the access token via environment variables:
export KEY_FILE_PATH=/tmp/keys/jenkins-key-file.json
gcloud iam service-accounts keys create $KEY_FILE_PATH --iam-account=$SERVICE_ACCOUNT_ID@$PROJECT_ID.iam.gserviceaccount.com
docker run -d
-p 8080:8080 \
-e APIGEE_ORG="my-org" \
-e APIGEE_TEST_ENV="test" \
-e APIGEE_PROD_ENV="prod"
-e TEST_HOST="api.example.apigee.com" \
-e GCP_SA_AUTH="vm-scope" \
-e API_VERSION="google"
-e JENKINS_ADMIN_PASS="password" \
-e GOOGLE_APPLICATION_CREDENTIALS="$KEY_FILE_PATH" \
-v "$KEY_FILE_PATH:$KEY_FILE_PATH:ro" \
apigee/devrel-jenkins:latest
After the initialization is completed, you can login with the Jenkins web UI
http://localhost:8080
using the admin
user and the password you specified
before.
Follow these instructions to build and run an ephemeral Jenkinsfile runtime. This is mainly intended for CI/CD of the pipeline itself.
docker pull ghcr.io/apigee/devrel-jenkinsfile:latest
docker tag ghcr.io/apigee/devrel-jenkinsfile:latest apigee/devrel-jenkinsfile:latest
docker build -t apigee/devrel-jenkins-base:latest .
docker build -f jenkinsfile-runner/Dockerfile -t apigee/devrel-jenkinsfile:latest .
PROJECT_ID=$(gcloud config get-value project)\
gcloud builds submit --config ./cloudbuild.yml --project $PROJECT_ID
gcloud builds submit --config ./jenkinsfile-runner/cloudbuild.yml --project $PROJECT_ID
docker pull europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkinsfile-runner:latest
docker tag europe-docker.pkg.dev/$PROJECT_ID/devrel/devrel-jenkinsfile-runner:latest apigee/devrel-jenkinsfile:latest
See pipeline.sh at the root of this reference.