Deployment Overview

Deploy your Goose application to production environments.

Deployment Options

Platform Best For Setup Complexity
Docker Containers, Kubernetes Medium
Traditional Server VPS, bare metal Simple
Cloud Platforms AWS, GCP, Azure Varies

Building for Production

Build Binary

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

# Build for different platforms
GOOS=darwin GOARCH=amd64 go build -o myapp-mac main.go
GOOS=windows GOARCH=amd64 go build -o myapp.exe main.go

Build Flags

# Strip debug info (smaller binary)
go build -ldflags="-s -w" -o myapp main.go

# Embed version info
go build -ldflags="-X main.Version=1.2.3" -o myapp main.go

Environment Configuration

Production Environment Variables

# Application
APP_NAME=myapp
APP_ENV=production
APP_DEBUG=false
HOST=0.0.0.0
PORT=8080

# Database
DB_DRIVER=postgres
DB_HOST=db.example.com
DB_PORT=5432
DB_NAME=myapp_prod
DB_USER=myapp
DB_PASSWORD=secret

# Redis
REDIS_HOST=redis.example.com
REDIS_PORT=6379
REDIS_PASSWORD=secret

# Security
JWT_SECRET=your-production-secret

Load Environment

// main.go
func main() {
    // Load .env file if exists
    if _, err := os.Stat(".env"); err == nil {
        env.Load(".env")
    }

    // Or use environment-specific files
    appEnv := os.Getenv("APP_ENV")
    if appEnv == "" {
        appEnv = "production"
    }
    env.Load(".env." + appEnv)
}

Quick Docker Deployment

Dockerfile

# Build stage
FROM golang:1.21-alpine AS builder

WORKDIR /app

# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download

# Copy source
COPY . .

# Build
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o myapp main.go

# Runtime stage
FROM alpine:3.19

WORKDIR /app

# Copy binary
COPY --from=builder /app/myapp .

# Copy config (if needed)
COPY .env.production .env

EXPOSE 8080

CMD ["./myapp"]

Build and Run

# Build image
docker build -t myapp:latest .

# Run container
docker run -d \
    -p 8080:8080 \
    -e APP_ENV=production \
    --name myapp \
    myapp:latest

Health Checks

Health Endpoint

type HealthController struct {
    db    *gorm.DB  `inject:""`
    redis *kv.Client `inject:""`
}

func (c *HealthController) Routes() types.Routes {
    return types.Routes{
        {Method: "GET", Path: "/health", Handler: c.Health},
        {Method: "GET", Path: "/health/ready", Handler: c.Ready},
        {Method: "GET", Path: "/health/live", Handler: c.Live},
    }
}

func (c *HealthController) Health(ctx types.Context) any {
    return map[string]string{"status": "healthy"}
}

func (c *HealthController) Ready(ctx types.Context) any {
    // Check all dependencies
    checks := map[string]string{}

    // Database
    if err := c.checkDB(); err != nil {
        checks["database"] = "unhealthy"
    } else {
        checks["database"] = "healthy"
    }

    // Redis
    if err := c.checkRedis(); err != nil {
        checks["redis"] = "unhealthy"
    } else {
        checks["redis"] = "healthy"
    }

    // Determine overall status
    for _, status := range checks {
        if status == "unhealthy" {
            return ctx.Status(503).JSON(checks)
        }
    }

    return checks
}

func (c *HealthController) Live(ctx types.Context) any {
    return map[string]string{"status": "alive"}
}

Graceful Shutdown

func main() {
    // Start application
    stop, err := goose.Start(goose.API(platform, module, nil))
    if err != nil {
        log.Fatal(err)
    }

    // Wait for interrupt signal
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    log.Println("Shutting down server...")

    // Graceful shutdown with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    if err := stop(); err != nil {
        log.Printf("Server forced to shutdown: %v", err)
    }

    log.Println("Server exited")
}

Logging in Production

type LogConfig struct {
    Level  string
    Format string // json or text
    Output string // stdout, file
}

func setupLogging() {
    config := LogConfig{
        Level:  env.String("LOG_LEVEL", "info"),
        Format: env.String("LOG_FORMAT", "json"),
        Output: env.String("LOG_OUTPUT", "stdout"),
    }

    // Configure logger based on environment
    if env.String("APP_ENV", "") == "production" {
        // Use JSON format for production (easier to parse)
        log.SetFormatter("json")
        log.SetLevel("info")
    }
}

Production Checklist

Before Deployment

  • Set APP_ENV=production
  • Disable debug mode
  • Use production database
  • Set secure secrets
  • Configure HTTPS
  • Set up health checks
  • Configure logging
  • Set up monitoring

Security

  • Use strong JWT secrets
  • Enable HTTPS/TLS
  • Configure CORS properly
  • Set security headers
  • Enable rate limiting
  • Validate all input

Performance

  • Configure connection pools
  • Set up caching
  • Enable compression
  • Optimize database queries
  • Use CDN for static assets

Monitoring

  • Set up error tracking
  • Configure log aggregation
  • Monitor health endpoints
  • Set up alerts
  • Track metrics

Process Management

Using systemd

# /etc/systemd/system/myapp.service
[Unit]
Description=My Goose Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=always
RestartSec=5
Environment=APP_ENV=production

[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl enable myapp
sudo systemctl start myapp

# Check status
sudo systemctl status myapp

Reverse Proxy (Nginx)

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }
}

Next Steps