Skip to content

Instantly share code, notes, and snippets.

@robvanoostenrijk
Last active April 9, 2023 15:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robvanoostenrijk/d14e67c0b89e65a429d05bf4086d1947 to your computer and use it in GitHub Desktop.
Save robvanoostenrijk/d14e67c0b89e65a429d05bf4086d1947 to your computer and use it in GitHub Desktop.
docker compose on Google CoS (Container optimized OS)

docker compose on Google CoS (Container optimized OS)

Google Cloud supports running a virtual machine instance using CoS

CoS is a slim OS distribution providing a docker CLI and containerd service to run a single docker container. The single container can be configured to be ran directly on instance startup from the cloud console itself.

However, for more advanced use cases sadly, docker compose is not available by default. By leveraging the official docker image, the docker compose CLI plugin can be made available as a side-car container.

Additionally, its makes docker-gcr-credentials available to enable pulling images from GCR securely using service account credentials.

Included in this gist is a shell script example and cloud-init YAML to configure a VM instance with docker-compose enabled. The technical details section explains more.

Technical Details

The virtual machine is configured to pull the official docker image and start this on boot-up. Google's konlet image will take care of the startup procedure.

By mapping /var/run/docker.sock into the docker image, docker compose can now interact with the host docker daemon.

The docker compose CLI plugin is initialized with the following command arguments: compose --project-directory=/home/compose up --build --force-recreate --no-color --pull=all --remove-orphans --renew-anon-volumes

By ensuring its project working directory is /home/compose, we can ensure it looks for a docker-compose.yml file in this location.

This home folder is mapped from the host into the docker image and is populated on startup through cloud-init.yaml write-files instructions.

Additionally the cloud-init.yaml places a ~/.docker/config.json file which configures docker-credential-gcr binary for any Google container registry domains.

In order to ensure docker compose reads this configuration file, the environment variable HOME=/home/compose is set for the docker compose container.

docker-credential-gcr is made available by mapping /usr/bin/docker-credential-gcr to /usr/local/bin/docker-credential-gcr. Additionally the /lib64 folder from the host operating system is mapped into the container to ensure the dynamically linked credential executable works.

## template: jinja
#cloud-config
users:
- name: compose
uid: '2000'
groups: docker
write_files:
- path: /home/compose/env
permissions: '0644'
owner: compose
content: |
MYKEY=myvalue
- path: /home/compose/.docker/config.json
permissions: '0644'
owner: compose
content: |
{
"credHelpers": {
"eu.gcr.io": "gcr",
"europe-west1-docker.pkg.dev": "gcr",
"gcr.io": "gcr",
"us.gcr.io": "gcr"
}
}
- path: /home/compose/docker-compose.yml
permissions: '0644'
owner: compose
content: |
version: '3.8'
services:
hello:
build:
context: .
dockerfile: nginx-hello.Dockerfile
container_name: nginx-hello
env_file: env
ports:
- 80:80
- 443:443
restart: always
- path: /home/compose/nginx-hello.Dockerfile
permissions: '0644'
owner: compose
content: |
# Sample Dockerfile inserting Google Cloud logo inside the demo
FROM nginxdemos/hello
RUN sed -i 's$<div class="info">$<img src="https://upload.wikimedia.org/wikipedia/commons/5/51/Google_Cloud_logo.svg" width="400"/>\n<div class="info">$g' /usr/share/nginx/html/index.html
# Create Google CoS image running docker-compose
MACHINE_TYPE=e2-medium
PROJECT=${PROJECT:-project-id}
VM_NAME=${VM_NAME:-nginx-hello}
ZONE=${ZONE:-europe-west1-b}
gcloud compute instances create-with-container \
--project=${PROJECT} \
${VM_NAME} \
--boot-disk-size="10G" \
--boot-disk-type="pd-ssd" \
--image-family="cos-stable" \
--image-project="cos-cloud" \
--machine-type="${MACHINE_TYPE}" \
--metadata-from-file user-data="cloud-init.yaml" \
--restart-on-failure \
--shielded-integrity-monitoring \
--shielded-secure-boot \
--shielded-vtpm \
--tags="http-server,https-server" \
--zone="${ZONE}" \
--container-arg="compose" \
--container-arg="--ansi=never" \
--container-arg="--project-directory=/home/compose" \
--container-arg="up" \
--container-arg="--build" \
--container-arg="--force-recreate" \
--container-arg="--no-color" \
--container-arg="--pull=all" \
--container-arg="--remove-orphans" \
--container-arg="--renew-anon-volumes" \
--container-env="HOME=/home/compose" \
--container-image="docker:cli" \
--container-mount-host-path="host-path=/lib64,mount-path=/lib64,mode=ro" \
--container-mount-host-path="host-path=/var/run/docker.sock,mount-path=/var/run/docker.sock,mode=ro" \
--container-mount-host-path="host-path=/usr/bin/docker-credential-gcr,mount-path=/usr/local/bin/docker-credential-gcr,mode=ro" \
--container-mount-host-path="host-path=/home/compose,mount-path=/home/compose,mode=rw"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment