Detection

migetpacks detects Go when any of these files are present in your project root:
  • go.mod
  • Godeps/Godeps.json
  • glide.yaml

Version Detection

Go version is resolved in this order:
PrioritySourceExample
1GO_VERSION env varGO_VERSION=1.23
2.go-version file1.25.0
3go directive in go.modgo 1.23
4Default1.25.0

Build Process

migetpacks generates a multi-stage Dockerfile that produces a static binary:
# Builder stage
FROM golang:1.25 AS builder
WORKDIR /build

# Go build environment (static linking)
ENV CGO_ENABLED=0
ENV GOOS=linux

# Layer 1: Copy go.mod/go.sum for layer caching
COPY go.mod go.sum* ./

# Layer 2: Download dependencies (CACHED when go.mod unchanged)
RUN go mod download

# Layer 3: Copy source code
COPY . .

# Layer 4: Build static binary and cleanup
RUN go build -ldflags="-s -w" -o /build/myapp . \
    && rm -rf .git *.go go.mod go.sum vendor/

# Runtime stage
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates
WORKDIR /app
COPY --from=builder /build /app

Static Linking

Go builds use CGO_ENABLED=0 by default, producing fully static binaries that run on minimal base images. The linker flags -s -w strip debug information for smaller binaries.

Module Name and Binary Detection

The binary name is automatically derived from the module name in go.mod:
  • module github.com/user/myapp produces binary myapp
  • Falls back to app if detection fails

Package Spec

You can specify which packages to build using the //+heroku install comment in go.mod:
module github.com/user/myapp

// +heroku install ./cmd/api ./cmd/worker

go 1.23
Without this directive, go build . is used (builds the package in the current directory). For multiple packages, binaries are placed in /build/bin/:
RUN go build -ldflags="-s -w" -o /build/bin/ ./cmd/...

Build Hooks

migetpacks supports pre- and post-compile hooks:
  • bin/go-pre-compile - Runs before go build
  • bin/go-post-compile - Runs after go build

golang-migrate

If github.com/golang-migrate/migrate is detected in go.mod, the migrate CLI tool is automatically installed in the builder stage.

Linker Symbols

Set custom linker symbols using environment variables:
-e GO_LINKER_SYMBOL=main.version -e GO_LINKER_VALUE=1.0.0
This adds -X main.version=1.0.0 to the linker flags.

Run Command

The default run command is determined in this order:
PrioritySourceCommand
1RUN_COMMAND env varUser-specified
2web: in ProcfileFrom Procfile
3Default./app (or ./myapp based on module name)
Binary names in Procfiles are automatically prefixed with ./ if they don’t already have a path prefix.

Caching

Docker Layer Caching

Dependencies are downloaded in a separate layer. go mod download is only re-run when go.mod or go.sum changes.

BuildKit Cache Mounts

When BUILD_CACHE_DIR is configured, BuildKit cache mounts are used:
Cache PathContents
/cache/goGo module cache (/go/pkg/mod) and build cache (~/.cache/go-build)

Registry Cache

Use CACHE_IMAGE to push/pull BuildKit inline cache layers to a registry for cross-build caching.

DHI Support

Go is supported with Docker Hardened Images (requires version 1.22 or later).
StageImage
Builddhi.io/golang:{version}-dev
Runtimedhi.io/golang:{version}
DHI images for Go require minimum patch versions: 1.22.12, 1.23.7, or 1.24.1+. Older patch versions within these minor releases are not available.
The DHI runtime image is distroless with no shell. Since Go produces static binaries, this works without any special handling.

Go Toolchain in Runtime

If you need the Go toolchain available at runtime (for plugins, go run, etc.):
-e GO_INSTALL_TOOLS_IN_IMAGE=true
This copies /usr/local/go from the builder to the runtime image.

Example

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-go-app:latest \
  miget/migetpacks:latest

With Custom Options

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=registry.io/app:v1 \
  -e GO_VERSION=1.23 \
  -e GO_LINKER_SYMBOL=main.version \
  -e GO_LINKER_VALUE=1.2.3 \
  -e USE_DHI=true \
  miget/migetpacks:latest

Multi-Binary Project

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=registry.io/app:v1 \
  -e RUN_COMMAND="./bin/api" \
  miget/migetpacks:latest
With // +heroku install ./cmd/api ./cmd/worker in go.mod, both binaries are available at /app/bin/api and /app/bin/worker.