547 lines
9.6 KiB
Markdown
547 lines
9.6 KiB
Markdown
|
|
# 🚀 Deployment Guide - Goa-GEL Documentation Service
|
||
|
|
|
||
|
|
Complete guide to deploy the documentation service in various environments.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 Prerequisites
|
||
|
|
|
||
|
|
- Docker 20.10+ or Docker Desktop
|
||
|
|
- Docker Compose 1.29+ (if using compose)
|
||
|
|
- Port 8080 available (or configure different port)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🐳 Docker Deployment (Recommended)
|
||
|
|
|
||
|
|
### Quick Deploy
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# From the Documentation directory
|
||
|
|
docker build -t goa-gel-docs .
|
||
|
|
docker run -d -p 8080:80 --name goa-gel-docs goa-gel-docs
|
||
|
|
|
||
|
|
# Verify it's running
|
||
|
|
docker ps | grep goa-gel-docs
|
||
|
|
|
||
|
|
# Access the documentation
|
||
|
|
open http://localhost:8080
|
||
|
|
```
|
||
|
|
|
||
|
|
### Docker Compose Deploy
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Start the service
|
||
|
|
docker-compose up -d
|
||
|
|
|
||
|
|
# Check logs
|
||
|
|
docker-compose logs -f documentation
|
||
|
|
|
||
|
|
# Stop the service
|
||
|
|
docker-compose down
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🌐 Production Deployment
|
||
|
|
|
||
|
|
### 1. Build Production Image
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Build with version tag
|
||
|
|
docker build -t goa-gel-docs:1.0.0 .
|
||
|
|
|
||
|
|
# Tag for production registry
|
||
|
|
docker tag goa-gel-docs:1.0.0 your-registry.com/goa-gel-docs:1.0.0
|
||
|
|
docker tag goa-gel-docs:1.0.0 your-registry.com/goa-gel-docs:latest
|
||
|
|
|
||
|
|
# Push to registry
|
||
|
|
docker push your-registry.com/goa-gel-docs:1.0.0
|
||
|
|
docker push your-registry.com/goa-gel-docs:latest
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Deploy to Server
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Pull image on production server
|
||
|
|
docker pull your-registry.com/goa-gel-docs:1.0.0
|
||
|
|
|
||
|
|
# Run with production settings
|
||
|
|
docker run -d \
|
||
|
|
--name goa-gel-docs \
|
||
|
|
-p 8080:80 \
|
||
|
|
--restart always \
|
||
|
|
--memory="256m" \
|
||
|
|
--cpus="0.5" \
|
||
|
|
-l "service=documentation" \
|
||
|
|
your-registry.com/goa-gel-docs:1.0.0
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Health Check
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check if service is healthy
|
||
|
|
curl http://localhost:8080
|
||
|
|
|
||
|
|
# Expected output: HTML of homepage
|
||
|
|
|
||
|
|
# Check Docker health status
|
||
|
|
docker inspect --format='{{.State.Health.Status}}' goa-gel-docs
|
||
|
|
# Expected: healthy
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ☸️ Kubernetes Deployment
|
||
|
|
|
||
|
|
### Create Kubernetes Manifests
|
||
|
|
|
||
|
|
**deployment.yaml**:
|
||
|
|
```yaml
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: goa-gel-docs
|
||
|
|
namespace: goa-gel
|
||
|
|
spec:
|
||
|
|
replicas: 2
|
||
|
|
selector:
|
||
|
|
matchLabels:
|
||
|
|
app: goa-gel-docs
|
||
|
|
template:
|
||
|
|
metadata:
|
||
|
|
labels:
|
||
|
|
app: goa-gel-docs
|
||
|
|
spec:
|
||
|
|
containers:
|
||
|
|
- name: goa-gel-docs
|
||
|
|
image: your-registry.com/goa-gel-docs:1.0.0
|
||
|
|
ports:
|
||
|
|
- containerPort: 80
|
||
|
|
resources:
|
||
|
|
limits:
|
||
|
|
memory: "256Mi"
|
||
|
|
cpu: "500m"
|
||
|
|
requests:
|
||
|
|
memory: "128Mi"
|
||
|
|
cpu: "250m"
|
||
|
|
livenessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /
|
||
|
|
port: 80
|
||
|
|
initialDelaySeconds: 5
|
||
|
|
periodSeconds: 10
|
||
|
|
readinessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /
|
||
|
|
port: 80
|
||
|
|
initialDelaySeconds: 3
|
||
|
|
periodSeconds: 5
|
||
|
|
```
|
||
|
|
|
||
|
|
**service.yaml**:
|
||
|
|
```yaml
|
||
|
|
apiVersion: v1
|
||
|
|
kind: Service
|
||
|
|
metadata:
|
||
|
|
name: goa-gel-docs
|
||
|
|
namespace: goa-gel
|
||
|
|
spec:
|
||
|
|
selector:
|
||
|
|
app: goa-gel-docs
|
||
|
|
ports:
|
||
|
|
- port: 80
|
||
|
|
targetPort: 80
|
||
|
|
protocol: TCP
|
||
|
|
type: ClusterIP
|
||
|
|
```
|
||
|
|
|
||
|
|
**ingress.yaml**:
|
||
|
|
```yaml
|
||
|
|
apiVersion: networking.k8s.io/v1
|
||
|
|
kind: Ingress
|
||
|
|
metadata:
|
||
|
|
name: goa-gel-docs
|
||
|
|
namespace: goa-gel
|
||
|
|
annotations:
|
||
|
|
nginx.ingress.kubernetes.io/rewrite-target: /
|
||
|
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||
|
|
spec:
|
||
|
|
ingressClassName: nginx
|
||
|
|
tls:
|
||
|
|
- hosts:
|
||
|
|
- docs.goa-gel.gov.in
|
||
|
|
secretName: goa-gel-docs-tls
|
||
|
|
rules:
|
||
|
|
- host: docs.goa-gel.gov.in
|
||
|
|
http:
|
||
|
|
paths:
|
||
|
|
- path: /
|
||
|
|
pathType: Prefix
|
||
|
|
backend:
|
||
|
|
service:
|
||
|
|
name: goa-gel-docs
|
||
|
|
port:
|
||
|
|
number: 80
|
||
|
|
```
|
||
|
|
|
||
|
|
### Deploy to Kubernetes
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create namespace
|
||
|
|
kubectl create namespace goa-gel
|
||
|
|
|
||
|
|
# Apply manifests
|
||
|
|
kubectl apply -f deployment.yaml
|
||
|
|
kubectl apply -f service.yaml
|
||
|
|
kubectl apply -f ingress.yaml
|
||
|
|
|
||
|
|
# Check deployment
|
||
|
|
kubectl get pods -n goa-gel
|
||
|
|
kubectl get svc -n goa-gel
|
||
|
|
kubectl get ingress -n goa-gel
|
||
|
|
|
||
|
|
# Check logs
|
||
|
|
kubectl logs -f deployment/goa-gel-docs -n goa-gel
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 HTTPS/SSL Setup
|
||
|
|
|
||
|
|
### Option 1: Let's Encrypt (Certbot)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Install certbot
|
||
|
|
sudo apt-get install certbot python3-certbot-nginx
|
||
|
|
|
||
|
|
# Get certificate
|
||
|
|
sudo certbot --nginx -d docs.goa-gel.gov.in
|
||
|
|
|
||
|
|
# Auto-renewal is configured automatically
|
||
|
|
# Test renewal
|
||
|
|
sudo certbot renew --dry-run
|
||
|
|
```
|
||
|
|
|
||
|
|
### Option 2: Custom Certificate
|
||
|
|
|
||
|
|
```nginx
|
||
|
|
# Add to nginx.conf
|
||
|
|
server {
|
||
|
|
listen 443 ssl http2;
|
||
|
|
server_name docs.goa-gel.gov.in;
|
||
|
|
|
||
|
|
ssl_certificate /etc/ssl/certs/goa-gel-docs.crt;
|
||
|
|
ssl_certificate_key /etc/ssl/private/goa-gel-docs.key;
|
||
|
|
|
||
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
|
|
|
||
|
|
# ... rest of config
|
||
|
|
}
|
||
|
|
|
||
|
|
# Redirect HTTP to HTTPS
|
||
|
|
server {
|
||
|
|
listen 80;
|
||
|
|
server_name docs.goa-gel.gov.in;
|
||
|
|
return 301 https://$server_name$request_uri;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 Reverse Proxy Setup
|
||
|
|
|
||
|
|
### Nginx Reverse Proxy
|
||
|
|
|
||
|
|
```nginx
|
||
|
|
# /etc/nginx/sites-available/goa-gel-docs
|
||
|
|
|
||
|
|
upstream docs_backend {
|
||
|
|
server localhost:8080;
|
||
|
|
}
|
||
|
|
|
||
|
|
server {
|
||
|
|
listen 80;
|
||
|
|
server_name docs.goa-gel.gov.in;
|
||
|
|
|
||
|
|
location / {
|
||
|
|
proxy_pass http://docs_backend;
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Enable site
|
||
|
|
sudo ln -s /etc/nginx/sites-available/goa-gel-docs /etc/nginx/sites-enabled/
|
||
|
|
sudo nginx -t
|
||
|
|
sudo systemctl reload nginx
|
||
|
|
```
|
||
|
|
|
||
|
|
### Apache Reverse Proxy
|
||
|
|
|
||
|
|
```apache
|
||
|
|
# /etc/apache2/sites-available/goa-gel-docs.conf
|
||
|
|
|
||
|
|
<VirtualHost *:80>
|
||
|
|
ServerName docs.goa-gel.gov.in
|
||
|
|
|
||
|
|
ProxyPreserveHost On
|
||
|
|
ProxyPass / http://localhost:8080/
|
||
|
|
ProxyPassReverse / http://localhost:8080/
|
||
|
|
|
||
|
|
ErrorLog ${APACHE_LOG_DIR}/goa-gel-docs-error.log
|
||
|
|
CustomLog ${APACHE_LOG_DIR}/goa-gel-docs-access.log combined
|
||
|
|
</VirtualHost>
|
||
|
|
```
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Enable modules and site
|
||
|
|
sudo a2enmod proxy proxy_http
|
||
|
|
sudo a2ensite goa-gel-docs
|
||
|
|
sudo systemctl reload apache2
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 Monitoring
|
||
|
|
|
||
|
|
### Health Check Endpoint
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check if service is running
|
||
|
|
curl -f http://localhost:8080/ || echo "Service down"
|
||
|
|
|
||
|
|
# Check response time
|
||
|
|
time curl -s http://localhost:8080/ > /dev/null
|
||
|
|
```
|
||
|
|
|
||
|
|
### Docker Stats
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Monitor resource usage
|
||
|
|
docker stats goa-gel-docs
|
||
|
|
|
||
|
|
# Expected:
|
||
|
|
# CPU: < 1% idle, < 10% under load
|
||
|
|
# Memory: ~20-50MB
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logs
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# View logs
|
||
|
|
docker logs -f goa-gel-docs
|
||
|
|
|
||
|
|
# Last 100 lines
|
||
|
|
docker logs --tail 100 goa-gel-docs
|
||
|
|
|
||
|
|
# Logs since timestamp
|
||
|
|
docker logs --since 2024-01-01T00:00:00 goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔧 Troubleshooting
|
||
|
|
|
||
|
|
### Service Won't Start
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check if port is in use
|
||
|
|
lsof -i :8080
|
||
|
|
|
||
|
|
# Check Docker logs
|
||
|
|
docker logs goa-gel-docs
|
||
|
|
|
||
|
|
# Try different port
|
||
|
|
docker run -d -p 9090:80 --name goa-gel-docs goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
### High Memory Usage
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Set memory limit
|
||
|
|
docker update --memory="256m" goa-gel-docs
|
||
|
|
|
||
|
|
# Or recreate with limit
|
||
|
|
docker stop goa-gel-docs
|
||
|
|
docker rm goa-gel-docs
|
||
|
|
docker run -d \
|
||
|
|
-p 8080:80 \
|
||
|
|
--memory="256m" \
|
||
|
|
--name goa-gel-docs \
|
||
|
|
goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
### Slow Performance
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check resource usage
|
||
|
|
docker stats goa-gel-docs
|
||
|
|
|
||
|
|
# Increase CPU allocation
|
||
|
|
docker update --cpus="1.0" goa-gel-docs
|
||
|
|
|
||
|
|
# Enable gzip compression (already enabled in nginx.conf)
|
||
|
|
# Check if compression is working
|
||
|
|
curl -H "Accept-Encoding: gzip" -I http://localhost:8080/
|
||
|
|
# Should see: Content-Encoding: gzip
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 Updates
|
||
|
|
|
||
|
|
### Update Documentation Content
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Update markdown files in docs/
|
||
|
|
# Then rebuild and redeploy
|
||
|
|
|
||
|
|
docker build -t goa-gel-docs:1.0.1 .
|
||
|
|
docker stop goa-gel-docs
|
||
|
|
docker rm goa-gel-docs
|
||
|
|
docker run -d -p 8080:80 --name goa-gel-docs goa-gel-docs:1.0.1
|
||
|
|
```
|
||
|
|
|
||
|
|
### Zero-Downtime Update (with 2+ instances)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Build new version
|
||
|
|
docker build -t goa-gel-docs:1.0.1 .
|
||
|
|
|
||
|
|
# Start new container on different port
|
||
|
|
docker run -d -p 8081:80 --name goa-gel-docs-new goa-gel-docs:1.0.1
|
||
|
|
|
||
|
|
# Test new version
|
||
|
|
curl http://localhost:8081/
|
||
|
|
|
||
|
|
# Update load balancer to point to 8081
|
||
|
|
# Then stop old container
|
||
|
|
docker stop goa-gel-docs
|
||
|
|
docker rm goa-gel-docs
|
||
|
|
|
||
|
|
# Rename new container
|
||
|
|
docker rename goa-gel-docs-new goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔐 Security Best Practices
|
||
|
|
|
||
|
|
### 1. Run as Non-Root User
|
||
|
|
|
||
|
|
Update Dockerfile:
|
||
|
|
```dockerfile
|
||
|
|
# Add after FROM nginx:alpine
|
||
|
|
RUN adduser -D -u 1000 docsuser
|
||
|
|
USER docsuser
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Read-Only Filesystem
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker run -d \
|
||
|
|
-p 8080:80 \
|
||
|
|
--read-only \
|
||
|
|
--tmpfs /tmp \
|
||
|
|
--tmpfs /var/run \
|
||
|
|
--tmpfs /var/cache/nginx \
|
||
|
|
--name goa-gel-docs \
|
||
|
|
goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Network Isolation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create isolated network
|
||
|
|
docker network create goa-gel-network
|
||
|
|
|
||
|
|
# Run with network
|
||
|
|
docker run -d \
|
||
|
|
-p 8080:80 \
|
||
|
|
--network goa-gel-network \
|
||
|
|
--name goa-gel-docs \
|
||
|
|
goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Security Scanning
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Scan image for vulnerabilities
|
||
|
|
docker scan goa-gel-docs
|
||
|
|
|
||
|
|
# Or use Trivy
|
||
|
|
trivy image goa-gel-docs
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📈 Performance Optimization
|
||
|
|
|
||
|
|
### CDN Setup
|
||
|
|
|
||
|
|
Use a CDN like Cloudflare for static assets:
|
||
|
|
|
||
|
|
1. Point domain to Cloudflare
|
||
|
|
2. Enable caching for:
|
||
|
|
- `/css/*`
|
||
|
|
- `/js/*`
|
||
|
|
- `/docs/*`
|
||
|
|
3. Enable Brotli compression
|
||
|
|
4. Enable HTTP/3
|
||
|
|
|
||
|
|
### Caching Headers
|
||
|
|
|
||
|
|
Already configured in `nginx.conf`:
|
||
|
|
```nginx
|
||
|
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||
|
|
expires 1y;
|
||
|
|
add_header Cache-Control "public, immutable";
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🧪 Testing Deployment
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Test homepage
|
||
|
|
curl -I http://localhost:8080/
|
||
|
|
# Expected: 200 OK
|
||
|
|
|
||
|
|
# 2. Test viewer
|
||
|
|
curl -I http://localhost:8080/viewer.html
|
||
|
|
# Expected: 200 OK
|
||
|
|
|
||
|
|
# 3. Test documentation
|
||
|
|
curl http://localhost:8080/docs/USER_GUIDE.md
|
||
|
|
# Expected: Markdown content
|
||
|
|
|
||
|
|
# 4. Test 404 handling
|
||
|
|
curl -I http://localhost:8080/nonexistent
|
||
|
|
# Expected: 404 Not Found
|
||
|
|
|
||
|
|
# 5. Load test (requires Apache Bench)
|
||
|
|
ab -n 1000 -c 10 http://localhost:8080/
|
||
|
|
# Should handle 1000 requests easily
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📞 Support
|
||
|
|
|
||
|
|
For deployment issues:
|
||
|
|
- **Email**: devops@goa.gov.in
|
||
|
|
- **Documentation**: README.md in this directory
|
||
|
|
- **Source**: GitHub repository
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Version**: 1.0.0
|
||
|
|
**Last Updated**: February 2026
|