
How to Dockerize and Deploy Go
Lukas MauserThis Dockerfile compiles your Go app into a single static binary, then ships it on a tiny Alpine image, so the final container is only a few megabytes.
If you're just here to copy and paste, here's the final Dockerfile that will produce an image for your Go app:
FROM golang:1.23-alpine AS build
WORKDIR /src
# Download modules first so this layer is cached when only source changes
COPY go.mod go.sum ./
RUN go mod download
# Build a static binary
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .
FROM alpine:3.20 AS runtime
WORKDIR /app
# Certificates so the binary can make outbound HTTPS calls
RUN apk add --no-cache ca-certificates
COPY --from=build /app/server .
EXPOSE 8080
CMD ["./server"]
And here's the .dockerignore file:
.git
*.md
Dockerfile
.dockerignore
To build and run the image, use these commands:
docker build -t go-app .
docker run -p 8080:8080 go-app
Not just here to copy and paste? Let's go over what's happening in the Dockerfile!
The Setup
For this tutorial, I assume you have a Go app that starts an HTTP server, with a go.mod file at the root. Go compiles to a single self-contained binary, which is a great fit for containers: the build stage needs the full Go toolchain, but the runtime stage needs almost nothing.
If your project has no external dependencies yet, it may not have a go.sum file. In that case just drop it from the COPY go.mod go.sum ./ line.
The Dockerfile
The build stage compiles the binary:
- Base image:
- Uses
golang:1.23-alpine, which has the Go compiler and tooling on a small base.
- Module caching:
- Copies
go.modandgo.sumfirst and runsgo mod download. This caches your dependencies in their own layer so they are not re-downloaded on every source change.
- Build step:
- Runs
go buildwithCGO_ENABLED=0. Disabling cgo produces a fully static binary with no dependency on system C libraries, which is what lets us run it on a minimal image.
The runtime stage is deliberately tiny:
- Runtime image:
- Starts from plain
alpine:3.20. - Installs
ca-certificatesso your app can make outbound HTTPS requests, for example to a database or a third-party API. Without them, TLS calls fail with certificate errors. - Copies just the compiled binary from the build stage.
- Exposes port 8080 and runs the binary.
Make sure your server actually listens on 0.0.0.0:8080 (or reads the port from an environment variable) rather than localhost, otherwise it won't accept connections from outside the container.
Deployment
You can deploy this Docker container to any cloud provider that supports Docker. For example, you could use platforms like Heroku, DigitalOcean, or AWS ECS. Because I am the co-founder of Sliplane, I will show you how to deploy it there.
After signing up, you can create a new service by selecting your GitHub repository. Then just keep the default settings and click on deploy.

After deployment your Go app will be available under a subdomain of sliplane.app, usually it's just your service name.
You can also see the logs of your app, view metrics such as CPU and memory usage, add persistent storage, and much more. Whenever you push to your repository, Sliplane will automatically deploy your app.
If you want to try out Sliplane, the first 2 days are free! Try it out and let me know what you think :)
Next Steps
If you want the smallest possible image, you can swap the Alpine runtime for scratch and copy the CA certificates in manually. Want help with that, or with adding a health check endpoint? Feel free to reach out!
Cheers,
Lukas