Docker & Containerization

The Nine Line project leverages Docker and Docker Compose to provide a consistent, reproducible, and isolated environment for development, testing, and production.

Docker logo

How Docker Works in This Project

  • Isolation: Each service (API, database, cache) runs in its own container, ensuring dependencies do not conflict and making it easy to scale or replace components.

  • Consistency: Developers and CI/CD pipelines use the same container images, reducing "it works on my machine" issues.

  • Orchestration: Docker Compose manages multi-container setups, allowing you to start the entire stack with a single command.


Main Docker Components

1. docker-compose.yml (Project Root)

This file orchestrates all services required for the application:

  • pool-appointment-api: The main backend API (Node.js, Express, Prisma)

  • db: PostgreSQL database

  • redis: Redis cache

Example:

version: '3.8'
services:
  db:
    image: postgres:16
    container_name: db
    restart: always
    environment:
      POSTGRES_DB: pool_appointments
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - nine-line-net

  redis:
    image: redis:7
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    networks:
      - nine-line-net

  pool-appointment-api:
    build:
      context: .
      dockerfile: ./apis/pool-appointment-api/Dockerfile
    container_name: pool-appointment-api
    env_file:
      - ./apis/pool-appointment-api/.env
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
    networks:
      - nine-line-net

volumes:
  db_data:

networks:
  nine-line-net:
    driver: bridge

2. apis/pool-appointment-api/Dockerfile

This Dockerfile builds and runs the backend API. Key steps:

  • Base Image: Uses Node.js 20 for compatibility and performance.

  • Copy Files: Copies the monorepo’s root files, shared packages, and the API source code.

  • Install Dependencies: Installs all dependencies at the root level for monorepo compatibility.

  • Build: Runs Prisma client generation and builds the TypeScript code.

  • Entrypoint: Runs a setup script that handles database migrations, seeding, and starts the API.

Key Excerpt:

FROM node:20
WORKDIR /app
COPY package*.json ./
COPY tsconfig.json ./
COPY packages ./packages
COPY apis/pool-appointment-api ./apis/pool-appointment-api
RUN npm install
WORKDIR /app/apis/pool-appointment-api
RUN npx prisma generate
RUN npm run build
EXPOSE 3000
CMD npm run setup

3. Other Dockerfiles

If you add more applications (e.g., apps/web for the frontend), each can have its own Dockerfile following a similar pattern:

  • Set up the working directory

  • Copy only the necessary files

  • Install dependencies

  • Build the application

  • Expose the required port

  • Set the startup command


How to Use

  • Start all services:

    docker-compose up --build
  • Stop all services:

    docker-compose down
  • View logs:

    docker-compose logs -f

Benefits

  • Easy onboarding: New developers can start all services with a single command.

  • Reproducibility: The same environment is used in development, testing, and production.

  • Scalability: Each service can be scaled independently.


Last updated