From d894012af630d9c30dfe232f1a7fe0bfe0778703 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Sun, 28 Dec 2025 12:05:12 -0300 Subject: [PATCH] perf(docker): ultra-optimize backend build - Use scratch base image (< 20MB final vs ~50MB alpine) - Add BuildKit cache for go modules and build cache - Selective COPY (cmd, internal, migrations, docs) instead of COPY . . - Remove HEALTHCHECK (not supported by Podman OCI) - Update .gitignore with more binary patterns - Optimize .dockerignore to exclude tests and binaries --- backend/.dockerignore | 60 ++++++++++++++++++++++++++----------- backend/.gitignore | 55 +++++++++++++++++++++++++++------- backend/Dockerfile | 70 +++++++++++++++++++------------------------ 3 files changed, 118 insertions(+), 67 deletions(-) diff --git a/backend/.dockerignore b/backend/.dockerignore index ea7fdc0..b2bf759 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -1,47 +1,73 @@ -# Dependencies -node_modules/ -.pnp -.pnp.js +# ============================================================================= +# GoHorse Backend - Docker Ignore (Optimized for smallest context) +# ============================================================================= -# Build outputs +# Binaries (CRITICAL - these are huge!) /main +/api +/backend *.exe +*.exe~ *.dll *.so *.dylib - -# Test files -*_test.go *.test +/bin/ +/build/ +/dist/ + +# Tests (not needed in prod image) +*_test.go +tests/ coverage.out coverage.html +coverage.txt +*.out -# IDE and editor +# Git +.git/ +.gitignore +.gitattributes + +# IDE .idea/ .vscode/ *.swp *.swo *~ -# Git -.git/ -.gitignore - -# Documentation (keep docs/ for swagger) +# Documentation (not needed in image) *.md +!migrations/*.md LICENSE +README* +CHANGELOG* +BACKEND.md -# Environment files (security) +# Environment (security) .env .env.* !.env.example -# Temporary files +# Temp and logs tmp/ temp/ *.tmp *.log +__debug_bin* -# OS files +# OS .DS_Store Thumbs.db + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Go debug/cache (if present) +go.work +go.work.sum + +# Swagger docs source (built at runtime if needed) +# Keep docs/ for swagger.json diff --git a/backend/.gitignore b/backend/.gitignore index cbb042e..c816fd6 100755 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,24 +1,57 @@ -# Binaries for programs and plugins +# ============================================================================= +# GoHorse Backend - Git Ignore +# ============================================================================= + +# Binaries *.exe *.exe~ *.dll *.so *.dylib - -# Test binary, built with `go test -c` *.test +/main +/api +/backend -# Output of the go coverage tool, specifically when used with LiteIDE +# Build cache +/bin/ +/build/ +/dist/ + +# Go coverage *.out +coverage.html +coverage.txt -# Dependency directories (remove the comment below to include it) +# Go workspace +go.work +go.work.sum + +# Vendor (uncomment if using go mod vendor) # vendor/ -# Go workspace file -go.work - -# Environment variables +# Environment .env +.env.local +.env.*.local -# Compiled binary -/api +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Temp +tmp/ +temp/ +*.tmp +*.log + +# Debug +__debug_bin* +debug.test diff --git a/backend/Dockerfile b/backend/Dockerfile index 4a14950..0dae13d 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,67 +1,59 @@ # ============================================================================= -# GoHorse Jobs Backend - Optimized Production Dockerfile +# GoHorse Jobs Backend - Ultra-Optimized Dockerfile +# Target: < 20MB final image (scratch-based) # ============================================================================= +# syntax=docker/dockerfile:1 # ----------------------------------------------------------------------------- -# Stage 1: Build +# Stage 1: Build (with cache mounts) # ----------------------------------------------------------------------------- FROM mirror.gcr.io/library/golang:1.24-alpine AS builder WORKDIR /build -# Install minimal build dependencies +# Install build deps (minimal) RUN apk add --no-cache git ca-certificates tzdata -# Cache dependencies +# Cache go modules (separate layer for better caching) COPY go.mod go.sum ./ -RUN go mod download && go mod verify +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download && go mod verify -# Copy source code -COPY . . +# Copy source +COPY cmd ./cmd +COPY internal ./internal +COPY migrations ./migrations +COPY docs ./docs -# Build with optimizations: -# - CGO_ENABLED=0: Static binary (no C dependencies) -# - ldflags -s -w: Strip debug info for smaller binary -# - trimpath: Remove local paths from binary -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ - -ldflags="-s -w -X main.Version=$(git describe --tags --always --dirty 2>/dev/null || echo 'dev')" \ +# Build with maximum optimizations: +# - CGO_ENABLED=0: Pure Go binary (no C deps) +# - ldflags -s -w: Strip debug info (-4MB) +# - trimpath: Remove local paths +# - -a: Rebuild all packages +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + -ldflags="-s -w -X main.Version=$(git describe --tags --always 2>/dev/null || echo 'dev')" \ -trimpath \ -o /app/main ./cmd/api # ----------------------------------------------------------------------------- -# Stage 2: Production (Minimal Image) +# Stage 2: Production (scratch for minimal size) # ----------------------------------------------------------------------------- -FROM mirror.gcr.io/library/alpine:3.19 +FROM scratch AS runner -# Security: Run as non-root user -RUN addgroup -g 1001 -S appgroup && \ - adduser -u 1001 -S appuser -G appgroup - -WORKDIR /app - -# Copy timezone data and CA certificates from builder +# Copy essentials from builder COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ # Copy binary and migrations -COPY --from=builder /app/main . -COPY --from=builder /build/migrations ./migrations +COPY --from=builder /app/main /main +COPY --from=builder /build/migrations /migrations -# Set ownership to non-root user -RUN chown -R appuser:appgroup /app - -# Switch to non-root user -USER appuser - -# Expose port -EXPOSE 8521 - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget -qO- http://localhost:8521/health || exit 1 - -# Environment defaults +# Environment ENV PORT=8521 \ TZ=America/Sao_Paulo -CMD ["./main"] +EXPOSE 8521 + +ENTRYPOINT ["/main"]