Dify Docker Compose Setup Guide
Everything you need to know about Dify's Docker architecture — from what each container does to production-hardening your deployment with custom configurations.
Dify's Docker Architecture
Dify's docker-compose.yaml spins up eight services. Understanding what each does helps you configure, troubleshoot and scale your deployment.
nginx Reverse proxy / web server Routes incoming HTTP requests to the correct internal service (web UI or API). This is the only container that needs to be publicly accessible.
api Dify API server The core Python/Flask backend. Handles all business logic, LLM calls, RAG pipeline execution and REST API endpoints.
worker Celery background worker Processes async tasks: document indexing, dataset imports, long-running LLM chains. Shares code with the API container.
web Next.js frontend The React-based user interface served as a Next.js app. Communicates with the API container.
db PostgreSQL database Stores all persistent data: apps, conversations, datasets metadata, users and API keys.
redis Cache & message broker Caches frequent queries, stores Celery task queue for the worker, and handles rate-limiting data.
weaviate Vector database Stores document embeddings for RAG knowledge bases. The heaviest memory consumer. Can be replaced with pgvector or Qdrant.
sandbox Code execution sandbox Isolated container for running user-defined code nodes in Dify workflows. Runs with restricted permissions.
Total RAM baseline: ~1.5 GB just for idle containers. On a 4GB server, this leaves ~2.5 GB for the OS and actual workloads. For production, 8GB RAM is recommended.
Environment Variables Guide
All Dify configuration lives in dify/docker/.env. Copy from .env.example and customize these key settings:
Security (Required)
# Generate with: openssl rand -base64 42
SECRET_KEY=your-very-long-random-secret-key
# Encryption key for sensitive stored data
# Generate with: openssl rand -hex 16
ENCRYPT_IV=your-16-char-hex-value Database Settings
# PostgreSQL settings (internal Docker network)
DB_USERNAME=postgres
DB_PASSWORD=change-this-strong-password
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify
# Redis settings
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=change-this-redis-password
REDIS_DB=0 URL & CORS Settings
# Your domain (no trailing slash)
CONSOLE_URL=https://your-domain.com
APP_URL=https://your-domain.com
SERVICE_API_URL=https://your-domain.com
# CORS origins (comma-separated)
CONSOLE_CORS_ALLOW_ORIGINS=https://your-domain.com
WEB_API_CORS_ALLOW_ORIGINS=https://your-domain.com File Storage
# Default: local filesystem (stored in ./volumes/app/storage)
STORAGE_TYPE=local
# For S3-compatible storage (recommended for production)
# STORAGE_TYPE=s3
# S3_ENDPOINT=https://s3.amazonaws.com
# S3_BUCKET_NAME=my-dify-bucket
# S3_ACCESS_KEY=your-access-key
# S3_SECRET_KEY=your-secret-key
# S3_REGION=us-east-1 LLM API Keys (optional at setup)
# You can also configure these in the Dify web UI
# These .env settings pre-configure providers on first launch
OPENAI_API_KEY=sk-your-openai-key
ANTHROPIC_API_KEY=sk-ant-your-key
GOOGLE_API_KEY=your-gemini-key
# For Ollama (local LLMs)
# Configure in UI: Settings → Model Provider → Ollama Custom Configurations
Custom Port Mapping
If port 80 is taken, change the host port Dify's Nginx binds to by editing .env:
# Change Nginx container's host port
EXPOSE_NGINX_PORT=8080
EXPOSE_NGINX_SSL_PORT=8443 Disable Weaviate (use pgvector instead)
Weaviate uses ~500MB RAM. On low-memory servers, switch to pgvector (already available in the PostgreSQL container):
# In .env — switch vector store to pgvector
VECTOR_STORE=pgvector
# Then restart without Weaviate
docker compose up -d --scale weaviate=0 Enable GPU Support
To pass through an NVIDIA GPU (for local embedding models), add the GPU runtime to your docker-compose.override.yaml:
services:
api:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu] See the GPU hosting guide for full setup instructions.
Common Commands
docker compose up -d docker compose down docker compose restart api docker compose logs -f api worker docker compose exec api bash docker compose ps docker stats docker compose down --remove-orphans docker compose pull docker compose up -d --build api Troubleshooting
Container keeps restarting / CrashLoopBackOff
Check logs: docker compose logs api. Usually caused by wrong SECRET_KEY format or a missing required environment variable. Ensure SECRET_KEY is at least 32 characters.
Out of memory — containers killed by OOM killer
Add swap space and/or upgrade to a larger server. Run dmesg | grep -i "killed process" to confirm OOM kills. The weaviate container is usually the culprit — consider switching to pgvector.
Database connection errors
Ensure the DB container is healthy before the API starts: docker compose ps db. The API has a depends_on with health check, but on slow servers the DB may not finish initializing in time. Try docker compose restart api.
Permission denied errors on ./volumes
The storage volume directory needs correct permissions. Run: sudo chown -R 1000:1000 ./volumes from the dify/docker directory.
Production Hardening
Before going live, apply these security measures:
1. Change all default passwords
Set strong unique values for DB_PASSWORD, REDIS_PASSWORD, and especially SECRET_KEY. Never use the .env.example defaults in production.
2. Secure your .env file
chmod 600 dify/docker/.env
# Never commit .env to version control 3. Enable automated backups
Add to crontab (crontab -e):
0 3 * * * cd ~/dify/docker && docker compose exec -T db pg_dump -U postgres dify > ~/backups/dify_$(date +\%Y\%m\%d).sql 4. Use S3 for file storage
Switch STORAGE_TYPE=s3 so uploaded documents are stored separately from your server and survive container rebuilds.