HomeBlog

Simple CI/CD for Your FastAPI App with Cloud Build and Cloud Run

3 min read

David Muraya Blog Header Image

Tired of manually building and deploying your FastAPI app every time you make a change? There's a much smoother way using Google Cloud. Let's set up a simple Continuous Integration and Continuous Deployment (CI/CD) pipeline.

When you push code changes to your GitHub repository, this pipeline will automatically build a container image and deploy it to Google Cloud Run. We'll use Google Cloud Build to handle the building and pushing, and Cloud Run to run our container without worrying about servers.

This means faster updates, fewer mistakes, and more time for you to focus on writing code.

What You'll Need:

  1. A Google Cloud Platform (GCP) project.
  2. Your FastAPI application code hosted in a GitHub repository.
  3. A Dockerfile in your repository to build your app's container image.
  4. A cloudbuild.yaml file in your repository to tell Cloud Build what to do.

Step 1: Enable the Cloud Build API

First things first, you need to make sure Cloud Build is allowed to run in your GCP project.

  1. Go to the Google Cloud Console.
  2. Navigate to "APIs & Services" > "Library".
  3. Search for "Cloud Build API".
  4. Click on it and make sure it's "Enabled". If not, click the "Enable" button.

Step 2: Get Your Code Ready (Dockerfile and cloudbuild.yaml)

You need two key files in the root of your GitHub repository: Dockerfile and cloudbuild.yaml.

Your Dockerfile

This file tells Docker how to package your FastAPI application. Here's a sample one. Important: Replace "my-project" in the WORKDIR, COPY, and RUN commands below with the actual name of your application's directory or desired work directory name within the container.

Dockerfile

# Use a specific Python version. Slim-buster is a good lightweight choice.
FROM python:3.11-slim-buster

# Set the working directory inside the container
WORKDIR /my-project

