Skip to main content

🐳 Docker Deployment

Containerized sovereignty: Deploy Reforms Messenger with enterprise-grade Docker orchestration

Docker deployment offers the fastest path to sovereign communication infrastructure. This guide covers everything from single-container development to production-ready orchestration with high availability and security.

🚀 Quick Start (5 Minutes)

Single Container Deployment

Get running immediately:

# Pull and run the latest stable release
docker run -d \
--name reforms-messenger \
-p 8443:8443 \
-p 3478:3478/udp \
-v $(pwd)/data:/app/data \
-v $(pwd)/config:/app/config \
-e REFORMS_MODE=production \
reforms/messenger:latest

Access your instance:

  • Web interface: https://localhost:8443
  • Admin panel: https://localhost:8443/admin
  • API endpoint: https://localhost:8443/api

Quick Configuration

Create basic configuration:

# Create config directory
mkdir -p ./config ./data ./ssl

# Generate basic config
cat > ./config/production.yaml << EOF
server:
host: "0.0.0.0"
port: 8443
ssl:
enabled: true
selfSigned: true

signaling:
mode: "zero-knowledge"

crypto:
identityProvider: "self-sovereign"
encryptionLevel: "maximum"

logging:
level: "info"
destination: "stdout"
EOF

📦 Docker Compose Setup

Basic Production Stack

Complete stack with database and monitoring:

# docker-compose.yml
version: '3.8'

services:
reforms-server:
image: reforms/messenger:latest
container_name: reforms-server
restart: unless-stopped
ports:
- "8443:8443"
- "3478:3478/udp"
- "3478:3478/tcp"
- "5349:5349/tcp"
environment:
- REFORMS_MODE=production
- REFORMS_CONFIG_PATH=/app/config/production.yaml
- REFORMS_DB_URL=postgresql://reforms:${DB_PASSWORD}@postgres:5432/reforms
- REFORMS_REDIS_URL=redis://redis:6379
volumes:
- ./config:/app/config:ro
- ./ssl:/app/ssl:ro
- ./data:/app/data
- ./logs:/app/logs
depends_on:
- postgres
- redis
networks:
- reforms-network
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost:8443/health"]
interval: 30s
timeout: 10s
retries: 3

postgres:
image: postgres:15-alpine
container_name: reforms-postgres
restart: unless-stopped
environment:
- POSTGRES_DB=reforms
- POSTGRES_USER=reforms
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
- ./backups:/backups
networks:
- reforms-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U reforms"]
interval: 10s
timeout: 5s
retries: 5

redis:
image: redis:7-alpine
container_name: reforms-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
networks:
- reforms-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3

nginx:
image: nginx:alpine
container_name: reforms-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/ssl:ro
depends_on:
- reforms-server
networks:
- reforms-network

volumes:
postgres-data:
redis-data:

networks:
reforms-network:
driver: bridge

Environment Configuration

Create .env file:

# .env
REFORMS_VERSION=latest
DB_PASSWORD=your_secure_db_password_here
REDIS_PASSWORD=your_secure_redis_password_here
DOMAIN=your-domain.com
SSL_EMAIL=admin@your-domain.com

NGINX Configuration

Create nginx.conf for SSL termination:

events {
worker_connections 1024;
}

