Repository navigation
Production Deployment
This page provides guidance on preparing and deploying the microservices architecture to a production environment. Production environments require additional considerations for security, reliability, and performance.
Before deploying to production, ensure you've addressed the following items:
- Generate new encryption keys and passwords
- Enable TLS for all services
- Secure all admin interfaces
- Set up proper backup procedures
- Configure monitoring and alerting
- Implement proper logging
- Test failover scenarios
- Document the deployment process
- Enable Consul ACLs
- Switch Vault to non-dev mode
- Implement proper auto-unsealing for Vault
Update your .env file with production-appropriate settings:
# Consul Production Settings
CONSUL_LOG_LEVEL=WARN
CONSUL_DATACENTER=production
CONSUL_ENCRYPT_KEY=<generate-new-key>
CONSUL_ACL_ENABLED=true
CONSUL_ACL_DEFAULT_POLICY=deny
CONSUL_ACL_DOWN_POLICY=extend-cache
CONSUL_ACL_TOKENS_MASTER=<generate-secure-token>
# Traefik Production Settings
TRAEFIK_LOG_LEVEL=WARN
TRAEFIK_DASHBOARD_ENABLED=true
TRAEFIK_DASHBOARD_INSECURE=false
TRAEFIK_TLS_ENABLED=true
TRAEFIK_ACME_EMAIL=admin@yourdomain.com
# Vault Production Settings
VAULT_LOG_LEVEL=WARN
VAULT_DEV_MODE=false
ENABLE_VAULT=true# Generate Consul encryption key
openssl rand -base64 32
# Generate secure tokens
openssl rand -hex 16- Generate TLS certificates:
# Create TLS directory
mkdir -p ./consul/config/certs
# Generate CA certificate
openssl req -new -x509 -days 365 -nodes \
-out ./consul/config/certs/ca.pem \
-keyout ./consul/config/certs/ca-key.pem
# Generate server certificate
openssl req -new -nodes \
-out ./consul/config/certs/server.csr \
-keyout ./consul/config/certs/server-key.pem
# Sign server certificate
openssl x509 -req -days 365 \
-in ./consul/config/certs/server.csr \
-CA ./consul/config/certs/ca.pem \
-CAkey ./consul/config/certs/ca-key.pem \
-CAcreateserial \
-out ./consul/config/certs/server.pem- Update Consul environment variables:
CONSUL_TLS_ENABLED=true
CONSUL_CA_FILE=/consul/config/certs/ca.pem
CONSUL_CERT_FILE=/consul/config/certs/server.pem
CONSUL_KEY_FILE=/consul/config/certs/server-key.pemEnable automatic TLS certificate issuance:
TRAEFIK_TLS_ENABLED=true
TRAEFIK_ACME_EMAIL=admin@yourdomain.comUpdate Traefik configuration in docker-compose.yml:
services:
traefik:
# ...
environment:
# ...
- TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS=true
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_EMAIL=${TRAEFIK_ACME_EMAIL}
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_STORAGE=/letsencrypt/acme.json
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE=true
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE_ENTRYPOINT=web
volumes:
# ...
- letsencrypt:/letsencrypt
volumes:
letsencrypt:Secure the Traefik dashboard:
labels:
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik-dashboard.yourdomain.com`)"
- "traefik.http.routers.traefik-dashboard.service=api@internal"
- "traefik.http.routers.traefik-dashboard.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
- "traefik.http.routers.traefik-dashboard.tls=true"
- "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"Generate basicauth credentials:
htpasswd -n adminImplement IP whitelisting for admin interfaces:
labels:
- "traefik.http.middlewares.admin-ipwhitelist.ipwhitelist.sourcerange=192.168.1.0/24,203.0.113.1/32"
- "traefik.http.routers.traefik-dashboard.middlewares=admin-ipwhitelist"Enable ACLs in Consul:
services:
consul-server:
environment:
- CONSUL_ACL_ENABLED=true
- CONSUL_ACL_DEFAULT_POLICY=deny
- CONSUL_ACL_DOWN_POLICY=extend-cache
- CONSUL_ACL_TOKENS_MASTER=<your-master-token>Create policies and tokens for services:
# Create a policy
cat > service-policy.hcl << EOF
service "my-service" {
policy = "write"
}
service_prefix "" {
policy = "read"
}
EOF
# Create a token with that policy
consul acl policy create -name "my-service-policy" -rules @service-policy.hcl
consul acl token create -description "my-service token" -policy-name "my-service-policy"Switch Vault to non-dev mode:
VAULT_DEV_MODE=falseUpdate Vault configuration:
storage "consul" {
address = "consul-server:8500"
path = "vault/"
token = "<consul-acl-token>"
service_tags = "vault-server"
redirect_addr = "https://vault.yourdomain.com"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/config/certs/vault.pem"
tls_key_file = "/vault/config/certs/vault-key.pem"
}
ui = true
api_addr = "https://vault.yourdomain.com"
cluster_addr = "https://vault.node.yourdomain.com:8201"Implement auto-unsealing (AWS KMS example):
seal "awskms" {
region = "us-west-2"
kms_key_id = "alias/vault-unseal-key"
}Create a multi-node Consul cluster:
services:
consul-server1:
# ...
environment:
- CONSUL_LOCAL_CONFIG={"server":true,"bootstrap_expect":3}
consul-server2:
# ...
environment:
- CONSUL_LOCAL_CONFIG={"server":true,"bootstrap_expect":3,"retry_join":["consul-server1"]}
consul-server3:
# ...
environment:
- CONSUL_LOCAL_CONFIG={"server":true,"bootstrap_expect":3,"retry_join":["consul-server1"]}Run multiple Traefik instances:
services:
traefik1:
# ...
traefik2:
# ...Use a load balancer in front of the Traefik instances.
Set up regular Vault snapshots (if using integrated storage):
#!/bin/bash
# backup-vault.sh
DATE=$(date +%Y-%m-%d-%H-%M)
export VAULT_ADDR=https://vault.yourdomain.com
export VAULT_TOKEN=$(cat /path/to/secure/root-token.txt)
# Create snapshot
vault operator raft snapshot save ./backups/vault/vault-backup-$DATE.snap
# Encrypt the backup
gpg --encrypt --recipient admin@yourdomain.com ./backups/vault/vault-backup-$DATE.snap
# Remove unencrypted backup
rm ./backups/vault/vault-backup-$DATE.snap
# Clean up old backups (keep last 7 days)
find ./backups/vault/ -name "vault-backup-*.snap.gpg" -type f -mtime +7 -deleteSet up as a cron job:
0 3 * * * /path/to/backup-vault.sh >> /var/log/vault-backup.log 2>&1Back up persistent volumes:
#!/bin/bash
# backup-volumes.sh
DATE=$(date +%Y-%m-%d-%H-%M)
BACKUP_DIR="./backups/volumes/$DATE"
mkdir -p $BACKUP_DIR
# Stop the containers
docker-compose down
# Backup volumes
for VOLUME in $(docker volume ls -q | grep microservices); do
docker run --rm -v $VOLUME:/source -v $BACKUP_DIR:/backup alpine \
tar -czf /backup/$VOLUME.tar.gz -C /source .
done
# Restart the containers
docker-compose up -d
# Clean up old backups (keep last 7 days)
find ./backups/volumes/ -type d -mtime +7 -exec rm -rf {} \;Add Prometheus for metrics collection:
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
ports:
- "9090:9090"
networks:
- traefik-net
- consul-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.prometheus.rule=Host(`prometheus.yourdomain.com`)"
- "traefik.http.routers.prometheus.middlewares=admin-ipwhitelist,admin-auth"
- "traefik.http.routers.prometheus.tls=true"
- "traefik.http.routers.prometheus.tls.certresolver=letsencrypt"
volumes:
prometheus-data:Prometheus configuration (./prometheus/prometheus.yml):
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'consul'
consul_sd_configs:
- server: 'consul-server:8500'
relabel_configs:
- source_labels: ['__meta_consul_service']
target_label: 'service'Add Grafana for visualization:
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=<secure-password>
- GF_USERS_ALLOW_SIGN_UP=false
networks:
- traefik-net
- consul-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)"
- "traefik.http.routers.grafana.middlewares=admin-ipwhitelist"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
volumes:
grafana-data:Add AlertManager for alerting:
services:
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
- alertmanager-data:/alertmanager
command:
- --config.file=/etc/alertmanager/alertmanager.yml
- --storage.path=/alertmanager
networks:
- traefik-net
- consul-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.alertmanager.rule=Host(`alerts.yourdomain.com`)"
- "traefik.http.routers.alertmanager.middlewares=admin-ipwhitelist,admin-auth"
- "traefik.http.routers.alertmanager.tls=true"
- "traefik.http.routers.alertmanager.tls.certresolver=letsencrypt"
volumes:
alertmanager-data:AlertManager configuration (./alertmanager/alertmanager.yml):
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.yourdomain.com:587'
smtp_from: 'alerts@yourdomain.com'
smtp_auth_username: 'alerts@yourdomain.com'
smtp_auth_password: '<smtp-password>'
route:
group_by: ['alertname', 'job']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'email-team'
receivers:
- name: 'email-team'
email_configs:
- to: 'team@yourdomain.com'
send_resolved: trueAdd the ELK stack for centralized logging:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0
container_name: elasticsearch
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
networks:
- traefik-net
- consul-net
deploy:
resources:
limits:
memory: 1g
logstash:
image: docker.elastic.co/logstash/logstash:7.14.0
container_name: logstash
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
environment:
- XPACK_MONITORING_ENABLED=false
depends_on:
- elasticsearch
networks:
- traefik-net
- consul-net
kibana:
image: docker.elastic.co/kibana/kibana:7.14.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
networks:
- traefik-net
- consul-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.kibana.rule=Host(`logs.yourdomain.com`)"
- "traefik.http.routers.kibana.middlewares=admin-ipwhitelist,admin-auth"
- "traefik.http.routers.kibana.tls=true"
- "traefik.http.routers.kibana.tls.certresolver=letsencrypt"
volumes:
elasticsearch-data:Add Filebeat to collect logs from services:
services:
filebeat:
image: docker.elastic.co/beats/filebeat:7.14.0
container_name: filebeat
user: root
volumes:
- ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- elasticsearch
- logstash
networks:
- consul-netFilebeat configuration (./filebeat/filebeat.yml):
filebeat.inputs:
- type: container
enabled: true
paths:
- /var/lib/docker/containers/*/*.log
processors:
- add_docker_metadata: ~
- add_host_metadata: ~
output.logstash:
hosts: ["logstash:5044"]Scale services horizontally:
services:
my-service:
deploy:
mode: replicated
replicas: 3To scale manually:
docker-compose up -d --scale my-service=5For cloud environments, configure a load balancer in front of Traefik:
AWS Example:
Load Balancer --> Traefik Instances --> Microservices
Ensure sticky sessions for path-based routing:
ALB Cookie Stickiness: AWSALB
Duration: 3600s
For production, consider managing your infrastructure with tools like:
- Terraform for cloud resources
- Ansible for configuration management
- GitHub Actions or Jenkins for CI/CD pipelines
Example Terraform structure:
terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ ├── networking/
│ ├── compute/
│ ├── database/
│ └── dns/
└── environments/
├── staging/
└── production/
Create a CI/CD pipeline for automated deployments:
# GitHub Actions Example (.github/workflows/deploy.yml)
name: Deploy to Production
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: Deploy to production
run: |
ssh user@your-production-server.com "cd /path/to/deployment && git pull && docker-compose up -d --build"Create a detailed disaster recovery plan:
-
Failover Procedures:
- Document steps to activate backup servers
- Automate where possible
-
Backup Verification:
- Regularly test backup restoration
- Document verification procedures
-
Recovery Time Objectives (RTO):
- Define maximum acceptable downtime
- Plan resources accordingly
-
Recovery Point Objectives (RPO):
- Define acceptable data loss
- Adjust backup frequency accordingly
-
Communication Plan:
- Define who to notify in case of outage
- Establish a communication protocol
Implement regular security audits:
-
Container Security Scanning:
docker scan myservice:latest
-
Network Penetration Testing:
- Engage external security professionals
- Test all exposed interfaces
-
Secret Rotation:
- Implement automated secret rotation
- Monitor for unauthorized access
-
Compliance Checks:
- Verify against relevant standards (PCI-DSS, HIPAA, etc.)
- Document compliance status
Before going live, verify:
- All services are running and healthy
- TLS certificates are valid and secure
- Backups are working and verified
- Monitoring is capturing all critical metrics
- Alerts are properly configured and tested
- Logging is capturing all required information
- All admin interfaces are securely accessible
- Load testing has been performed
- Security scans are clean
- Documentation is up-to-date
- Recovery procedures are documented and tested
- Team is trained on operations and maintenance
This checklist ensures your production deployment is robust, secure, and maintainable. HA
Run multiple Vault instances with Consul backend:
services:
vault1:
# ...
vault2:
# ...Set up regular Consul snapshots:
#!/bin/bash
# backup-consul.sh
DATE=$(date +%Y-%m-%d-%H-%M)
docker exec consul-server consul snapshot save /consul/data/backup-$DATE.snap
docker cp consul-server:/consul/data/backup-$DATE.snap ./backups/consul/
# Clean up old backups (keep last 7 days)
find ./backups/consul/ -name "backup-*.snap" -type f -mtime +7 -deleteSet up as a cron job:
0 2 * * * /path/to/backup-consul.sh >> /var/log/consul-backup.log 2>&1- Add your services (see [Adding Services](Adding-Services)) [Architecture Overview](Architecture-Overview) - Detailed explanation of the architecture design [Core Components](Core-Components) - Information about Consul, Traefik, and Vault [Detailed Setup](Detailed-Setup) - Step-by-step setup instructions [Adding Services](Adding-Services) - How to add microservices to the architecture [Service Registration](Service-Registration) - Methods for registering services with Consul [Service Routing](Service-Routing) - Configuring Traefik for routing to services [Secret Management](Secret-Management) - Working with Vault for secrets [Health Checks](Health-Checks) - Implementing and monitoring service health [Advanced Features](Advanced-Features) - Advanced capabilities of each component [Production Deployment](Production-Deployment) - Checklist and best practices for production