Docker & Docker Compose
Multi-Stage Dockerfile
Section titled “Multi-Stage Dockerfile”The repository includes a production-ready multi-stage Dockerfile:
# Stage 1: Build Rust CLI binary and Python wheelFROM rust:1.75-bookworm AS builder
RUN apt-get update && apt-get install -y \ libssl-dev pkg-config python3 python3-pip python3-venv
WORKDIR /appCOPY Cargo.toml Cargo.lock ./COPY crates/ crates/COPY python/ python/
RUN python3 -m venv /opt/venvENV PATH="/opt/venv/bin:$PATH"RUN pip install maturinRUN cargo build --release -p justapi-cli --features tls,compressionRUN maturin build -m crates/justapi-py/Cargo.toml --release -o wheels/
# Stage 2: Minimal runtimeFROM python:3.12-slim-bookwormRUN apt-get update && apt-get install -y ca-certificates libssl3
WORKDIR /appCOPY --from=builder /app/target/release/justapi /usr/local/bin/justapiCOPY --from=builder /app/wheels /tmp/wheelsRUN pip install --no-cache-dir /tmp/wheels/*.whl
COPY . .EXPOSE 8080CMD ["python", "app.py"]Build the Image
Section titled “Build the Image”docker build -t my-justapi-app .docker run -p 8080:8080 my-justapi-appDocker Compose (Development)
Section titled “Docker Compose (Development)”version: "3.9"services: justapi: build: . ports: - "8080:8080" environment: - RUST_LOG=info - DATABASE_URL=postgres://justapi:justapi@db:5432/justapi depends_on: db: condition: service_healthy
db: image: postgres:16-alpine environment: POSTGRES_USER: justapi POSTGRES_PASSWORD: justapi POSTGRES_DB: justapi healthcheck: test: ["CMD-SHELL", "pg_isready -U justapi"] interval: 5s timeout: 5s retries: 5docker compose up -dOpenTelemetry Stack
Section titled “OpenTelemetry Stack”Generated projects include docker-compose.otel.yml:
services: jaeger: image: jaegertracing/all-in-one:latest ports: - "16686:16686" # UI - "4318:4318" # OTLP HTTPUsing uv in Docker (Smaller & Faster Builds)
Section titled “Using uv in Docker (Smaller & Faster Builds)”For smaller Docker images and faster builds, replace pip with uv in your Dockerfile:
FROM python:3.12-slim-bookworm AS builderRUN pip install uvCOPY --from=builder /app/wheels /tmp/wheelsRUN uv pip install --system --no-cache /tmp/wheels/*.whlThis reduces layer size and install time significantly.
Production Image Optimizations
Section titled “Production Image Optimizations”- Use
python:3.12-slim— Small image (~120 MB) - Set
panic = "abort"— Already configured in Cargo.toml - Run as non-root — Use
USER nobodyor create an app user - Add HEALTHCHECK — Use
/healthendpoint - Use
.dockerignore— Exclude target/, .git/, pycache/
Example Production Dockerfile Snippet
Section titled “Example Production Dockerfile Snippet”FROM python:3.12-slim-bookwormRUN adduser --disabled-password --gecos '' appuserWORKDIR /appCOPY --from=builder /app/target/release/justapi /usr/local/bin/justapiCOPY --from=builder /app/wheels /tmp/wheelsRUN pip install --no-cache-dir /tmp/wheels/*.whl && rm -rf /tmp/wheelsCOPY app.py .USER appuserEXPOSE 8080HEALTHCHECK --interval=30s --timeout=3s CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"CMD ["python", "app.py"]See Also
Section titled “See Also”- Kubernetes / Helm — Orchestrate with K8s
- Production Checklist — Production readiness
- Docker Compose File