http {
upstream reforms-backend {
server reforms-server:8443;
}

server {
listen 80;
server_name ${DOMAIN};
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name ${DOMAIN};

ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;

# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

location / {
proxy_pass https://reforms-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;

# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}

⚙️ Advanced Configuration

High Availability Setup

Multi-node cluster with load balancing:

# docker-compose.ha.yml
version: '3.8'

services:
# Load balancer
haproxy:
image: haproxy:alpine
ports:
- "80:80"
- "443:443"
- "8404:8404" # Stats page
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./ssl:/etc/ssl:ro
depends_on:
- reforms-server-1
- reforms-server-2
- reforms-server-3

# Primary server nodes
reforms-server-1:
image: reforms/messenger:latest
environment:
- REFORMS_NODE_ID=node-1
- REFORMS_CLUSTER_MODE=true
- REFORMS_CLUSTER_NODES=node-1,node-2,node-3
volumes:
- ./config:/app/config:ro
- ./data-1:/app/data
networks:
- reforms-cluster

reforms-server-2:
image: reforms/messenger:latest
environment:
- REFORMS_NODE_ID=node-2
- REFORMS_CLUSTER_MODE=true
- REFORMS_CLUSTER_NODES=node-1,node-2,node-3
volumes:
- ./config:/app/config:ro
- ./data-2:/app/data
networks:
- reforms-cluster

reforms-server-3:
image: reforms/messenger:latest
environment:
- REFORMS_NODE_ID=node-3
- REFORMS_CLUSTER_MODE=true
- REFORMS_CLUSTER_NODES=node-1,node-2,node-3
volumes:
- ./config:/app/config:ro
- ./data-3:/app/data
networks:
- reforms-cluster

# Shared database cluster
postgres-primary:
image: postgres:15-alpine
environment:
- POSTGRES_REPLICATION_MODE=master
- POSTGRES_REPLICATION_USER=replicator
- POSTGRES_REPLICATION_PASSWORD=${REPLICATION_PASSWORD}
volumes:
- postgres-primary-data:/var/lib/postgresql/data

postgres-replica:
image: postgres:15-alpine
environment:
- POSTGRES_REPLICATION_MODE=slave
- POSTGRES_REPLICATION_USER=replicator
- POSTGRES_REPLICATION_PASSWORD=${REPLICATION_PASSWORD}
- POSTGRES_MASTER_HOST=postgres-primary
depends_on:
- postgres-primary
volumes:
- postgres-replica-data:/var/lib/postgresql/data

networks:
reforms-cluster:
driver: overlay
attachable: true

volumes:
postgres-primary-data:
postgres-replica-data:

Healthcare (HIPAA) Configuration

HIPAA-compliant deployment:

# docker-compose.hipaa.yml
version: '3.8'

services:
reforms-server:
image: reforms/messenger:hipaa
environment:
- REFORMS_COMPLIANCE_MODE=HIPAA
- REFORMS_ENCRYPTION_LEVEL=FIPS-140-2
- REFORMS_AUDIT_LOGGING=true
- REFORMS_DATA_RETENTION=never
- REFORMS_GEO_RESTRICTION=US-only
volumes:
- ./config/hipaa.yaml:/app/config/production.yaml:ro
- ./ssl:/app/ssl:ro
- ./audit-logs:/app/audit-logs
- type: tmpfs
target: /tmp
tmpfs:
noexec: true
nosuid: true
size: 1G
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
user: "1000:1000"

# Encrypted database
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_INITDB_ARGS=--auth-host=scram-sha-256
volumes:
- type: volume
source: postgres-encrypted
target: /var/lib/postgresql/data
volume:
driver: local
driver_opts:
type: "tmpfs"
device: "tmpfs"
o: "encryption=aes256"

volumes:
postgres-encrypted:
driver: local
driver_opts:
type: "nfs"
o: "encryption=aes256,backup=daily"

📈 Scaling Strategies

Horizontal Scaling

Auto-scaling with Docker Swarm:

# Initialize swarm
docker swarm init

# Deploy stack
docker stack deploy -c docker-compose.swarm.yml reforms

# Scale services
docker service scale reforms_reforms-server=5
docker service scale reforms_postgres=3

Swarm configuration:

# docker-compose.swarm.yml
version: '3.8'

services:
reforms-server:
image: reforms/messenger:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2G
networks:
- reforms-overlay

networks:
reforms-overlay:
driver: overlay
attachable: true

Kubernetes Deployment

Production-ready Kubernetes manifests:

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: reforms-messenger
labels:
name: reforms-messenger

---
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: reforms-server
namespace: reforms-messenger
spec:
replicas: 3
selector:
matchLabels:
app: reforms-server
template:
metadata:
labels:
app: reforms-server
spec:
containers:
- name: reforms
image: reforms/messenger:latest
ports:
- containerPort: 8443
env:
- name: REFORMS_MODE
value: "production"
- name: REFORMS_CONFIG_PATH
value: "/app/config/production.yaml"
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: ssl
mountPath: /app/ssl
readOnly: true
- name: data
mountPath: /app/data
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
cpu: "2"
livenessProbe:
httpGet:
path: /health
port: 8443
scheme: HTTPS
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8443
scheme: HTTPS
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: config
configMap:
name: reforms-config
- name: ssl
secret:
secretName: reforms-ssl
- name: data
persistentVolumeClaim:
claimName: reforms-data

---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: reforms-service
namespace: reforms-messenger
spec:
selector:
app: reforms-server
ports:
- name: https
port: 8443
targetPort: 8443
- name: stun
port: 3478
targetPort: 3478
protocol: UDP
type: LoadBalancer

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: reforms-ingress
namespace: reforms-messenger
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- reforms.your-domain.com
secretName: reforms-tls
rules:
- host: reforms.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: reforms-service
port:
number: 8443

🔒 Security Hardening

Container Security

Secure container configuration:

services:
reforms-server:
image: reforms/messenger:latest
security_opt:
- no-new-privileges:true
- apparmor:docker-default
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
- CHOWN
- SETGID
- SETUID
read_only: true
user: "1000:1000"
tmpfs:
- /tmp:noexec,nosuid,size=1G
- /var/run:noexec,nosuid,size=100M
ulimits:
nproc: 65535
nofile:
soft: 65535
hard: 65535

Network Security

Network isolation and security:

networks:
reforms-frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
reforms-backend:
driver: bridge
internal: true
ipam:
config:
- subnet: 172.21.0.0/24

Secrets Management

Using Docker secrets:

# Create secrets
echo "your_db_password" | docker secret create db_password -
echo "your_redis_password" | docker secret create redis_password -
echo "your_ssl_cert" | docker secret create ssl_cert -

# Use in compose
services:
reforms-server:
secrets:
- db_password
- redis_password
- ssl_cert
environment:
- REFORMS_DB_PASSWORD_FILE=/run/secrets/db_password

secrets:
db_password:
external: true
redis_password:
external: true
ssl_cert:
external: true

📊 Monitoring & Observability

Comprehensive Monitoring Stack

# docker-compose.monitoring.yml
version: '3.8'

services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'

grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./grafana/datasources:/etc/grafana/provisioning/datasources

loki:
image: grafana/loki:latest
ports:
- "3100:3100"
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
- loki-data:/loki

promtail:
image: grafana/promtail:latest
volumes:
- ./promtail-config.yaml:/etc/promtail/config.yml
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro

volumes:
prometheus-data:
grafana-data:
loki-data:

🚀 Deployment Scripts

Automated Deployment

Complete deployment script:

#!/bin/bash
# deploy.sh - Automated Reforms Messenger deployment

set -euo pipefail

# Configuration
DOMAIN="${1:-localhost}"
EMAIL="${2:-admin@localhost}"
ENVIRONMENT="${3:-production}"

echo "🚀 Deploying Reforms Messenger"
echo "Domain: $DOMAIN"
echo "Environment: $ENVIRONMENT"

# Create directories
mkdir -p {config,data,ssl,logs,backups}

# Generate configuration
cat > config/production.yaml << EOF
server:
host: "0.0.0.0"
port: 8443
domain: "$DOMAIN"
ssl:
enabled: true
certPath: "/app/ssl/fullchain.pem"
keyPath: "/app/ssl/privkey.pem"

signaling:
mode: "zero-knowledge"
retentionPolicy: "never"

crypto:
identityProvider: "self-sovereign"
encryptionLevel: "maximum"

logging:
level: "info"
destination: "file"
path: "/app/logs/reforms.log"
EOF

# Generate SSL certificates (Let's Encrypt)
if [ "$DOMAIN" != "localhost" ]; then
docker run --rm \
-v $(pwd)/ssl:/etc/letsencrypt \
-p 80:80 \
certbot/certbot certonly \
--standalone \
--email "$EMAIL" \
--agree-tos \
--no-eff-email \
-d "$DOMAIN"

cp ssl/live/$DOMAIN/fullchain.pem ssl/
cp ssl/live/$DOMAIN/privkey.pem ssl/
else
# Generate self-signed certificate for localhost
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ssl/privkey.pem \
-out ssl/fullchain.pem \
-subj "/C=US/ST=CA/L=SF/O=Reforms/CN=localhost"
fi

# Generate environment file
cat > .env << EOF
REFORMS_VERSION=latest
DB_PASSWORD=$(openssl rand -base64 32)
REDIS_PASSWORD=$(openssl rand -base64 32)
DOMAIN=$DOMAIN
SSL_EMAIL=$EMAIL
EOF

# Deploy with Docker Compose
docker-compose up -d

# Wait for services to be ready
echo "⏳ Waiting for services to start..."
sleep 30

# Health check
if curl -k -f "https://localhost:8443/health" > /dev/null 2>&1; then
echo "✅ Deployment successful!"
echo "🌐 Access your instance at: https://$DOMAIN"
echo "🔧 Admin panel: https://$DOMAIN/admin"
else
echo "❌ Deployment failed - check logs:"
docker-compose logs
fi

Make it executable:

chmod +x deploy.sh
./deploy.sh your-domain.com admin@your-domain.com production

🔧 Troubleshooting

Common Issues

Container won't start:

# Check logs
docker logs reforms-server

# Check configuration
docker exec reforms-server cat /app/config/production.yaml

# Test connectivity
docker exec reforms-server curl -k https://localhost:8443/health

SSL certificate issues:

# Verify certificate
openssl x509 -in ssl/fullchain.pem -text -noout

# Test SSL connection
openssl s_client -connect localhost:8443 -servername your-domain.com

Performance issues:

# Check resource usage
docker stats

# Monitor application metrics
curl -k https://localhost:8443/metrics

Containerized sovereignty. Enterprise security. Zero compromise.

Deploy with confidence. Scale with purpose. Control with precision.