QTPortfolio
Docker & CI/CD: Automating Deployments with GitHub Actions
DockerGitHub ActionsCI/CDDevOps

Docker & CI/CD: Automating Deployments with GitHub Actions

April 6, 20262 min read~203 words

Why Automate Deployments?

Manual deployments are error-prone and time-consuming. A CI/CD pipeline gives you confidence that every change has passed tests before it reaches production.

The Pipeline Structure

My GitHub Actions workflow has three jobs that run in sequence:

  1. test-backend — Runs Gradle tests on Java 21
  2. test-frontend — Runs pnpm build on Node 22
  3. docker-build — Builds both Docker images (only if tests pass)
jobs:
  test-backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { java-version: '21', distribution: 'temurin' }
      - run: cd backend && ./gradlew test

  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: cd frontend && npm i -g pnpm && pnpm install && pnpm build

Multi-Stage Docker Builds

Multi-stage builds keep image sizes small. For the Spring Boot backend, the final image is only ~200MB:

# Stage 1: Build
FROM gradle:8.5-jdk21 AS builder
WORKDIR /app
COPY . .
RUN gradle bootJar --no-daemon

# Stage 2: Run
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

Key Takeaways

  • Always run tests before building Docker images
  • Use multi-stage builds to minimize image size
  • Store secrets in GitHub Actions secrets, never in code

Enjoyed this article?

Share it with your network or explore more posts below.