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:
-
Development Environments:
-
Local development using Docker Compose
-
Consistent environments across developer machines
-
Testing:
-
Integration tests with containerized dependencies
-
Isolated test environments
-
Deployment:
- Production-ready container images
- Cloud Run deployment targets
Dockerfile Structure
Most services in the repository use multi-stage builds with:
- Base stage: Common dependencies and tools
- Build stage: Compiles the application
- 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 environmentscompose.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:
- docker-bake.hcl: Defines build targets for Docker Buildx
- build-affected-services.sh: Builds only affected services
- 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
- Use multi-stage builds to reduce image size
- Order commands by change frequency (less frequent changes first)
- Leverage build cache by structuring Dockerfiles efficiently
- Minimize the build context by using
.dockerignore
- Use specific base image versions for reproducible builds