Skip to content

Docker Primer

What is Docker?

Docker is a platform for developing, shipping, and running applications in containers. Containers are lightweight, isolated environments that package an application and its dependencies. In the v4-monorepo, Docker is used to containerize services for development, testing, and production deployment.

Key Concepts

Containers

  • Container: A lightweight, standalone execution environment for an application
  • Image: A blueprint for creating containers
  • Dockerfile: A script of instructions to build a Docker image
  • Registry: A repository for storing and distributing Docker images

Multi-Stage Builds

Multi-stage builds allow you to use multiple FROM statements in a Dockerfile. Each FROM starts a new build stage that can selectively copy artifacts from previous stages, resulting in smaller final images.

Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications, using a YAML file to configure services, networks, and volumes.

How Docker is Used in This Repository

Container Strategy

In the v4-monorepo, Docker is used for:

  1. Development Environments:

  2. Local development using Docker Compose

  3. Consistent environments across developer machines

  4. Testing:

  5. Integration tests with containerized dependencies

  6. Isolated test environments

  7. Deployment:

  8. Production-ready container images
  9. Cloud Run deployment targets

Dockerfile Structure

Most services in the repository use multi-stage builds with:

  1. Base stage: Common dependencies and tools
  2. Build stage: Compiles the application
  3. Production stage: Minimal runtime environment

Dockerfile Examples

TypeScript Service Dockerfile

A typical Dockerfile for a TypeScript service:

# Base stage
FROM node:22-alpine AS base
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

# Build stage
FROM base AS build
COPY . .
RUN yarn nx build orderbook

# Production stage
FROM node:22-alpine AS production
WORKDIR /app
COPY --from=build /app/dist/apps/orderbook ./
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "index.js"]

Python Service Dockerfile

A typical Dockerfile for a Python service:

# Base stage
FROM python:3.10-slim as base
WORKDIR /app
RUN pip install poetry
COPY pyproject.toml poetry.lock ./

# Build stage
FROM base as build
RUN poetry export -f requirements.txt -o requirements.txt
COPY . .
RUN poetry build

# Production stage
FROM python:3.10-slim as production
WORKDIR /app
COPY --from=build /app/requirements.txt .
COPY --from=build /app/dist/*.whl .
RUN pip install *.whl
EXPOSE 8000
CMD ["python", "-m", "funding.main"]

Docker Compose

The repository uses Docker Compose for local development:

  • compose.base.yml: Base configuration shared across environments
  • compose.dev.yml: Development-specific configuration

Example Docker Compose configuration:

version: '3.8'

services:
  mysql:
    image: mysql:8.4.3
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: kyan
    ports:
      - '3306:3306'
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:7.0
    ports:
      - '6379:6379'

  orderbook:
    build:
      context: .
      dockerfile: apps/orderbook/Dockerfile
    depends_on:
      - mysql
      - redis
    ports:
      - '3000:3000'
    environment:
      DATABASE_URL: mysql://root:root@mysql:3306/kyan
      REDIS_URL: redis://redis:6379

volumes:
  mysql_data:

Common Docker Commands

Basic Commands

# Start the development environment
yarn docker:up

# Stop the development environment
yarn docker:down

# Build Docker images
yarn docker:build

# Clean up Docker resources
yarn docker:cleanup

Advanced Commands

# Run tests in Docker containers
yarn docker:test

# Build a specific service image
docker build -f apps/orderbook/Dockerfile -t orderbook .

# Run a specific container
docker run -p 3000:3000 orderbook

Custom Build Tools

The repository includes several custom build tools:

  1. docker-bake.hcl: Defines build targets for Docker Buildx
  2. build-affected-services.sh: Builds only affected services
  3. Dockerfile.progressive: A template for progressive builds

Docker Bake Example

group "default" {
  targets = ["orderbook", "datastream"]
}

target "orderbook" {
  context = "."
  dockerfile = "apps/orderbook/Dockerfile"
  tags = ["premia/orderbook:latest"]
}

target "datastream" {
  context = "."
  dockerfile = "apps/datastream/Dockerfile"
  tags = ["premia/datastream:latest"]
}

Troubleshooting Docker

Common Issues

Issue Solution
"No space left on device" Run yarn docker:cleanup to free up space
"Image build failure" Check Dockerfile syntax and build context
"Container won't start" Check logs with docker logs <container_id>
"Connection refused" Ensure ports are correctly mapped
"Permission denied" Check user permissions in Docker and host system

Optimizing Docker Builds

  1. Use multi-stage builds to reduce image size
  2. Order commands by change frequency (less frequent changes first)
  3. Leverage build cache by structuring Dockerfiles efficiently
  4. Minimize the build context by using .dockerignore
  5. Use specific base image versions for reproducible builds

Learn More