# Install system packages needed (like ffmpeg if your app uses it, gcc for some Python packages)
# Update package lists, install, then clean up to keep the image small
RUN apt-get update && \
    apt-get install -y \
    gcc \
    ffmpeg \
    && rm -rf /var/lib/apt/lists/*

# Copy just the requirements file first. Docker caches this layer.
# If requirements.txt doesn't change, Docker reuses the cached layer, speeding up builds.
COPY ./requirements.txt /my-project/requirements.txt

# Install Python dependencies
RUN pip install --no-cache-dir --upgrade -r /my-project/requirements.txt

# Copy the rest of your application code
# Assumes your FastAPI code is in a directory named 'app'
COPY ./app /my-project/app

# Command to run your application when the container starts
# Uses gunicorn as the web server, binding to the port provided by Cloud Run ($PORT)
# Adjust workers/threads based on your app's needs and Cloud Run instance size
CMD exec gunicorn --bind :$PORT --workers 4 --worker-class uvicorn.workers.UvicornWorker  --threads 4 -t 60 --max-requests 1000 --max-requests-jitter 50 app.main:app

Your cloudbuild.yaml File

This file tells Cloud Build the steps to take: build the image, push it to Google Container Registry (GCR), and deploy it to Cloud Run.

Important: Replace "my-project" in the args for building, pushing, and deploying with the exact same name you want for your Cloud Run service and container image path.

steps:
  # Step 1: Build the Docker image
  # Uses the standard Docker builder provided by Google Cloud Build
  # Tags the image with the unique commit SHA for easy tracking
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-project:$COMMIT_SHA', '.']

  # Step 2: Push the built image to Google Container Registry (GCR)
  # GCR is Google's private Docker image storage
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/my-project:$COMMIT_SHA']

  # Step 3: Deploy the image to Cloud Run
  # Uses the gcloud command-line tool (also provided as a builder)
  # Deploys a service named "my-project" using the image we just pushed
  # Sets an environment variable (e.g., ENV=LIVE)
  # Specifies the region and project
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'run'
      - 'deploy'
      - 'my-project' # This should be your service name
      - '--image=gcr.io/$PROJECT_ID/my-project:$COMMIT_SHA' # Use the image we built/pushed
      - '--set-env-vars=ENV=LIVE' # Example environment variable
      - '--region=us-central1' # Choose the region for your service
      - '--project=$PROJECT_ID'
      # Add other flags as needed: --memory, --cpu, --allow-unauthenticated, etc.

  # Step 4: Make sure 100% of traffic goes to the new version
  # This ensures the update is live immediately
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'run'
      - 'services'
      - 'update-traffic'
      - 'my-project' # Your service name again
      - '--to-latest'
      - '--region=us-central1' # Same region as deployment
      - '--project=$PROJECT_ID'

# Configure Cloud Build options
options:
  # Send build logs straight to Cloud Logging
  logging: CLOUD_LOGGING_ONLY

Make sure both these files (Dockerfile and cloudbuild.yaml) are committed and pushed to the root of your GitHub repository.

Step 3: Set Up the Cloud Build Trigger

Now, let's connect Cloud Build to your GitHub repository.

  1. In the Google Cloud Console, go to "Cloud Build" > "Triggers".
  2. Click "Create trigger".
  3. Give your trigger a Name (e.g., deploy-fastapi-main).
  4. Under Event, choose "Push to a branch".
  5. Under Source, click "Connect repository". Select "GitHub" as the source.
    • You might need to authenticate with GitHub and authorize Google Cloud Build. -Select your GitHub repository from the list.
  6. In the Configuration section:
    • For Branch, enter the name of the branch you want to trigger deployments from (e.g., main or master).
    • For Build configuration, select "Autodetected". Cloud Build will automatically look for your cloudbuild.yaml or Dockerfile.
  7. Service Account (Important Note): By default, Cloud Build uses a standard service account. This account needs permissions to push to Container Registry and deploy to Cloud Run. If your build fails with permission errors, you might need to:
    • Create a dedicated service account with roles like "Cloud Run Admin" (roles/run.admin) and "Storage Admin" (roles/storage.admin - for GCR).
    • Go back to your trigger settings, find the "Edit Trigger" or "Service Account" section, and select your custom service account.
  8. Click "Create".

Step 4: Push Your Code!

That's it for setup!

Now, whenever you push a commit to the specific branch (main in our example) of your connected GitHub repository:

  1. GitHub notifies Google Cloud Build.
  2. Your Cloud Build trigger fires up.
  3. Cloud Build reads your cloudbuild.yaml file.
  4. It runs the steps: builds the Docker image, pushes it to GCR, and deploys the new version to Cloud Run, updating the traffic. You can watch the build progress in the "History" section of Cloud Build in the Google Cloud Console. Once it's green, your latest changes are live on Cloud Run!

Related Blog Posts

Enjoyed this blog post? Check out these related posts!

Reflex Makes SEO Easier: Automatic robots.txt and sitemap.xml Generation

Reflex Makes SEO Easier: Automatic robots.txt and sitemap.xml Generation

Discover how adding your deploy URL in Reflex automatically generates robots.txt and sitemap.xml for easier SEO.

Read More..

Adding middleware to FastAPI Applications: Process Time, Security, and Compression

Adding middleware to FastAPI Applications: Process Time, Security, and Compression

A practical guide to implementing middleware in FastAPI for better performance, security, and efficiency.

Read More..

Deploying Reflex Front-End with Caddy in Docker

Deploying Reflex Front-End with Caddy in Docker

A step-by-step guide to building and serving Reflex static front-end files using Caddy in a Docker container

Read More..

Simple CI/CD for Your FastAPI App with Google Cloud Build and Cloud Run

Simple CI/CD for Your FastAPI App with Google Cloud Build and Cloud Run

Push code, deploy automatically: A simple CI/CD guide for your web app.

Read More..

Contact Me

Have a project in mind? Send me an email at hello@davidmuraya.com and let's bring your ideas to life. I am always available for exciting discussions.

© 2025 David Muraya. All rights reserved.