Scalable Blog with GCP Hosting

Architecture Overview

Frontend & Backend: A web app (e.g., Flask, Node.js, or Django).

Database: Cloud SQL (PostgreSQL or MySQL) to store blog posts, users, comments, etc.

Media: Cloud Storage for hosting images or other static files.

Deployment: Docker container running on Cloud Run.

Set up your project
gcloud projects create blog-project-123
gcloud config set project blog-project-123
gcloud services enable run sqladmin storage.googleapis.com \
    compute.googleapis.com artifactregistry.googleapis.com
Design your blog backend

Pick your stack:

  • Flask (Python)
  • Express (Node.js)
  • Django (Python)
  • Laravel (PHP)

In this tutorial, we will use Flask + PostgreSQL app.

Example Routes:

  • / – List blog posts
  • /post/<id> – View a single post
  • /admin – Write/edit posts

Example models.py:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255))
    content = db.Column(db.Text)
    image_url = db.Column(db.String(255))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
Create Cloud SQL
gcloud sql instances create blog-db \
--database-version=POSTGRES_13 \
--cpu=1 --memory=4GB --region=us-central1 \
--root-password=mysecurepassword

Create the database:

gcloud sql databases create blogdb --instance=blog-db

You can also use Cloud SQL Proxy for local development.

Use Cloud Storage for media files
gsutil mb -l us-central1 gs://your-blog-media-bucket

Configure it to be public or use signed URLs for uploads. Use it to store:

  • Blog post images
  • Avatars
Dockerize your app

Example Dockerfile:

FROM python:3.10

WORKDIR /app
COPY . /app

RUN pip install -r requirements.txt

ENV PORT=8080
CMD ["gunicorn", "-b", ":8080", "app:app"]
Deploy to Cloud Run

Build image:

gcloud builds submit --tag gcr.io/blog-project-123/blog-app

Deploy:

gcloud run deploy blog-app \
--image gcr.io/blog-project-123/blog-app \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars DB_USER=postgres,DB_PASS=mysecurepassword,DB_NAME=blogdb,INSTANCE_CONNECTION_NAME=blog-project-123:us-central1:blog-db
Connect to Cloud SQL securely

Use Unix socket or Cloud SQL Auth Proxy. In Flask, you'd connect like:

app.config['SQLALCHEMY_DATABASE_URI'] = \
  'postgresql+psycopg2://user:password@/blogdb?host=/cloudsql/blog-project-123:us-central1:blog-db'
Secure and Optimize

Set up Cloud Armor to block suspicious traffic.

Use HTTPS with custom domain via Cloud Run settings.

Implement JWT-based authentication or Firebase Auth for admin access.

# Cloud Armor
gcloud compute security-policies create ...
gcloud compute security-policies rules create ...
gcloud compute backend-services update ... --security-policy=...

# HTTPS Custom Domain
gcloud domains verify yourdomain.com
gcloud run domain-mappings create --service=...

# Auth
gcloud run services update blog-app --no-allow-unauthenticated
Add CI/CD

Use Cloud Build to automate builds from GitHub or GitLab:

.cloudbuild.yaml:

steps:
- name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/blog-app', '.']
- name: 'gcr.io/cloud-builders/gcloud'
    args: ['run', 'deploy', 'blog-app', '--image', 'gcr.io/$PROJECT_ID/blog-app', '--region', 'us-central1', '--platform', 'managed']