Skip to main content

Docker Deployment

This guide covers deploying Posthoot using Docker and Docker Compose. This is the recommended approach for most users as it provides a good balance of simplicity and production readiness.

Prerequisites

Before you begin, ensure you have:
  • Docker installed and running
  • Docker Compose installed
  • Git for cloning the repository
  • Basic knowledge of Docker concepts

Quick Start

1. Clone the Repository

git clone https://github.com/posthoot/posthoot-backend.git
cd posthoot-backend

2. Configure Environment

Copy the example environment file:
cp .env.example .env
Edit .env with your configuration:
# Server settings
SERVER_HOST=0.0.0.0
SERVER_PORT=9001
PUBLIC_URL=http://your-domain.com

# Database (PostgreSQL)
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_USER=posthoot_user
POSTGRES_PASSWORD=your_secure_password
POSTGRES_DB=posthoot
POSTGRES_SSLMODE=disable

# Security
JWT_SECRET=your_very_long_and_secure_jwt_secret_key_here

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DB=0

# Admin account
SUPERADMIN_EMAIL=admin@yourdomain.com
SUPERADMIN_PASSWORD=secure_admin_password
SUPERADMIN_NAME=Admin

# SMTP (for sending emails)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@yourdomain.com
SMTP_PROVIDER=GMAIL

3. Create Docker Compose File

Create docker-compose.yml:
version: '3.8'

services:
  posthoot-server:
    build: .
    ports:
      - "9001:9001"
    environment:
      - POSTGRES_HOST=postgres
      - REDIS_HOST=redis
    depends_on:
      - postgres
      - redis
    volumes:
      - ./storage:/app/storage
    restart: unless-stopped
    networks:
      - posthoot-network

  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=posthoot
      - POSTGRES_USER=posthoot_user
      - POSTGRES_PASSWORD=your_secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - posthoot-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U posthoot_user -d posthoot"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass your_redis_password
    volumes:
      - redis_data:/data
    restart: unless-stopped
    networks:
      - posthoot-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  asynqmon:
    image: hibiken/asynqmon:latest
    environment:
      - REDIS_ADDR=redis:6379
    ports:
      - "8080:8080"
    depends_on:
      - redis
    networks:
      - posthoot-network

volumes:
  postgres_data:
  redis_data:

networks:
  posthoot-network:
    driver: bridge

4. Build and Start

# Build the images
docker-compose build

# Start all services
docker-compose up -d

# Check status
docker-compose ps

Configuration

Environment Variables

Key environment variables for Docker deployment:
VariableDescriptionDefaultRequired
SERVER_HOSTServer bind address0.0.0.0No
SERVER_PORTServer port9001No
POSTGRES_HOSTDatabase hostpostgresYes
POSTGRES_USERDatabase username-Yes
POSTGRES_PASSWORDDatabase password-Yes
POSTGRES_DBDatabase nameposthootNo
REDIS_HOSTRedis hostredisNo
REDIS_PASSWORDRedis password-No
JWT_SECRETJWT signing secret-Yes

Volume Mounts

The setup includes several volume mounts:
  • PostgreSQL data: postgres_data:/var/lib/postgresql/data
  • Redis data: redis_data:/data
  • Application storage: ./storage:/app/storage

Network Configuration

All services communicate through the posthoot-network bridge network, providing:
  • Isolated communication between services
  • Automatic DNS resolution
  • No external network exposure

Management

Basic Commands

# Start services
docker-compose up -d

# Stop services
docker-compose down

# View logs
docker-compose logs -f

# View specific service logs
docker-compose logs -f posthoot-server

# Restart services
docker-compose restart

# Rebuild and restart
docker-compose up -d --build

Monitoring

# Check service status
docker-compose ps

# View resource usage
docker stats

# Check container health
docker-compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"

Backup and Restore

Database Backup

# Create backup
docker-compose exec postgres pg_dump -U posthoot_user posthoot > backup.sql

# Restore backup
docker-compose exec -T postgres psql -U posthoot_user posthoot < backup.sql

Volume Backup

# Backup PostgreSQL data
docker run --rm -v posthoot_postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres_backup.tar.gz -C /data .

