| name | docker-setup |
| description | Setup and create Dockerfiles, Docker Compose, and container build configurations for Todo application |
| allowed-tools | Bash, Write, Read, Glob, Edit |
Docker Setup Skill
Quick Start
- Read Phase 4 Constitution -
prompts/constitution-prompt-phase-4.md - Check existing files - Use
Globto find existingDockerfile*ordocker-compose.yml - Create Dockerfiles - One for each service (frontend, backend, mcp-server)
- Create docker-compose.yml - For local development
- Create .dockerignore files - Optimize build context
- Build and test images - Verify containers start correctly
Containerization Overview
This project requires 3 containerized services:
| Service | Base Image | Runtime Port | Purpose |
|---|---|---|---|
| Frontend | node:20-alpine | 3000 | Next.js + ChatKit UI |
| Backend | python:3.13-slim | 8000 | FastAPI + Agents SDK |
| MCP Server | python:3.13-slim | 8001 | FastMCP task tools |
Frontend Dockerfile Pattern
Create frontend/Dockerfile:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci
# Copy source and build
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine AS runner
WORKDIR /app
# Set environment
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Create non-root user
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Copy from builder
COPY --from=builder /app/public ./public
COPY --from=builder --app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
# Set permissions
RUN chown -R nextjs:nodejs /app
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
Requirements for Next.js:
output: "standalone"innext.config.jsnpm run buildcreates.next/standalonedirectory
Backend Dockerfile Pattern
Create backend/Dockerfile:
# Builder stage
FROM python:3.13-slim AS builder
WORKDIR /app
# Install uv and build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir uv
# Copy dependencies
COPY pyproject.toml uv.lock ./
# Install to .venv
RUN uv sync --frozen --no-dev
# Runtime stage
FROM python:3.13-slim
WORKDIR /app
# Install uv for runtime
RUN pip install --no-cache-dir uv
# Copy .venv from builder
COPY --from=builder /app/.venv /app/.venv
# Copy application code
COPY src/ ./src/
COPY alembic/ ./alembic/
# Create non-root user
RUN useradd -m -u 1000 appuser && \
chown -R appuser:appuser /app
USER appuser
# Activate venv
ENV PATH="/app/.venv/bin:$PATH"
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
MCP Server Dockerfile Pattern
Create backend/Dockerfile.mcp:
FROM python:3.13-slim
WORKDIR /app
# Install FastMCP and dependencies
RUN pip install --no-cache-dir fastmcp mcp openai litellm
# Copy MCP server code
COPY mcp_server/ ./mcp_server/
EXPOSE 8001
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8001/health || exit 1
CMD ["python", "-m", "mcp_server.server"]
Docker Compose Setup
Create docker-compose.yml in project root:
version: '3.9'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: todo-frontend
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- NEXT_PUBLIC_API_URL=http://backend:8000
- NEXT_PUBLIC_MCP_URL=http://mcp-server:8001
depends_on:
backend:
condition: service_healthy
mcp-server:
condition: service_healthy
networks:
- todo-network
restart: unless-stopped
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: todo-backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=${DATABASE_URL}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- MCP_SERVER_URL=http://mcp-server:8001
depends_on:
mcp-server:
condition: service_healthy
networks:
- todo-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
mcp-server:
build:
context: ./backend
dockerfile: Dockerfile.mcp
container_name: todo-mcp-server
ports:
- "8001:8001"
environment:
- GEMINI_API_KEY=${GEMINI_API_KEY}
networks:
- todo-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
todo-network:
driver: bridge
Create .env file (don't commit to git):
DATABASE_URL=postgresql://user:password@host:5432/todo_db
GEMINI_API_KEY=your-gemini-api-key
BETTER_AUTH_SECRET=your-auth-secret
.dockerignore Files
Frontend .dockerignore
Create frontend/.dockerignore:
node_modules
.next
.git
.gitignore
README.md
.DS_Store
.env.local
.env.production.local
*.log
npm-debug.log*
yarn-error.log*
.vscode
.idea
coverage
Backend .dockerignore
Create backend/.dockerignore:
__pycache__
*.pyc
*.pyo
*.pyd
.Python
.venv
env/
venv/
ENV/
.git
.gitignore
.env
*.log
.pytest_cache/
.coverage
htmlcov/
.tox/
.mypy_cache/
.dmypy.json
dmypy.json
.pyrepl.json
.DS_Store
.vscode
.idea
Docker AI (Gordon) Integration
When Docker AI (Gordon) is available:
Enabling Gordon
- Install Docker Desktop 4.53+
- Go to Settings → Beta features
- Toggle "Docker AI" on
Using Gordon Commands
# Check capabilities
docker ai "What can you do?"
# Generate Dockerfile
docker ai "Create a Dockerfile for FastAPI application"
# Optimize Dockerfile
docker ai "Optimize this Dockerfile for smaller image size" < Dockerfile
# Debug build issues
docker ai "Why is my container crashing on startup?"
# Security scan
docker ai "Scan this image for security vulnerabilities" todo-backend:latest
# Multi-stage build
docker ai "Convert this to a multi-stage Dockerfile" < Dockerfile
Build Commands
# Build individual images
docker build -t todo-frontend:latest ./frontend
docker build -t todo-backend:latest ./backend
docker build -t todo-mcp-server:latest -f backend/Dockerfile.mcp ./backend
# Build without cache
docker build --no-cache -t todo-frontend:latest ./frontend
# Build with build args
docker build --build-arg NODE_ENV=production -t todo-frontend:latest ./frontend
# Using Docker Compose
docker-compose build
docker-compose up -d
docker-compose down
docker-compose logs -f
# Tag for registry
docker tag todo-frontend:latest docker.io/username/todo-frontend:v1.0.0
Run Commands
# Run individual containers
docker run -d -p 3000:3000 --name todo-frontend todo-frontend:latest
docker run -d -p 8000:8000 --name todo-backend todo-backend:latest
docker run -d -p 8001:8001 --name todo-mcp-server todo-mcp-server:latest
# Run with environment variables
docker run -d \
-p 8000:8000 \
-e DATABASE_URL=${DATABASE_URL} \
-e GEMINI_API_KEY=${GEMINI_API_KEY} \
--name todo-backend todo-backend:latest
# Run with volume mount (for development)
docker run -d \
-p 8000:8000 \
-v $(pwd)/backend/src:/app/src \
--name todo-backend todo-backend:latest
Verification Checklist
After setup, verify:
- All Dockerfiles created (frontend, backend, mcp-server)
- docker-compose.yml created in project root
- .dockerignore files created for each service
- .env file created and added to .gitignore
- Frontend Dockerfile uses multi-stage build
- Backend Dockerfile uses non-root user
- All containers have health checks
- Images build successfully
-
docker-compose up -dstarts all services - Services can communicate via Docker network
- Gordon commands work (if available)
Troubleshooting
| Issue | Likely Cause | Solution |
|---|---|---|
npm ci fails |
node_modules exists | Remove node_modules first |
| Build timeout | Large context | Check .dockerignore |
| Container exits immediately | Entry point error | Verify CMD and healthcheck |
| Port already in use | Previous container | docker-compose down first |
| Can't connect to DB | Wrong network name | Use Docker Compose network |
| Permission denied | Running as root | Ensure non-root user in Dockerfile |
Next Steps
After Docker setup:
- Test locally with
docker-compose up -d - Access frontend at http://localhost:3000
- Verify backend health at http://localhost:8000/health
- Proceed to Kubernetes deployment with
@devops-kubernetes-builder