Docker Production Deployment
This guide covers deploying AutoCom using Docker Compose with production-optimized configurations.
Prerequisites
- Docker 24.0+
- Docker Compose 2.0+
- At least 4GB RAM
- 20GB available disk space
Production Dockerfile
AutoCom uses a multi-stage Dockerfile optimized for production:
# Stage 1: Dependencies - Install Composer packages
FROM composer:latest AS composer-deps
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--no-interaction \
--prefer-dist \
--ignore-platform-reqs
# Stage 2: Base - Build PHP extensions
FROM php:8.4-fpm-alpine AS base
# Install extensions: pdo_pgsql, redis, opcache, etc.
# Copy optimized PHP configuration
# Generate optimized autoloader
# Stage 3: Production - Minimal runtime
FROM php:8.4-fpm-alpine AS production
# Copy only what's needed for runtime
# Set proper permissions
Key Optimizations
| Optimization | Benefit |
|---|---|
| Multi-stage build | Smaller final image (~150MB) |
| Alpine base | Minimal attack surface |
| OPcache precompilation | Faster startup time |
| Route/View caching | Reduced runtime overhead |
Building Production Images
# Build all production images
docker compose -f docker-compose.prod.yml build
# Build specific service
docker compose -f docker-compose.prod.yml build app
# Build without cache (for clean rebuild)
docker compose -f docker-compose.prod.yml build --no-cache
Docker Compose Configuration
Environment Variables
Create a .env file in the project root:
# Application
APP_NAME=AutoCom
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
# Database
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=autocom
DB_USERNAME=autocom
DB_PASSWORD=your-secure-password
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password
# Cache & Queue
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
Production Compose File
The docker-compose.prod.yml includes:
services:
app:
build:
context: ./backend
dockerfile: Dockerfile.prod
environment:
- APP_ENV=production
depends_on:
- postgres
- redis
nginx:
image: nginx:alpine
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
- "443:443"
postgres:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: autocom
POSTGRES_USER: autocom
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
horizon:
build:
context: ./backend
dockerfile: Dockerfile.prod
command: php artisan horizon
depends_on:
- app
- redis
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.prod
environment:
- NEXT_PUBLIC_API_URL=${APP_URL}/api/v1
volumes:
postgres_data:
redis_data:
Starting Production Services
# Start all services in detached mode
docker compose -f docker-compose.prod.yml up -d
# View logs
docker compose -f docker-compose.prod.yml logs -f
# Check service status
docker compose -f docker-compose.prod.yml ps
Running Migrations
# Run database migrations
docker compose -f docker-compose.prod.yml exec app php artisan migrate --force
# Seed initial data (if needed)
docker compose -f docker-compose.prod.yml exec app php artisan db:seed --force
Health Checks
The production setup includes health checks for all services:
PHP-FPM Health Check
# Check PHP-FPM ping endpoint
docker compose exec app /usr/local/bin/health-check.sh
The health check script uses FastCGI to ping PHP-FPM:
#!/bin/sh
SCRIPT_NAME=/fpm-ping \
SCRIPT_FILENAME=/fpm-ping \
REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000 | grep -q pong
Nginx Health Check
# Check nginx health endpoint
curl http://localhost/health
SSL/TLS Configuration
For production, configure SSL using Let's Encrypt:
# Add to docker-compose.prod.yml
services:
nginx:
volumes:
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
certbot:
image: certbot/certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
command: certonly --webroot -w /var/www/certbot -d your-domain.com
Backup Configuration
Database Backup
# Create backup
docker compose exec postgres pg_dump -U autocom autocom > backup.sql
# Restore backup
docker compose exec -T postgres psql -U autocom autocom < backup.sql
Redis Backup
# Trigger Redis save
docker compose exec redis redis-cli -a ${REDIS_PASSWORD} BGSAVE
# Copy RDB file
docker cp $(docker compose ps -q redis):/data/dump.rdb ./redis-backup.rdb
Monitoring
View Resource Usage
# Check container stats
docker stats
# Check specific service
docker compose -f docker-compose.prod.yml top app
Log Management
# View all logs
docker compose -f docker-compose.prod.yml logs -f
# View specific service logs
docker compose -f docker-compose.prod.yml logs -f app
# Tail last 100 lines
docker compose -f docker-compose.prod.yml logs --tail=100 app
Troubleshooting
Common Issues
Container won't start:
# Check logs for errors
docker compose -f docker-compose.prod.yml logs app
# Verify environment variables
docker compose -f docker-compose.prod.yml config
Database connection issues:
# Verify postgres is running
docker compose exec postgres pg_isready
# Check connection from app
docker compose exec app php artisan db:monitor
Permission errors:
# Fix storage permissions
docker compose exec app chmod -R 755 storage bootstrap/cache
docker compose exec app chown -R www-data:www-data storage bootstrap/cache
Next Steps
- Configure PHP Optimization for maximum performance
- Deploy to Kubernetes for scalability
- Set up Autoscaling for handling traffic spikes