Go to Production: VPS, Docker or Cloud — Choosing the Best Deployment

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Go is an Ideal Candidate for Production, but Deployment Still Decides Everything

\n\n

You wrote a backend in Go. It flies: compilation into a single binary, minimal memory consumption, goroutines that aren't afraid of load. But there's a nuance: even the fastest code is useless if it sits as dead weight on a local machine. Sooner or later, the question arises: how do you roll this marvel of engineering out to production?

\n\n

Deploying Go applications is not rocket science, but it's easy to step on a rake here. In this article, we'll break down three main paths: classic VPS, containerization with Docker, and cloud platforms. You'll learn which approach to choose for your task and get ready-made scripts to get started.

\n\n

Deploying Go on VPS: A Classic That Never Gets Old

\n\n

A Virtual Private Server (VPS) is your personal root. Full control, no platform restrictions, but all responsibility lies with you. For a Go application, this is often the optimal option: the binary weighs 10–20 MB, starts in milliseconds, and doesn't require complex orchestration.

\n\n

What You Need for Deploying Go on VPS

\n\n
    \n
  • Server with Linux (Ubuntu 22.04 / Debian 11 — the classics)
  • \n
  • SSH access
  • \n
  • Go (optional, if compiling on the server)
  • \n
  • Systemd for process management
  • \n
  • Nginx or Caddy as a reverse proxy
  • \n
\n\n

Example: Deploying a Go Server via Systemd

\n\n

Let's say you have a simple application main.go that listens on port 8080. Compile it on your machine for the target architecture:

\n\n
GOOS=linux GOARCH=amd64 go build -o app main.go
\n\n

Copy the binary to the server:

\n\n
scp app user@your-server:/opt/app/
\n\n

Create a systemd unit at /etc/systemd/system/app.service:

\n\n
[Unit]\nDescription=Go App\nAfter=network.target\n\n[Service]\nExecStart=/opt/app/app\nWorkingDirectory=/opt/app\nRestart=always\nUser=www-data\nGroup=www-data\nEnvironment=PORT=8080\n\n[Install]\nWantedBy=multi-user.target
\n\n

Start and enable auto-start:

\n\n
sudo systemctl daemon-reload\nsudo systemctl enable --now app
\n\n

Now your Go application runs as a daemon. Add Nginx for proxying from port 80:

\n\n
server {\n    listen 80;\n    server_name yourdomain.com;\n\n    location / {\n        proxy_pass http://127.0.0.1:8080;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n}
\n\n

VPS Pros: full control, low cost (from $5/month), transparency. Cons: manual updates, no autoscaling, need to configure security yourself.

\n\n

Docker for Go: Containerization That Simplifies Life

\n\n

If you work in a team or plan microservices, Docker is your choice. Go and Docker are a perfect pair: multi-stage builds produce images sized 5–15 MB, and static compilation allows you to do without a base image.

\n\n

Dockerfile for a Go Application

\n\n

Here is a minimal but production-ready Dockerfile:

\n\n
# Stage 1: build\nFROM golang:1.22-alpine AS builder\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -o app .\n\n# Stage 2: minimal image\nFROM alpine:latest\nRUN apk --no-cache add ca-certificates\nWORKDIR /root/\nCOPY --from=builder /app/app .\nEXPOSE 8080\nCMD ["./app"]
\n\n

Build and run:

\n\n
docker build -t go-app .\ndocker run -d -p 8080:8080 --name go-app go-app
\n\n

Docker Compose for a Full Setup

\n\n

When the application needs a database or Redis, use docker-compose.yml:

\n\n
version: '3.8'\nservices:\n  app:\n    build: .\n    ports:\n      - "8080:8080"\n    environment:\n      - DB_HOST=db\n      - DB_PORT=5432\n    depends_on:\n      - db\n  db:\n    image: postgres                

Blogs

Book Recommendations