Введение: От разработки до production-сервера на Go
Вы написали высокопроизводительное веб-приложение на Go (Golang). Компиляция в один бинарник, статическая типизация, встроенная работа с сетью — всё это даёт фору Node.js или Python. Но «оно работает на моей машине» — не аргумент для продакшена. Продвинутый деплой Go приложения на VPS — это не просто копирование файлов по SSH. Это настройка CI/CD пайплайна, контейнеризация, reverse proxy, автоматическое обновление сертификатов, мониторинг и graceful shutdown.
В этой статье мы разберём полный production-ready сценарий для Golang-приложения на Ubuntu 22.04 LTS. Вы узнаете, как настроить Docker-сборку, организовать zero-downtime деплой через GitHub Actions, прикрутить Nginx с SSL и настроить мониторинг метрик Prometheus.
1. Подготовка VPS и настройка окружения
Предположим, у вас есть VPS (DigitalOcean, Hetzner, Timeweb) с Ubuntu 22.04. Первым делом обновляем систему и устанавливаем базовый набор инструментов:
ssh root@your_server_ip
apt update && apt upgrade -y
apt install -y git curl htop net-tools ufw
Создаём пользователя deploy с sudo-правами (без пароля, только по SSH-ключу):
adduser deploy
usermod -aG sudo deploy
mkdir /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh && chmod 600 /home/deploy/.ssh/authorized_keys
Настраиваем фаервол UFW:
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Важно: Отключаем вход для root в /etc/ssh/sshd_config (PermitRootLogin no) и перезапускаем SSH (systemctl restart sshd).
1.1 Установка Docker и Docker Compose
Для Go-приложения контейнеризация — стандарт де-факто. Устанавливаем Docker по официальной инструкции:
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
usermod -aG docker deploy
Проверяем версию: docker --version. Далее устанавливаем Docker Compose v2 (плагин):
apt install -y docker-compose-plugin
2. CI/CD пайплайн с GitHub Actions и Docker
Продвинутый деплой подразумевает автоматизацию. Мы будем использовать GitHub Actions для сборки образа и отправки его на сервер через SSH с последующим запуском нового контейнера.
Структура проекта на Go:
myapp/
├── main.go
├── go.mod
├── Dockerfile
├── docker-compose.yml
└── .github/workflows/deploy.yml
Dockerfile (Multi-stage build):
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/myapp .
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
docker-compose.yml (для production):
version: '3.8'
services:
app:
image: ghcr.io/your_username/myapp:latest
restart: always
ports:
- "127.0.0.1:8080:8080"
environment:
- DB_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
GitHub Actions workflow (.github/workflows/deploy.yml):
name: Deploy Go App
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/your_username/myapp:latest
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/deploy/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
Не забудьте добавить секреты в репозиторий: GHCR_TOKEN, VPS_HOST, VPS_USER, SSH_PRIVATE_KEY.
3. Reverse Proxy Nginx, SSL и Systemd Service
Запускать Go-приложение напрямую на порту 80 — плохая практика. Используем Nginx как reverse proxy, который будет отдавать статику, проксировать запросы к нашему приложению и терминировать SSL.
3.1 Установка Nginx и Certbot
apt install -y nginx certbot python3-certbot-nginx
Создаём конфиг для нашего домена (/etc/nginx/sites-available/myapp.example.com):
server {
listen 80;
server_name myapp.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host