# Stage 1: Build the Go application
# Use a Go official image with Alpine Linux for a smaller build environment
FROM golang:1.24-alpine AS builder
# Set the working directory inside the container to the root of devex
WORKDIR /devex
# Copy packages first
COPY packages/ /devex/packages
# Set the working directory inside the container to the root of your Go module
WORKDIR /devex/apps/core
# Copy go.mod and go.sum first to allow Docker to cache these layers.
# This means if only your code changes, but dependencies don't, the build will be faster.
COPY apps/core/go.mod apps/core/go.sum ./
# Download all Go module dependencies
# This command fetches all required modules declared in go.mod
RUN go mod download
# Copy the rest of your application source code into the working directory
# This includes all subdirectories like cmd/, internal/, models/, pkg/, services/
COPY apps/core/ .
# Build the Go application binary
# CGO_ENABLED=0: Disables cgo, resulting in a statically linked binary, which is highly portable.
# GOOS=linux: Ensures the binary is built for a Linux environment, as is typical for Docker containers.
# -a -installsuffix cgo: Additional flags to help create a fully static binary.
# -o main: Specifies the output executable name as 'main'.
# cmd/main.go: This is crucial! It explicitly tells the Go compiler where your application's entry point is.
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/main.go
# Stage 2: Create the final lean image for deployment
# Use a minimal base image. 'alpine:latest' is a good balance for beginner friendliness
# between extreme minimalism (like 'scratch') and having basic debugging tools.
FROM alpine:latest
# Set the working directory for the final image
WORKDIR /app
# Copy the compiled binary from the 'builder' stage into the final image's working directory
COPY --from=builder /devex/apps/core/main .
# Expose the port your Go application listens on.
# Based on your .env, your app listens on PORT=8080.
EXPOSE 8080
# Define the command to run your application when the container starts.
# This executes the 'main' binary copied from the builder stage.
CMD ["./main"]
# --- Best Practices for Dockerfile ---
# 1. Use specific version tags for base images (e.g., golang:1.22-alpine) to ensure reproducible builds.
# 2. Leverage Docker's layer caching by placing less frequently changing instructions (like COPY go.mod/sum)
# before more frequently changing ones (like COPY . .).
# 3. Keep the final image as small as possible to reduce attack surface and improve deployment speed.
# 4. Use `CGO_ENABLED=0` for Go applications to create static binaries.
# 5. Define `EXPOSE` for clarity, though it doesn't actually publish the port; it's documentation.
# 6. Use `CMD` with the executable path.