Gothic Framework G symbol

Customize Dockerfile

When you run gothic deploy, the CLI builds your container image from a default Dockerfile. To use your own instead, point gothic.config.go at it with the DockerfilePath field. The path is resolved relative to your project root, and the change applies on the next deploy.

package main

import gothic "github.com/gothicframework/core/config"

var Config = gothic.Config{
	ProjectName:    "gothic-example",
	DockerfilePath: "Dockerfile",
}

Default Image

The default Dockerfile is a multi-stage build: it compiles your Go binary in golang:1.26 (a glibc image, not alpine), then copies the statically linked binary into a minimal scratch image alongside the AWS Lambda Web Adapter.

# Build stage — glibc base so GOTOOLCHAIN=auto can fetch the exact Go your go.mod needs
FROM golang:1.26 AS build

ENV GOTOOLCHAIN=auto
ENV GOWORK=off

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download
COPY . .

# Build the whole package (.), not main.go — Config lives in gothic.config.go.
# CGO_ENABLED=0 makes a static binary that runs on scratch.
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server .

# AWS Lambda Web Adapter (the repo was renamed to aws-lambda-adapter)
FROM public.ecr.aws/awsguru/aws-lambda-adapter:1.0.1 AS adapter

# Final image
FROM scratch
COPY --from=adapter /lambda-adapter /opt/extensions/lambda-adapter
COPY --from=build /app/server /server
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

# The server binds HTTP_LISTEN_ADDR; empty falls back to :80, which a non-root
# Lambda process cannot bind. Pin it to :8080 to match AWS_LWA_PORT.
ENV HTTP_LISTEN_ADDR=:8080
ENV AWS_LWA_PORT=8080

ENTRYPOINT ["/server"]

Example 1 — Add a System Dependency

If your app needs a native library at build time (for example, ffmpeg for video processing), add a RUN apt-get install line in the build stage (golang:1.26 is Debian-based):

# Build stage — glibc base so GOTOOLCHAIN=auto can fetch the exact Go your go.mod needs
FROM golang:1.26 AS build

ENV GOTOOLCHAIN=auto
ENV GOWORK=off

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download
COPY . .

# golang:1.26 is Debian-based, so use apt-get for build-time system deps
RUN apt-get update && apt-get install -y ffmpeg

# Build the whole package (.), not main.go — Config lives in gothic.config.go.
# CGO_ENABLED=0 makes a static binary that runs on scratch.
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server .

# AWS Lambda Web Adapter (the repo was renamed to aws-lambda-adapter)
FROM public.ecr.aws/awsguru/aws-lambda-adapter:1.0.1 AS adapter

# Final image
FROM scratch
COPY --from=adapter /lambda-adapter /opt/extensions/lambda-adapter
COPY --from=build /app/server /server
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

# The server binds HTTP_LISTEN_ADDR; empty falls back to :80, which a non-root
# Lambda process cannot bind. Pin it to :8080 to match AWS_LWA_PORT.
ENV HTTP_LISTEN_ADDR=:8080
ENV AWS_LWA_PORT=8080

ENTRYPOINT ["/server"]

Because the final image is scratch, only the compiled binary ships to Lambda — build-time dependencies do not increase your production image size.

Example 2 — Use Alpine as Runtime

If your app needs a shell or system libraries at runtime (for example, for debugging or calling external binaries), replace scratch with alpine in the final stage. Remember to install ca-certificates in the runtime stage as well:

# Build stage — glibc base so GOTOOLCHAIN=auto can fetch the exact Go your go.mod needs
FROM golang:1.26 AS build

ENV GOTOOLCHAIN=auto
ENV GOWORK=off

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download
COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server .

FROM public.ecr.aws/awsguru/aws-lambda-adapter:1.0.1 AS adapter

# Runtime image with a shell + package manager (adds ~8 MB vs scratch)
FROM alpine
RUN apk add --no-cache ca-certificates
COPY --from=adapter /lambda-adapter /opt/extensions/lambda-adapter
COPY --from=build /app/server /server

ENV HTTP_LISTEN_ADDR=:8080
ENV AWS_LWA_PORT=8080

ENTRYPOINT ["/server"]

Using alpine adds ~8 MB to the image but gives you a full package manager and shell. This is useful for apps that shell out to tools like ffmpeg, imagemagick, or wkhtmltopdf at runtime.

Next, learn how to add your own AWS resources with the infra/ drop-in!