Ian Fako
Ian Fako

Reputation: 1210

Github Action for updating a docker container on GCE

I am currently trying to create a Github Action that automatically updates a running container on one of my GCE instances. I am using the template from this repo:

# Copyright 2020 Google, LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Build and Deploy to Google Compute Engine

on:
  push:
    branches:
      - master

env:
  PROJECT_ID: ${{ secrets.GCE_PROJECT }}
  GCE_INSTANCE: instance-name
  GCE_INSTANCE_ZONE: us-east1-d

jobs:
  setup-build-publish-deploy:
    name: Setup, Build, Publish, and Deploy
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      # Setup gcloud CLI
      - uses: google-github-actions/setup-gcloud@master
        with:
          version: '290.0.1'
          service_account_key: ${{ secrets.GCE_SA_KEY }}
          project_id: ${{ secrets.GCE_PROJECT }}

      # Configure Docker to use the gcloud command-line tool as a credential
      # helper for authentication
      - run: |-
          gcloud --quiet auth configure-docker
      # Build the Docker image
      - name: Build
        run: |-
          docker build --tag "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA" .
      # Push the Docker image to Google Container Registry
      - name: Publish
        run: |-
          docker push "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA"
      - name: Deploy
        run: |-
          gcloud compute instances update-container "$GCE_INSTANCE" \
            --zone "$GCE_INSTANCE_ZONE" \
            --container-image "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA"

What I did so far to update my application is by manually pull changes from my github repo and run docker-compose up --build. I am using docker-compose since my app is also using a Postgres DB.

Here is my Dockerfile:

FROM node:14
WORKDIR /usr/src/app
COPY . .
RUN npm install
CMD [ "npm", "run", "prod" ]

And my docker-compose.yaml (with dummy values):

version: "3"
services:
  app:
    container_name: cname
    restart: always
    build: .
    depends_on:
      - postgres
  postgres:
    image: postgres
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pw
      POSTGRES_DB: db
    ports:
      - '5432:5432'
    volumes:
      - db-volume:/var/lib/postgresql/data

volumes:
  db-volume:

The app itself is working properly. A docker image is created and stored in the GCP Container Registry after making a commit on master but how do I run this container together with the Postgres Container?

Upvotes: 0

Views: 903

Answers (1)

guillaume blaquiere
guillaume blaquiere

Reputation: 75940

You have 2 solutions.

  • Either you use Docker Compose
  • Or you use GCE with container image

With Docker Compose you don't use a GCE feature, you simply run a command at startup. If you want to do that, you can define a startup script. My recommendation is to store it on Google Cloud Storage and to reference it in your startup script url (don't forget to grant the correct role and scope on your compute engine to let it accessing the file).

Then, everytime that you deploy a new version, you update (with github action) the startup script in GCS with the latest image tag (with the GIT_SHA value) and you reset your GCE to restart it and replay the startup script (and thus to load the latest image)


Because using docker compose isn't a native feature of GCE (and the fact to maintain it, patch it and so on), I can't recommend this.

It could be better, in term of performance and scalability, to use Cloud SQL for your postgres database, and to deploy only your Node container on GCE. Like this, you will be able to use the GCE with container image feature out of the box.


But this solution isn't yet perfect. you have only 1 VM, that you have to monitor, to update, patch,... The ultimate solution is to use the brand new autopilot mode for GKE to host your Node container, or Cloud Run if your Node container only answer to HTTP requests.

Upvotes: 1

Related Questions