# Backup Redis data
docker run --rm -v posthoot_redis_data:/data -v $(pwd):/backup alpine tar czf /backup/redis_backup.tar.gz -C /data .

Production Deployment

Using External Database

For production, consider using managed database services:
services:
  posthoot-server:
    build: .
    environment:
      - POSTGRES_HOST=your-managed-db-host
      - POSTGRES_PORT=5432
      - POSTGRES_USER=your-db-user
      - POSTGRES_PASSWORD=your-db-password
      - POSTGRES_SSLMODE=require
    # Remove postgres dependency
    depends_on:
      - redis

Using External Redis

services:
  posthoot-server:
    build: .
    environment:
      - REDIS_HOST=your-redis-host
      - REDIS_PORT=6379
      - REDIS_PASSWORD=your-redis-password
    # Remove redis dependency
    depends_on: []

Reverse Proxy Setup

Add Nginx for SSL termination:
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - posthoot-server
    networks:
      - posthoot-network
Create nginx.conf:
events {
    worker_connections 1024;
}

http {
    upstream posthoot {
        server posthoot-server:9001;
    }

    server {
        listen 80;
        server_name your-domain.com;
        return 301 https://$server_name$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name your-domain.com;

        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/key.pem;

        location / {
            proxy_pass http://posthoot;
            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;
        }
    }
}

Security

Environment File Security

# Set proper permissions
chmod 600 .env

# Use Docker secrets in production
docker secret create postgres_password ./postgres_password.txt

Network Security

# Restrict external access
services:
  posthoot-server:
    # Remove ports mapping for internal only
    expose:
      - "9001"
    networks:
      - posthoot-network

Container Security

services:
  posthoot-server:
    # Run as non-root user
    user: "1000:1000"
    # Read-only root filesystem
    read_only: true
    # Security options
    security_opt:
      - no-new-privileges:true

Troubleshooting

Common Issues

1. Database Connection Issues

# Check if PostgreSQL is running
docker-compose ps postgres

# Check PostgreSQL logs
docker-compose logs postgres

# Test connection
docker-compose exec postgres pg_isready -U posthoot_user

2. Redis Connection Issues

# Check if Redis is running
docker-compose ps redis

# Check Redis logs
docker-compose logs redis

# Test Redis connection
docker-compose exec redis redis-cli ping

3. Port Conflicts

# Check what's using the port
sudo netstat -tlnp | grep :9001

# Change port in docker-compose.yml
ports:
  - "9002:9001"

4. Permission Issues

# Fix storage directory permissions
sudo chown -R 1000:1000 ./storage

# Fix volume permissions
docker-compose down
sudo chown -R 999:999 ./postgres_data
docker-compose up -d

Debugging

# Access container shell
docker-compose exec posthoot-server /bin/sh

# Check environment variables
docker-compose exec posthoot-server env

# View container details
docker inspect posthoot-server

Performance Tuning

Resource Limits

services:
  posthoot-server:
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'
        reservations:
          memory: 512M
          cpus: '0.5'

Database Optimization

services:
  postgres:
    environment:
      - POSTGRES_SHARED_BUFFERS=256MB
      - POSTGRES_MAX_CONNECTIONS=100
      - POSTGRES_WORK_MEM=16MB

Redis Optimization

services:
  redis:
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru

Monitoring

Health Checks

All services include health checks:
services:
  postgres:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U posthoot_user -d posthoot"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

Logging

# View all logs
docker-compose logs -f

# View specific service logs
docker-compose logs -f posthoot-server

# Export logs
docker-compose logs > posthoot.log

Metrics

Consider adding monitoring:
services:
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - posthoot-network

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    networks:
      - posthoot-network

Support

For Docker-specific issues:
  1. Check Docker and Docker Compose logs
  2. Verify environment variables are set correctly
  3. Ensure ports are not conflicting
  4. Check volume permissions and mounts

Next Steps

After successful deployment:
  1. Configure monitoring and alerting
  2. Set up backups and test recovery
  3. Implement security best practices
  4. Plan scaling strategies
  5. Document procedures for your team