Lesson 06 Push-to-Deploy
Theme:
Lesson 06 · Slide 1

Lesson 06 — Push-to-Deploy

From a signed image in GHCR to a running container in the cloud — with environment-scoped secrets and a blue/green pattern.

Cloud & DevOps Module 2

Lesson 06 · Slide 2

What we have so far

L06 closes that gap: we wire a deploy job that fires after Security & Sign and SSHes to a target to run the new image.

Lesson 06 · Slide 3

The deploy spectrum

Manual

docker run on a VM by hand

  • You SSH in and type commands
  • Easy to reason about
  • Hard to audit, easy to forget
  • Does not scale past a couple of servers

Fully automated (GitOps)

GitOps reconciliation — L14

  • A controller watches the repo and reconciles
  • Every change is auditable via Git history
  • Requires more tooling up-front
  • The gold standard for Kubernetes workloads

Today: one step right of manual — a CI job invokes the deploy on push to main.

Lesson 06 · Slide 4

GHCR vs ECR vs other registries

RegistryAuth in GHACost / notes
GHCR (ghcr.io) GITHUB_TOKEN — no extra setup Free with the repo; tight GitHub integration
ECR (<acct>.dkr.ecr.<region>.amazonaws.com) OIDC federation via aws-actions/configure-aws-credentials@v4 AWS IAM-native; no long-lived AWS keys needed
Docker Hub Username + PAT secret Rate-limited free tier; easy mindshare, watch pull quota in CI

We use GHCR for all course labs. The lab guide includes a side note on the ECR variant.

Lesson 06 · Slide 5

Environment-scoped secrets

GitHub Environments (Settings → Environments) let you scope secrets to specific environments such as production or staging. The production environment can require manual approval before its secrets are released to a job.

Lesson 06 · Slide 6

Defining an environment in a workflow

deploy:
  environment:
    name: production
    url: https://shortener.example.com

When this job runs, GitHub checks the production environment policy. If a required reviewer is configured, the job blocks until that reviewer approves in the GitHub Actions UI. Only then are the production secrets injected and the steps begin executing.

Lesson 06 · Slide 7

The deploy step: simplest version (SSH to a VM)

- uses: appleboy/ssh-action@v1
  with:
    host: ${{ secrets.DEPLOY_HOST }}
    username: ${{ secrets.DEPLOY_USER }}
    key: ${{ secrets.DEPLOY_KEY }}
    script: |
      docker pull ghcr.io/$ORG/$REPO/api:${{ github.sha }}
      docker compose -f /opt/shortener/docker-compose.yml up -d
Lesson 06 · Slide 8

Blue/green basics

  ┌──────────────────────────────────────────────────┐
  │                  Load Balancer / Router           │
  └─────────────────┬────────────────────────────────┘
                    │  ◀── traffic flows here
          ┌─────────▼──────────┐   ┌────────────────────┐
          │    BLUE (live)      │   │   GREEN (idle)      │
          │  api:sha-a1b2c3d    │   │  api:sha-e4f5g6h    │
          └────────────────────┘   └────────────────────┘
  
Lesson 06 · Slide 9

Blue/green in a workflow (sketch)

- name: Deploy to blue
  run: ./deploy.sh blue ${{ github.sha }}

- name: Smoke test blue
  run: curl -fsS https://blue.shortener.example.com/healthz

- name: Flip traffic
  run: ./flip.sh blue
Lesson 06 · Slide 10

Tag your deploys with the digest

Deploying by digest (@sha256:…) instead of a mutable tag (:latest) prevents the surprise of a silently mutated tag.

# Risky: tag can be overwritten
docker pull ghcr.io/org/repo/api:latest

# Safe: digest is content-addressable, immutable
docker pull ghcr.io/org/repo/api@sha256:abc123...
Lesson 06 · Slide 11

Rollback strategy

Three options, from simplest to most GitOps-consistent:

OptionHowSpeed
Re-deploy previous digest Re-run the previous Deploy workflow run in the Actions UI, or SSH and set IMAGE_TAG to the previous digest manually Minutes — needs the digest recorded
Blue/green flip Run ./flip.sh <old-slot> to point the router back Seconds — only available with blue/green standing
Git revert + auto-deploy Revert the offending commit; CI re-deploys automatically Slowest; most consistent with GitOps (L14)

All three need the previous digest written down somewhere. Design your pipeline to emit it.

Lesson 06 · Slide 12

What we’ll build in lab

End state: push to main → CI (L04) → Security & Sign (L05) → Deploy (L06). Three automated stages, one manual gate, one running container.

Lesson 06 · Slide 13

Common gotchas

Lesson 06 · Slide 14

Recap & what’s next

Coming up: Module 3 — actually provision the VM and replace the SSH stub with a real Terraform-managed target, plus infrastructure as code foundations.
1 / ?