Skip to content

Building Go Binaries with Private GitHub Modules in Docker

Go projects often depend on private GitHub modules. When building inside Docker, authentication must work non-interactively and without embedding credentials into images.

This post shows two supported patterns:

  • SSH agent forwarding (local / VM)
  • Git token authentication (CI)

Both produce the same minimal runtime image.


SSH-Based Build (Local / VM)

# ---------- build stage ----------
FROM golang:1.24 AS builder

# Trust GitHub host key (required for non-interactive builds)
RUN mkdir -p /root/.ssh && \
    ssh-keyscan github.com >> /root/.ssh/known_hosts

# Configure Go for private modules
RUN go env -w GOPRIVATE=github.com/acmeorg/*

# Rewrite HTTPS imports to SSH for github urls
RUN git config --global url."ssh://git@github.com/acmeorg".insteadOf "https://github.com/acmeorg"

# Download private modules
RUN --mount=type=ssh go mod download

# Build the binary
RUN --mount=type=ssh CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} go build -ldflags "-s -w" -a -o app cmd/main.go

# ---------- runtime stage ----------
FROM gcr.io/distroless/static:nonroot

COPY --from=builder /app /app

ENTRYPOINT ["/app"]

Build command

DOCKER_BUILDKIT=1 sudo -E docker build \
  --ssh default \
  -t my-org/app \
  -f Dockerfile.ssh \
  .
  • --ssh default forwards the active SSH agent
  • sudo -E preserves SSH_AUTH_SOCK (and other environment variables from the current shell)
  • No SSH keys or credentials are copied into the image.
  • Any RUN step that may access Git must include --mount=type=ssh

Token-Based Build (CI / Headless)

The same Dockerfile structure can be used with HTTPS and a Github token.

# ---------- build stage ----------
FROM golang:1.24 AS builder
ARG GITHUB_TOKEN

RUN git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/acmeorg".insteadOf "https://github.com/acmeorg"

RUN go env -w GOPRIVATE=github.com/acmeorg/*

RUN go mod download

RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} go build -ldflags "-s -w" -a -o app cmd/main.go

# ---------- runtime stage ----------
FROM gcr.io/distroless/static:nonroot

COPY --from=builder /app /app

ENTRYPOINT ["/app"]

Build command (CI)

docker build \
  --build-arg GITHUB_TOKEN=****** \
  -t my-org/app \
  .

Note

  • SSH forwarding is preferred for local and VM builds
  • Token authentication is better suited for CI
  • Both approaches are secure, non-interactive, and image-safe

This pattern scales cleanly from development to production without leaking credentials.