# Go Dockerfile Generator

URL: /dockerizer/golang

Generate a production Dockerfile for a Go service — a statically linked binary cross-compiled without QEMU, in an image with nothing else in it.

## Default configuration

- `appName` (App name): go-app — Used for the image tag, the compose service and the OCI labels.

- `port` (Port): 8080 — The port the app listens on inside the container. Keep it above 1024 so the process can bind it without root.

- `mainPackage` (Main package): ./cmd/server — The package path passed to `go build`. Use `.` if main.go is at the project root.

- `goVersion` (Go version): 1.24

- `runtimeBase` (Runtime image): distroless — A static Go binary needs no runtime at all. Distroless still gives you CA certificates and timezone data, which scratch does not.

- `cgo` (Enable cgo): false — Required by go-sqlite3 and some crypto libraries. Turning it on gives up static linking, so the runtime image has to be Alpine or Debian.

- `database` (Database service): none — Adds the database to docker-compose.yml with a healthcheck, a named volume and a DATABASE_URL wired into the app.

- `redis` (Redis service): false — Adds Redis to docker-compose.yml and exposes REDIS_URL to the app.

- `cacheMounts` (BuildKit cache mounts): true — Persists the package manager store between builds. Repeat builds skip the download entirely.

- `multiArch` (Multi-architecture build): false — Adds BUILDPLATFORM/TARGETARCH so `docker buildx build --platform linux/amd64,linux/arm64` cross-compiles natively.

- `healthcheck` (Healthcheck): true — Adds a HEALTHCHECK so orchestrators can restart an unresponsive container.

- `ociLabels` (OCI labels): false — Adds org.opencontainers.image.* metadata to the final image.

## Generated files

### Dockerfile

Multi-stage build: dependencies, compilation and the runtime image are separate, so only what the app needs at runtime ships.

```docker
# syntax=docker/dockerfile:1
# Generated by Easypanel Dockerizer — https://easypanel.io/dockerizer

# --- Build --------------------------------------------
FROM golang:1.24-alpine AS build
WORKDIR /src

# Module graph first — source edits must not re-download it
COPY go.mod go.sum ./
RUN --mount=type=cache,id=go-mod,target=/go/pkg/mod,sharing=locked \
    go mod download
COPY . .

# -s -w strips the symbol table and DWARF data — typically 25% off the binary
RUN --mount=type=cache,id=go-mod,target=/go/pkg/mod,sharing=locked \
    --mount=type=cache,id=go-build,target=/root/.cache/go-build,sharing=locked \
    CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /bin/app ./cmd/server

# --- Runtime ------------------------------------------
FROM gcr.io/distroless/static-debian12:nonroot AS runtime
COPY --from=build /bin/app /app
USER 65532:65532
ENV PORT=8080
EXPOSE 8080
STOPSIGNAL SIGTERM

# No healthcheck: this image has no shell and no wget. Probe from the orchestrator instead.
ENTRYPOINT ["/app"]

```

### .dockerignore

Keeps the build context small and stops secrets and local dependencies from reaching an image layer.

```bash
# Version control
.git
.gitignore
.github

# Secrets — never bake these into an image layer
.env
.env.*
!.env.example
*.pem
*.key

# Editor and OS noise
.vscode
.idea
.DS_Store
Thumbs.db

# Docs and local tooling
README.md
LICENSE
docs
.editorconfig
docker-compose*.yml
Dockerfile*
.dockerignore

# Local build output
bin
dist
*.exe
*.test
*.out
vendor

```

### docker-compose.yml

Runs the image locally with its backing services, wired together and health-gated.

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - "8080:8080"

```

## Frequently asked questions

### Why is the image only a few megabytes?

Because it contains one file: your binary. Go statically links everything it needs, so there is no base OS, no libc and no package manager to ship.

### scratch or distroless?

Distroless static, almost always. It adds CA certificates, timezone data and a nonroot user for roughly 2 MB — all things you eventually need and would otherwise hand-copy.

### Why no HEALTHCHECK on the small images?

A HEALTHCHECK needs a binary to run, and these images have none. Probe the container from outside instead — Kubernetes, Compose and Easypanel can all do HTTP checks without a shell.

## Related generators

- [Rust](/dockerizer/rust)

- [FastAPI](/dockerizer/fastapi)

- [Node.js](/dockerizer/nodejs)

- [.NET](/dockerizer/dotnet)