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.
First things first, you need to make sure Cloud Build is allowed to run in your GCP project.
You need two key files in the root of your GitHub repository: Dockerfile and cloudbuild.yaml.
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.
# 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
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.
Now, let's connect Cloud Build to your GitHub repository.
That's it for setup!
Now, whenever you push a commit to the specific branch (main in our example) of your connected GitHub repository:
Enjoyed this blog post? Check out these related posts!
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
A practical guide to implementing middleware in FastAPI for better performance, security, and efficiency.
Read More..
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
Push code, deploy automatically: A simple CI/CD guide for your web app.
Read More..
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.