diff --git a/Dockerfile b/Dockerfile index c2037cf..c0762aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,106 +1,43 @@ -# Build Stage -FROM golang:1.21-alpine AS build - -# Install necessary packages including CA certificates -RUN apk --no-cache add ca-certificates tzdata git curl - -WORKDIR /src - -# Copy go mod files first for better caching -COPY go.mod go.sum ./ - -# Download dependencies -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 /app cmd/server/main.go - -# Development Stage -FROM golang:1.21-alpine AS development - -# Install air for live reload and other dev tools -RUN go install github.com/cosmtrek/air@latest - -# Install necessary packages -RUN apk --no-cache add ca-certificates tzdata git curl - -WORKDIR /app - -# Copy go mod files -COPY go.mod go.sum ./ -RUN go mod download - -# Copy source code -COPY . . - -# Set timezone -ENV TZ=Asia/Jakarta - -# Expose port -EXPOSE 3300 - -# Use air for live reload in development -CMD ["air", "-c", ".air.toml"] - -# Migration Stage -FROM build AS migration - -# Install migration tool -RUN go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest - -WORKDIR /app - -# Copy migration files -COPY migrations ./migrations -COPY infra ./infra - -# Set the entrypoint for migrations -ENTRYPOINT ["migrate"] - -# Production Stage +# ========================= +# 3) Production runtime +# ========================= FROM debian:bullseye-slim AS production -# Install minimal runtime dependencies + Chrome, Chromium, and wkhtmltopdf for PDF generation +# Install only minimal runtime deps RUN apt-get update && apt-get install -y \ ca-certificates \ tzdata \ curl \ - fontconfig \ - wget \ - gnupg \ - && wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \ - && echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \ - && apt-get update \ - && apt-get install -y google-chrome-stable chromium wkhtmltopdf \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* -# Create non-root user for security +# Create non-root user RUN groupadd -r appuser && useradd -r -g appuser appuser -# Copy the binary -COPY --from=build /app /app +# Copy app binary from build +COPY --from=build /out/app /app -# Copy configuration files -COPY --from=build /src/infra /infra +# Copy infra/config files (if your app reads config/templates from here) +COPY --from=migration /src/infra /infra -# Change ownership to non-root user -RUN chown -R appuser:appuser /app /infra +# Optionally copy migrations and migrate binary so you can run migrations +COPY --from=migration /go/bin/migrate /usr/local/bin/migrate +COPY --from=migration /src/migrations /migrations -# Set timezone +# Permissions +RUN chown -R appuser:appuser /app /infra /migrations + +# Env & timezone ENV TZ=Asia/Jakarta -# Expose port +# Network EXPOSE 3300 -# Health check +# Healthcheck HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ - CMD curl -f http://localhost:3300/health || exit 1 + CMD curl -fsS http://localhost:3300/health || exit 1 -# Switch to non-root user +# Drop privileges USER appuser -# Set the entrypoint +# Default entrypoint -> run the server ENTRYPOINT ["/app"] diff --git a/internal/middleware/cors.go b/internal/middleware/cors.go index 224079b..20e6835 100644 --- a/internal/middleware/cors.go +++ b/internal/middleware/cors.go @@ -5,7 +5,7 @@ import ( ) func CORS() gin.HandlerFunc { - return gin.HandlerFunc(func(c *gin.Context) { + return func(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Credentials", "true") c.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") @@ -17,5 +17,5 @@ func CORS() gin.HandlerFunc { } c.Next() - }) + } } diff --git a/internal/router/router.go b/internal/router/router.go index 7d125a1..6732a71 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -101,11 +101,11 @@ func (r *Router) Init() *gin.Engine { engine := gin.New() engine.Use( middleware.JsonAPI(), + middleware.CORS(), middleware.CorrelationID(), middleware.Recover(), middleware.HTTPStatLogger(), middleware.PopulateContext(), - middleware.CORS(), ) r.addAppRoutes(engine)