Skip to content

[BE-33] CI/CD Pipeline: Docker Compose, GitHub Actions & Deployment Readiness #1026

@mftee

Description

@mftee

Overview

The project has no Docker configuration, no GitHub Actions CI pipeline, no automated deployment script, and relies on synchronize: true in TypeORM (which is dangerous in production). This issue prepares the backend for production deployment.

Technical Details

1. Replace TypeORM synchronize: true

In backend/src/app.module.ts, change TypeOrmModule.forRootAsync:

synchronize: process.env.NODE_ENV === 'development', // NEVER true in production
migrationsRun: process.env.NODE_ENV === 'production', // auto-run migrations in prod
migrations: [__dirname + '/migrations/*.js'],

This is critical — synchronize: true will drop and recreate columns on a production database.

2. Docker Configuration

backend/Dockerfile:

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json .
EXPOSE 6006
CMD ["node", "dist/main.js"]

docker-compose.yml (root):

version: '3.9'
services:
  db:
    image: postgres:16-alpine
    environment: { POSTGRES_DB: freightflow, POSTGRES_USER: postgres, POSTGRES_PASSWORD: postgres }
    ports: ['5432:5432']
    volumes: [pgdata:/var/lib/postgresql/data]
  redis:
    image: redis:7-alpine
    ports: ['6379:6379']
  backend:
    build: ./backend
    ports: ['6006:6006']
    env_file: ./backend/.env
    depends_on: [db, redis]
  frontend:
    build: ./frontend
    ports: ['3000:3000']
    env_file: ./frontend/.env.local
volumes:
  pgdata:

3. GitHub Actions CI (.github/workflows/backend-ci.yml)

name: Backend CI
on:
  push:
    paths: ['backend/**']
  pull_request:
    paths: ['backend/**']
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env: { POSTGRES_DB: freightflow_test, POSTGRES_USER: postgres, POSTGRES_PASSWORD: postgres }
        ports: ['5432:5432']
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm', cache-dependency-path: 'backend/package-lock.json' }
      - run: npm ci
        working-directory: backend
      - run: npm run test
        working-directory: backend
        env: { NODE_ENV: test, DATABASE_URL: postgres://postgres:postgres@localhost:5432/freightflow_test, JWT_SECRET: test-secret }
      - run: npm run build
        working-directory: backend

Add .github/workflows/frontend-ci.yml similarly: npm ci && npm run build && npm run test.

4. Environment Validation

Verify that backend/src/config/env.validation.ts (or equivalent) has Joi schema entries for every env var in .env.example. Any env var missing from Joi validation should throw an error at startup in production.

Acceptance Criteria

  • synchronize is false in production (conditional on NODE_ENV)
  • docker compose up starts the database, Redis, backend, and frontend successfully
  • Backend is accessible at http://localhost:6006/api/v1/health after docker compose up
  • .github/workflows/backend-ci.yml runs tests and build on every PR touching backend/
  • .github/workflows/frontend-ci.yml runs build on every PR touching frontend/
  • All env vars in .env.example are present in the Joi validation schema
  • docker build --tag freightflow-backend ./backend completes without errors
  • The production Docker image runs with NODE_ENV=production (not development)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions