Skip to main content

Deployment Strategies

OPS Intermediate

Deploy EZ-Console applications to production using various strategies.

Overview

This guide covers different deployment strategies for EZ-Console applications, including standalone binary deployment, Docker containers, Kubernetes, and cloud platforms.

Deployment Methods

1. Standalone Binary

Deploy as a single executable file.

Advantages:

  • Simple deployment
  • No container runtime required
  • Direct control over resources

Steps:

# Build binary
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server main.go

# Copy to server
scp server config.yml user@server:/opt/myapp/

# Run on server
/opt/myapp/server --global.encrypt-key=your-key --config=/opt/myapp/config.yml

2. Docker

Deploy using Docker containers.

Advantages:

  • Consistent environment
  • Easy to scale
  • Isolation

Dockerfile:

FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-w -s" -o server main.go

FROM node:18-alpine AS frontend-builder
WORKDIR /app
COPY web/package*.json ./
RUN npm install -g pnpm && pnpm install
COPY web/ ./
RUN pnpm build

FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /app
COPY --from=builder /app/server ./
COPY --from=frontend-builder /app/dist ./static
EXPOSE 8080
CMD ["./server", "--global.encrypt-key=${ENCRYPT_KEY}"]

Deploy:

docker build -t myapp:latest .
docker run -d \
-p 8080:8080 \
-e ENCRYPT_KEY=your-key \
-v /path/to/config.yml:/app/config.yml \
myapp:latest

3. Docker Compose

Deploy with Docker Compose for multi-container applications.

docker-compose.yml:

version: '3.8'

services:
app:
build: .
ports:
- "8080:8080"
environment:
- GLOBAL_ENCRYPT_KEY=${ENCRYPT_KEY}
- DATABASE_DRIVER=mysql
- DATABASE_HOST=db
- DATABASE_USERNAME=root
- DATABASE_PASSWORD=${DB_PASSWORD}
- DATABASE_SCHEMA=myapp
depends_on:
- db
volumes:
- ./config.yml:/app/config.yml
- ./uploads:/app/uploads
restart: unless-stopped

db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
- MYSQL_DATABASE=myapp
volumes:
- db-data:/var/lib/mysql
restart: unless-stopped

volumes:
db-data:

Deploy:

docker-compose up -d

4. Kubernetes

Deploy to Kubernetes cluster.

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 8080
env:
- name: GLOBAL_ENCRYPT_KEY
valueFrom:
secretKeyRef:
name: myapp-secrets
key: encrypt-key
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: myapp-secrets
key: db-password
volumeMounts:
- name: config
mountPath: /app/config.yml
subPath: config.yml
volumes:
- name: config
configMap:
name: myapp-config
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
type: LoadBalancer

Deploy:

kubectl apply -f deployment.yaml

5. Systemd Service

Deploy as systemd service for Linux servers.

Create service file /etc/systemd/system/myapp.service:

[Unit]
Description=My Console Application
After=network.target mysql.service

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/environment
ExecStart=/opt/myapp/server --config=/etc/myapp/config.yml
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp

Reverse Proxy Setup

Nginx Configuration

server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

# Frontend
location / {
root /var/www/myapp;
try_files $uri $uri/ /index.html;
}

# API
location /api {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# WebSocket support
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Traefik Configuration

# docker-compose.yml with Traefik
version: '3.8'

services:
traefik:
image: traefik:v2.9
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock

app:
build: .
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`example.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls=true"

Environment Setup

Environment Variables

Create /etc/myapp/environment:

GLOBAL_ENCRYPT_KEY=your-32-byte-encryption-key
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_MODE=release
DATABASE_DRIVER=mysql
DATABASE_HOST=localhost
DATABASE_USERNAME=myapp
DATABASE_PASSWORD=secure-password
DATABASE_SCHEMA=myapp
LOG_LEVEL=info

Monitoring Setup

Health Check

GET /api/health

Response:

{
"code": "0",
"data": {
"status": "ok"
}
}

Metrics Endpoint

import "github.com/prometheus/client_golang/prometheus/promhttp"

router.GET("/metrics", gin.WrapH(promhttp.Handler()))

Rollback Strategy

Docker Rollback

# Rollback to previous image
docker stop myapp
docker run -d --name myapp myapp:previous-version

Kubernetes Rollback

# Rollback deployment
kubectl rollout undo deployment/myapp

Systemd Rollback

# Stop service
sudo systemctl stop myapp

# Restore previous binary
cp /opt/myapp/server.backup /opt/myapp/server

# Start service
sudo systemctl start myapp

Best Practices

1. Use Environment Variables

# ✅ Good: Use environment variables
-e ENCRYPT_KEY=${ENCRYPT_KEY}

# ❌ Bad: Hardcode in config
encrypt_key: "hardcoded-key"

2. Version Control Configs

Keep configuration in version control (without secrets).

3. Health Checks

Always set up health checks for monitoring.

4. Logging

Ensure logs are accessible and centralized.


Need help? Ask in GitHub Discussions.