# Multi-stage build for GitCitadel Online # Using Alpine Linux for smaller image size (~50MB vs ~200MB+ for Debian) # Alpine works well here because: # - Go binary is statically compiled (CGO_ENABLED=0) # - Node.js packages are pure JavaScript (no native bindings) # - No C library dependencies required # Stage 1: Build Go application FROM golang:1.22-alpine AS builder # Install build dependencies RUN apk add --no-cache git # Set working directory WORKDIR /build # Copy go mod files COPY go.mod go.sum ./ RUN go mod download # Copy source code COPY . . # Build the application RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags='-w -s' -o gitcitadel-online ./cmd/server # Stage 2: Runtime with Node.js for AsciiDoc processing FROM node:20-alpine # Install runtime dependencies (wget for health check and nostr-tools download) RUN apk add --no-cache ca-certificates tzdata wget # Set working directory WORKDIR /app # Install Node.js dependencies for AsciiDoc processing COPY package.json package-lock.json ./ RUN npm ci --only=production # Copy built binary from builder COPY --from=builder /build/gitcitadel-online /app/gitcitadel-online # Copy static files and templates COPY static/ ./static/ COPY templates/ ./templates/ # Download nostr-tools bundle if not present (for contact form) RUN if [ ! -f ./static/js/nostr.bundle.js ]; then \ mkdir -p ./static/js && \ wget -O ./static/js/nostr.bundle.js https://unpkg.com/nostr-tools@latest/lib/nostr.bundle.js || \ echo "Warning: Failed to download nostr-tools bundle"; \ fi # Copy example config (user should mount their own config.yaml) COPY config.yaml.example ./config.yaml.example # Create cache directories RUN mkdir -p cache/media # Create non-root user for security RUN addgroup -g 1000 appuser && \ adduser -D -u 1000 -G appuser appuser && \ chown -R appuser:appuser /app # Switch to non-root user USER appuser # Expose port (default 8080, can be overridden via config) EXPOSE 8080 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 # Run the application ENTRYPOINT ["/app/gitcitadel-online"] CMD ["--config", "/app/config.yaml"]