# syntax=docker/dockerfile:1.4 # Production-ready multi-stage build for server deployment # Build arguments ARG GO_VERSION=1.23.6 ARG ALPINE_VERSION=3.19 ARG APP_USER=appuser ARG APP_GROUP=appgroup # --- Builder Stage --- FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS builder # Install build dependencies RUN apk add --no-cache git make gcc libc-dev # Set working directory WORKDIR /build # Enable Go modules ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ GOARCH=amd64 # Copy dependency files first for better layer caching COPY go.mod go.sum ./ # Download dependencies RUN --mount=type=cache,target=/go/pkg/mod \ go mod download # Copy source code COPY . . # Create the configs directory in the build context RUN mkdir -p /build/configs && \ cp -r configs/* /build/configs/ 2>/dev/null || : # Build the application with optimizations RUN --mount=type=cache,target=/root/.cache/go-build \ go build -ldflags="-w -s -X 'main.Version=$(git describe --tags --always 2>/dev/null || echo 'dev')'" \ -o /build/bin/app ./cmd/app # --- Final Stage --- FROM alpine:${ALPINE_VERSION} # Re-declare ARG to use in this stage ARG APP_USER=appuser ARG APP_GROUP=appgroup ARG APP_HOME=/app # Set environment variables ENV TZ=Asia/Ho_Chi_Minh \ APP_USER=${APP_USER} \ APP_GROUP=${APP_GROUP} \ APP_HOME=${APP_HOME} # Install runtime dependencies RUN apk add --no-cache \ ca-certificates \ tzdata \ tini \ && rm -rf /var/cache/apk/* # Create app user and group RUN addgroup -S ${APP_GROUP} && \ adduser -S -G ${APP_GROUP} -h ${APP_HOME} -D ${APP_USER} # Create necessary directories RUN mkdir -p ${APP_HOME}/configs ${APP_HOME}/logs ${APP_HOME}/storage # Switch to app directory WORKDIR ${APP_HOME} # Copy binary and configs from builder COPY --from=builder --chown=${APP_USER}:${APP_GROUP} /build/bin/app . COPY --from=builder --chown=${APP_USER}:${APP_GROUP} /build/configs ./configs/ # Set file permissions RUN chmod +x ./app && \ chown -R ${APP_USER}:${APP_GROUP} ${APP_HOME} # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 # Switch to non-root user USER ${APP_USER} # Default command CMD ["./app"] # Expose port EXPOSE 3000 # Set environment variable for production ENV APP_ENV=production # Command to run the application ENTRYPOINT ["/sbin/tini", "--"]