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:
| Priority | Source | Example |
|---|
| 1 | GO_VERSION env var | GO_VERSION=1.23 |
| 2 | .go-version file | 1.25.0 |
| 3 | go directive in go.mod | go 1.23 |
| 4 | Default | 1.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:
| Priority | Source | Command |
|---|
| 1 | RUN_COMMAND env var | User-specified |
| 2 | web: in Procfile | From Procfile |
| 3 | Default | ./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 Path | Contents |
|---|
/cache/go | Go 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).
| Stage | Image |
|---|
| Build | dhi.io/golang:{version}-dev |
| Runtime | dhi.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.
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.