fetch_ml/build/docker/secure-prod.Dockerfile
Jeremie Fraeys cb142213fa
chore(build): update build system, Dockerfiles, and dependencies
Build and deployment improvements:

Makefile:
- Native library build targets with ASan support
- Cross-platform compilation helpers
- Performance benchmark targets
- Security scan integration

Docker:
- secure-prod.Dockerfile: Hardened production image (non-root, minimal surface)
- simple.Dockerfile: Lightweight development image

Scripts:
- build/: Go and native library build scripts, cross-platform builds
- ci/: checks.sh, test.sh, verify-paths.sh for validation
- benchmarks/: Local performance testing and regression tracking
- dev/: Monitoring setup

Dependencies: Update to latest stable with security patches

Commands:
- api-server/main.go: Server initialization updates
- data_manager/data_sync.go: Data sync with visibility
- errors/main.go: Error handling improvements
- tui/: TUI improvements for group management
2026-03-08 13:03:48 -04:00

100 lines
4.1 KiB
Docker

# Secure Production Dockerfile with cache optimization
# Build with: DOCKER_BUILDKIT=1 docker build --build-arg WORKER_PASSWORD=$(openssl rand -base64 32) -f build/docker/secure-prod.Dockerfile .
# ============================================================================
# STAGE 1: Go Dependencies (cached layer)
# ============================================================================
FROM golang:1.25-alpine AS go-deps
RUN apk add --no-cache git make gcc musl-dev
WORKDIR /app
# Copy only module files first for maximum cache efficiency
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download && \
go mod verify
# ============================================================================
# STAGE 2: Go Builder
# ============================================================================
FROM go-deps AS go-builder
# Copy source code (changes here won't rebuild deps layer)
COPY cmd/ ./cmd/
COPY internal/ ./internal/
COPY pkg/ ./pkg/
COPY tools/ ./tools/
# Build Go binaries with cache mount for build cache
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=1 go build -ldflags="-w -s" -o bin/api-server ./cmd/api-server/main.go && \
CGO_ENABLED=1 go build -ldflags="-w -s" -o bin/worker ./cmd/worker
# ============================================================================
# STAGE 3: Final Runtime with Podman and secure SSH
# ============================================================================
FROM alpine:3.19
# Build argument for worker password (no hardcoded secrets)
ARG WORKER_PASSWORD=changeme
ENV WORKER_PASSWORD=$WORKER_PASSWORD
# Create app user and worker user, configure SSH in combined layer
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup && \
addgroup -g 1002 -S workergroup && \
adduser -u 1002 -S worker -G workergroup -s /bin/sh && \
echo "worker:$WORKER_PASSWORD" | chpasswd && \
mkdir -p /home/worker/.ssh && \
chown -R worker:workergroup /home/worker && \
\
# Generate SSH keys for worker user
ssh-keygen -t rsa -b 4096 -f /home/worker/.ssh/id_rsa -N "" && \
cp /home/worker/.ssh/id_rsa.pub /home/worker/.ssh/authorized_keys && \
chmod 700 /home/worker/.ssh && \
chmod 600 /home/worker/.ssh/id_rsa && \
chmod 644 /home/worker/.ssh/id_rsa.pub /home/worker/.ssh/authorized_keys && \
chown -R worker:workergroup /home/worker/.ssh && \
\
# Configure SSH daemon securely
echo "Port 2222" >> /etc/ssh/sshd_config && \
echo "PermitRootLogin no" >> /etc/ssh/sshd_config && \
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config && \
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config && \
echo "AuthorizedKeysFile %h/.ssh/authorized_keys" >> /etc/ssh/sshd_config && \
echo "AllowUsers worker" >> /etc/ssh/sshd_config && \
echo "MaxAuthTries 3" >> /etc/ssh/sshd_config && \
echo "ClientAliveInterval 300" >> /etc/ssh/sshd_config && \
echo "ClientAliveCountMax 2" >> /etc/ssh/sshd_config && \
echo "X11Forwarding no" >> /etc/ssh/sshd_config && \
echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config && \
echo "Banner /etc/ssh/banner" >> /etc/ssh/sshd_config && \
\
# Create SSH banner
echo "=================================================" > /etc/ssh/banner && \
echo " ML Experiments Production Server" >> /etc/ssh/banner && \
echo " Unauthorized access is prohibited" >> /etc/ssh/banner && \
echo "=================================================" >> /etc/ssh/banner && \
\
# Generate SSH host keys
ssh-keygen -A && \
\
# Give appuser sudo permissions for SSH and worker user for Podman
echo "appuser ALL=(ALL) NOPASSWD: /usr/sbin/sshd" >> /etc/sudoers && \
echo "worker ALL=(ALL) NOPASSWD: /usr/bin/podman" >> /etc/sudoers
# Switch to app user for application
USER appuser
# Expose ports
EXPOSE 9101 2222
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -k -f https://localhost:9101/health || exit 1
# Default command for API server
CMD ["/usr/local/bin/api-server", "-config", "/app/configs/api/prod.yaml"]