> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xem.email/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker Deployment

> Deploy Posthoot using Docker and Docker Compose

# 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

```bash theme={"dark"}
git clone https://github.com/posthoot/posthoot-backend.git
cd posthoot-backend
```

### 2. Configure Environment

Copy the example environment file:

```bash theme={"dark"}
cp .env.example .env
```

Edit `.env` with your configuration:

```env theme={"dark"}
# 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`:

```yaml theme={"dark"}
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

```bash theme={"dark"}
# 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:

| Variable            | Description         | Default    | Required |
| ------------------- | ------------------- | ---------- | -------- |
| `SERVER_HOST`       | Server bind address | `0.0.0.0`  | No       |
| `SERVER_PORT`       | Server port         | `9001`     | No       |
| `POSTGRES_HOST`     | Database host       | `postgres` | Yes      |
| `POSTGRES_USER`     | Database username   | -          | Yes      |
| `POSTGRES_PASSWORD` | Database password   | -          | Yes      |
| `POSTGRES_DB`       | Database name       | `posthoot` | No       |
| `REDIS_HOST`        | Redis host          | `redis`    | No       |
| `REDIS_PASSWORD`    | Redis password      | -          | No       |
| `JWT_SECRET`        | JWT 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

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# 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:

```yaml theme={"dark"}
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

```yaml theme={"dark"}
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:

```yaml theme={"dark"}
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`:

```nginx theme={"dark"}
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

```bash theme={"dark"}
# Set proper permissions
chmod 600 .env

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

### Network Security

```yaml theme={"dark"}
# Restrict external access
services:
  posthoot-server:
    # Remove ports mapping for internal only
    expose:
      - "9001"
    networks:
      - posthoot-network
```

### Container Security

```yaml theme={"dark"}
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

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# Check what's using the port
sudo netstat -tlnp | grep :9001

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

#### 4. Permission Issues

```bash theme={"dark"}
# 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

```bash theme={"dark"}
# 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

```yaml theme={"dark"}
services:
  posthoot-server:
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'
        reservations:
          memory: 512M
          cpus: '0.5'
```

### Database Optimization

```yaml theme={"dark"}
services:
  postgres:
    environment:
      - POSTGRES_SHARED_BUFFERS=256MB
      - POSTGRES_MAX_CONNECTIONS=100
      - POSTGRES_WORK_MEM=16MB
```

### Redis Optimization

```yaml theme={"dark"}
services:
  redis:
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
```

## Monitoring

### Health Checks

All services include health checks:

```yaml theme={"dark"}
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

```bash theme={"dark"}
# 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:

```yaml theme={"dark"}
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
