diff --git a/Dockerfile.appview b/Dockerfile.appview index ee4d8d4..bd35b77 100644 --- a/Dockerfile.appview +++ b/Dockerfile.appview @@ -1,41 +1,71 @@ -# Build stage -FROM golang:1.24-alpine AS builder +# ========================================== +# Stage 1: Build stage with Debian (glibc) +# ========================================== +FROM golang:1.25.2-trixie AS builder -# Install build dependencies (gcc and musl-dev needed for SQLite CGO) -RUN apk add --no-cache git make gcc musl-dev sqlite-dev +# Install SQLite development libraries (for CGO compilation) +RUN apt-get update && \ + apt-get install -y --no-install-recommends sqlite3 libsqlite3-dev && \ + rm -rf /var/lib/apt/lists/* # Set working directory WORKDIR /build -# Copy go mod files +# Copy go mod files and download dependencies (cached layer) COPY go.mod go.sum ./ - -# Download dependencies RUN go mod download # Copy source code COPY . . -# Build the binary with CGO enabled for SQLite support -RUN CGO_ENABLED=1 GOOS=linux go build -a -o atcr-appview ./cmd/appview +# Build optimized binary: +# - CGO_ENABLED=1: Required for SQLite (mattn/go-sqlite3) +# - -ldflags="-s -w": Strip debug symbols (~30% size reduction) +# - -tags sqlite_omit_load_extension: Remove SQLite extension loading (~100KB savings) +# - -trimpath: Remove build paths (reproducible builds) +# SQLite is statically embedded in the binary (no runtime .so needed) +RUN CGO_ENABLED=1 go build \ + -ldflags="-s -w" \ + -tags sqlite_omit_load_extension \ + -trimpath \ + -o atcr-appview ./cmd/appview -# Runtime stage -FROM alpine:latest +# Collect minimal runtime dependencies based on ldd output +RUN mkdir -p /runtime-deps/lib/x86_64-linux-gnu /runtime-deps/lib64 && \ + # Core glibc library (only one the binary links to) + cp -L /lib/x86_64-linux-gnu/libc.so.6 /runtime-deps/lib/x86_64-linux-gnu/ && \ + # Dynamic linker + cp -L /lib64/ld-linux-x86-64.so.2 /runtime-deps/lib64/ && \ + # NSS modules for DNS resolution (loaded via dlopen at runtime, not shown in ldd) + cp -L /lib/x86_64-linux-gnu/libnss_dns.so.2 /runtime-deps/lib/x86_64-linux-gnu/ && \ + cp -L /lib/x86_64-linux-gnu/libnss_files.so.2 /runtime-deps/lib/x86_64-linux-gnu/ && \ + # NSS modules depend on libresolv + cp -L /lib/x86_64-linux-gnu/libresolv.so.2 /runtime-deps/lib/x86_64-linux-gnu/ && \ + # Create NSS config (tells glibc to check /etc/hosts then DNS) + echo "hosts: files dns" > /tmp/nsswitch.conf -# Install CA certificates for HTTPS, SQLite runtime libraries, and sqlite CLI for debugging -RUN apk --no-cache add ca-certificates sqlite-libs sqlite +# ========================================== +# Stage 2: Minimal FROM scratch runtime +# ========================================== +FROM scratch -# Set working directory -WORKDIR /app +# Copy minimal glibc runtime dependencies +COPY --from=builder /runtime-deps / -# Copy binary from builder -COPY --from=builder /build/atcr-appview . +# Copy NSS configuration for DNS resolution +COPY --from=builder /tmp/nsswitch.conf /etc/nsswitch.conf -# Create directories for storage -RUN mkdir -p /var/lib/atcr/blobs /var/lib/atcr/auth +# Copy CA certificates for HTTPS (PDS, Jetstream, relay connections) +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -# Expose ports -EXPOSE 5000 5001 +# Copy timezone data for timestamp formatting +COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo + +# Copy optimized binary (SQLite embedded) +COPY --from=builder /build/atcr-appview /atcr-appview + +# Expose port (main HTTP server) +EXPOSE 5000 # OCI image annotations LABEL org.opencontainers.image.title="ATCR AppView" \ @@ -48,5 +78,6 @@ LABEL org.opencontainers.image.title="ATCR AppView" \ io.atcr.icon="https://imgs.blue/evan.jarrett.net/1TpTNrRelfloN2emuWZDrWmPT0o93bAjEnozjD6UPgoVV9m4" # Run the AppView (no config file - uses environment variables) -ENTRYPOINT ["/app/atcr-appview"] +# Creates /var/lib/atcr directories on first run via Go code +ENTRYPOINT ["/atcr-appview"] CMD ["serve"]