How to Dockerize and Deploy Go

How to Dockerize and Deploy Go

Lukas Mauser - Co-Founder von sliplane.ioLukas Mauser
4 min

This 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:

Dockerfile
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:

  1. Base image:
  • Uses golang:1.23-alpine, which has the Go compiler and tooling on a small base.
  1. Module caching:
  • Copies go.mod and go.sum first and runs go mod download. This caches your dependencies in their own layer so they are not re-downloaded on every source change.
  1. Build step:
  • Runs go build with CGO_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:

  1. Runtime image:
  • Starts from plain alpine:3.20.
  • Installs ca-certificates so 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.

Sliplane Dashboard

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 :)

Deploy Go in 2 minutes 🚀

Push your repo to GitHub and let Sliplane build and deploy your Go app for you. The first 2 days are free.

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

Welcome to your cloud platform

Sliplane makes it simple to deploy and scale your apps in the cloud. Start with a container or your favorite framework and grow from there. Try it now and get started in minutes!