Docker Configuration
CORTEX uses Docker for containerization and local development.
Local Development
docker-compose.yml
# infra/docker/docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: cortex-postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: cortex
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: cortex-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:
redis-data:
Commands
# Start services
docker-compose -f infra/docker/docker-compose.yml up -d
# View logs
docker-compose -f infra/docker/docker-compose.yml logs -f
# Stop services
docker-compose -f infra/docker/docker-compose.yml down
# Reset data
docker-compose -f infra/docker/docker-compose.yml down -v
Core Service Dockerfile
# apps/core/Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Copy package files
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/core/package.json ./apps/core/
COPY packages/shared-types/package.json ./packages/shared-types/
# Install dependencies
RUN pnpm install --frozen-lockfile
# Copy source
COPY apps/core ./apps/core
COPY packages/shared-types ./packages/shared-types
# Generate Prisma client
RUN cd apps/core && pnpm prisma generate
# Build
RUN pnpm --filter core build
# Production stage
FROM node:20-alpine AS production
WORKDIR /app
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Copy built files
COPY --from=builder /app/apps/core/dist ./dist
COPY --from=builder /app/apps/core/package.json ./
COPY --from=builder /app/apps/core/prisma ./prisma
COPY --from=builder /app/node_modules ./node_modules
# Set environment
ENV NODE_ENV=production
ENV PORT=8091
EXPOSE 8091
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8091/health || exit 1
CMD ["node", "dist/main.js"]
Building Images
# Build core service
docker build -t cortex-core:latest -f apps/core/Dockerfile .
# Build with specific tag
docker build -t cortex-core:v1.0.0 -f apps/core/Dockerfile .
# Build for multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 \
-t cortex-core:latest -f apps/core/Dockerfile .
Running Containers
# Run with environment file
docker run -d \
--name cortex-core \
--env-file .env \
-p 8091:8091 \
cortex-core:latest
# Run with inline environment
docker run -d \
--name cortex-core \
-e DATABASE_URL="postgresql://..." \
-e JWT_SECRET="..." \
-p 8091:8091 \
cortex-core:latest
# View logs
docker logs -f cortex-core
# Enter container
docker exec -it cortex-core sh
Full Stack Docker Compose
# docker-compose.full.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: cortex
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
core:
build:
context: .
dockerfile: apps/core/Dockerfile
ports:
- "8091:8091"
environment:
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/cortex
JWT_SECRET: development-jwt-secret-key-at-least-32-chars
JWT_REFRESH_SECRET: development-refresh-secret-at-least-32-chars
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
web:
build:
context: .
dockerfile: apps/cortex-web/Dockerfile
ports:
- "3090:3000"
environment:
NEXT_PUBLIC_API_URL: http://localhost:8091
depends_on:
- core
volumes:
postgres-data:
redis-data:
Docker Best Practices
1. Multi-stage Builds
Separate build and runtime stages to minimize image size.
2. Non-root User
# Create non-root user
RUN addgroup -S app && adduser -S app -G app
USER app
3. Health Checks
Always include health checks for container orchestration.
4. Layer Caching
Order Dockerfile commands to maximize cache hits:
- System packages
- Package files (package.json)
- Install dependencies
- Copy source code
- Build
5. .dockerignore
node_modules
.git
.env*
*.md
coverage
dist