Gin Web Framework Deployment & Usage Guide
1. Prerequisites
- Go: Version 1.24 or higher (download)
- Git: For cloning repositories and managing dependencies
- Optional:
airfor hot reload during development (go install github.com/cosmtrek/air@latest)
Verify Go installation:
go version
2. Installation
Initialize a New Project
mkdir my-gin-app && cd my-gin-app
go mod init example.com/my-gin-app
Install Gin
go get -u github.com/gin-gonic/gin
Or simply import in your code and Go modules will auto-fetch:
import "github.com/gin-gonic/gin"
Download Examples (Optional)
git clone https://github.com/gin-gonic/examples.git
cd examples
3. Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
GIN_MODE | Runtime mode: debug, release, or test | debug |
PORT | Server port (if using os.Getenv("PORT")) | 8080 |
Basic Configuration Setup
package main
import (
"os"
"github.com/gin-gonic/gin"
)
func main() {
// Set mode via environment
ginMode := os.Getenv("GIN_MODE")
if ginMode == "" {
ginMode = gin.DebugMode
}
gin.SetMode(ginMode)
r := gin.Default()
// Trust specific CIDRs (security)
r.SetTrustedProxies([]string{"192.168.1.0/24", "10.0.0.0/8"})
// Or trust all (not recommended for production)
// r.SetTrustedProxies(nil)
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "running"})
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
r.Run(":" + port)
}
TLS/HTTPS Configuration
// Auto TLS with Let's Encrypt
r.RunAutoTLS(":443")
// Manual TLS
r.RunTLS(":443", "server.crt", "server.key")
HTTP/2 and HTTP/3 Support
// HTTP/2 (enabled by default with TLS)
r.RunTLS(":443", "cert.pem", "key.pem")
// HTTP/3 (QUIC) - requires quic-go
r.RunQUIC(":443", "cert.pem", "key.pem")
4. Build & Run
Development Mode
Run with hot reload (requires air):
air
Standard run:
go run main.go
Production Build
Build optimized binary:
# Set production mode
export GIN_MODE=release
# Build for current platform
go build -o server main.go
# Cross-compile for Linux
GOOS=linux GOARCH=amd64 go build -o server-linux main.go
# Run
./server
Build Flags for Production
# Strip debug symbols, optimize
go build -ldflags="-s -w" -o server main.go
# With CGO disabled (for static linking)
CGO_ENABLED=0 go build -ldflags="-s -w" -o server main.go
5. Deployment
Docker Deployment
Dockerfile (multi-stage build):
# Build stage
FROM golang:1.24-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 server .
# Runtime stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
EXPOSE 8080
ENV GIN_MODE=release
CMD ["./server"]
Build and run:
docker build -t my-gin-app .
docker run -p 8080:8080 -e GIN_MODE=release my-gin-app
Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: gin-app
spec:
replicas: 3
selector:
matchLabels:
app: gin-app
template:
metadata:
labels:
app: gin-app
spec:
containers:
- name: gin
image: my-gin-app:latest
ports:
- containerPort: 8080
env:
- name: GIN_MODE
value: "release"
resources:
limits:
memory: "256Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: gin-service
spec:
selector:
app: gin-app
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
Cloud Platform Deployment
Google Cloud Run:
gcloud run deploy gin-app --source . --platform managed --region us-central1
AWS Lambda (using gin-lambda adapter):
import "github.com/awslabs/aws-lambda-go-api-proxy/gin"
Heroku:
# Create Procfile
echo 'web: bin/server' > Procfile
# Set Go version in go.mod (1.24+)
git push heroku main
Systemd Service (Linux Server)
Create /etc/systemd/system/gin-app.service:
[Unit]
Description=Gin Web Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/my-gin-app
ExecStart=/var/www/my-gin-app/server
Environment="GIN_MODE=release"
Environment="PORT=8080"
Restart=on-failure
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable gin-app
sudo systemctl start gin-app
6. Troubleshooting
Port Already in Use
Error: bind: address already in use
Solution:
# Find process using port 8080
lsof -i :8080
# Kill process or change port
PORT=3000 go run main.go
CORS Issues
Install middleware:
go get github.com/gin-contrib/cors
Usage:
import "github.com/gin-contrib/cors"
func main() {
r := gin.Default()
r.Use(cors.Default())
// or custom config
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"https://example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
}))
}
Memory Issues with File Uploads
Default multipart memory is 32MB. Increase if needed:
r.MaxMultipartMemory = 64 << 20 // 64 MiB
Static Files Not Serving
Ensure path is absolute:
r.Static("/assets", "./static")
// Or use embed for production
import "embed"
//go:embed static/*
var staticFS embed.FS
r.StaticFS("/assets", http.FS(staticFS))
"Too Many Open Files" Error
Increase ulimit:
ulimit -n 4096
Or in systemd service:
LimitNOFILE=65535
HTTP/3 Not Working
Ensure certificates are valid and quic-go is properly imported:
go get github.com/quic-go/quic-go
Request Timeout Issues
Set custom timeouts:
srv := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
}
srv.ListenAndServe()