docker.recipes

Directus Headless CMS

intermediate

Directus data platform with PostgreSQL and Redis.

Overview

Directus is a modern, open-source headless CMS and data platform that automatically generates REST and GraphQL APIs from your database schema. Founded in 2004 and completely rebuilt in 2019, Directus acts as a wrapper around SQL databases, providing a powerful admin interface, user management, and API layer without vendor lock-in. Unlike traditional CMSs that force content into predefined structures, Directus works with your existing database or creates new schemas dynamically, making it ideal for developers who need database flexibility with content management convenience. This stack combines Directus with PostgreSQL as the primary database and Redis for caching and session management. PostgreSQL provides ACID compliance, complex querying capabilities, and JSON support that complements Directus's flexible content modeling, while Redis accelerates response times by caching frequently accessed data and managing user sessions. The combination delivers enterprise-grade performance with the ability to handle both structured relational data and flexible document-style content through PostgreSQL's JSONB support. This configuration is perfect for development teams building headless applications, agencies managing multiple client projects, and organizations migrating from legacy CMSs while maintaining database control. The stack scales from prototype to production, supporting complex content relationships, multi-user collaboration, and API-first architectures that power modern web applications, mobile apps, and IoT dashboards.

Key Features

  • Auto-generated REST and GraphQL APIs from PostgreSQL schema changes with real-time updates
  • Advanced content modeling with PostgreSQL's JSONB support for flexible field types and nested data structures
  • Redis-powered caching system that dramatically improves API response times and reduces database load
  • Role-based permissions with granular field-level access control tied to PostgreSQL user management
  • Real-time collaboration features using Redis pub/sub for live content editing and user presence indicators
  • PostgreSQL full-text search integration with ranking and highlighting for advanced content discovery
  • File asset management with automatic image transformations and PostgreSQL metadata indexing
  • Webhook system for triggering external integrations when content changes in PostgreSQL tables

Common Use Cases

  • 1Headless e-commerce platforms requiring complex product catalogs with PostgreSQL's advanced querying for inventory management
  • 2Multi-tenant SaaS applications where each client needs isolated content management with shared infrastructure
  • 3News and publishing platforms leveraging PostgreSQL's full-text search and Redis caching for high-traffic article delivery
  • 4Mobile app backends requiring real-time content updates through Directus APIs with Redis session management
  • 5Digital asset management systems for marketing teams with PostgreSQL's robust file metadata indexing
  • 6IoT data dashboards where Directus provides user-friendly interfaces for PostgreSQL time-series data visualization
  • 7Agency portfolio sites managing multiple client projects with Directus's flexible content modeling and user permissions

Prerequisites

  • Docker Engine 20.10+ and Docker Compose V2 for container orchestration support
  • Minimum 2GB RAM (PostgreSQL needs 1GB+, Redis 512MB+, Directus 512MB+) for stable operation
  • Port 8055 available for Directus admin interface and API endpoints
  • Basic understanding of PostgreSQL schema design for effective content modeling in Directus
  • Generated secure random values for KEY and SECRET environment variables (minimum 32 characters each)
  • Valid email configuration if using Directus email features for user invitations and password resets

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 postgres:
3 image: postgres:16-alpine
4 container_name: directus-postgres
5 restart: unless-stopped
6 environment:
7 POSTGRES_USER: ${POSTGRES_USER:-directus}
8 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}
9 POSTGRES_DB: ${POSTGRES_DB:-directus}
10 volumes:
11 - postgres_data:/var/lib/postgresql/data
12 networks:
13 - directus-network
14
15 redis:
16 image: redis:alpine
17 container_name: directus-redis
18 restart: unless-stopped
19 volumes:
20 - redis_data:/data
21 networks:
22 - directus-network
23
24 directus:
25 image: directus/directus:latest
26 container_name: directus
27 restart: unless-stopped
28 ports:
29 - "${DIRECTUS_PORT:-8055}:8055"
30 environment:
31 KEY: ${KEY:-replace-with-random-value}
32 SECRET: ${SECRET:-replace-with-random-value}
33 DB_CLIENT: pg
34 DB_HOST: postgres
35 DB_PORT: 5432
36 DB_DATABASE: ${POSTGRES_DB:-directus}
37 DB_USER: ${POSTGRES_USER:-directus}
38 DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}
39 CACHE_ENABLED: "true"
40 CACHE_STORE: redis
41 REDIS: redis://redis:6379
42 ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
43 ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}
44 volumes:
45 - directus_uploads:/directus/uploads
46 depends_on:
47 - postgres
48 - redis
49 networks:
50 - directus-network
51
52volumes:
53 postgres_data:
54 redis_data:
55 directus_uploads:
56
57networks:
58 directus-network:
59 driver: bridge

.env Template

.env
1# Directus
2DIRECTUS_PORT=8055
3KEY=your-random-key-here
4SECRET=your-random-secret-here
5POSTGRES_USER=directus
6POSTGRES_PASSWORD=directus
7POSTGRES_DB=directus
8ADMIN_EMAIL=admin@example.com
9ADMIN_PASSWORD=admin123

Usage Notes

  1. 1Directus at http://localhost:8055
  2. 2Login with admin credentials
  3. 3Generate random KEY and SECRET
  4. 4Access API at /items/{collection}

Individual Services(3 services)

Copy individual services to mix and match with your existing compose files.

postgres
postgres:
  image: postgres:16-alpine
  container_name: directus-postgres
  restart: unless-stopped
  environment:
    POSTGRES_USER: ${POSTGRES_USER:-directus}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}
    POSTGRES_DB: ${POSTGRES_DB:-directus}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  networks:
    - directus-network
redis
redis:
  image: redis:alpine
  container_name: directus-redis
  restart: unless-stopped
  volumes:
    - redis_data:/data
  networks:
    - directus-network
directus
directus:
  image: directus/directus:latest
  container_name: directus
  restart: unless-stopped
  ports:
    - ${DIRECTUS_PORT:-8055}:8055
  environment:
    KEY: ${KEY:-replace-with-random-value}
    SECRET: ${SECRET:-replace-with-random-value}
    DB_CLIENT: pg
    DB_HOST: postgres
    DB_PORT: 5432
    DB_DATABASE: ${POSTGRES_DB:-directus}
    DB_USER: ${POSTGRES_USER:-directus}
    DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}
    CACHE_ENABLED: "true"
    CACHE_STORE: redis
    REDIS: redis://redis:6379
    ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
    ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}
  volumes:
    - directus_uploads:/directus/uploads
  depends_on:
    - postgres
    - redis
  networks:
    - directus-network

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 postgres:
5 image: postgres:16-alpine
6 container_name: directus-postgres
7 restart: unless-stopped
8 environment:
9 POSTGRES_USER: ${POSTGRES_USER:-directus}
10 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}
11 POSTGRES_DB: ${POSTGRES_DB:-directus}
12 volumes:
13 - postgres_data:/var/lib/postgresql/data
14 networks:
15 - directus-network
16
17 redis:
18 image: redis:alpine
19 container_name: directus-redis
20 restart: unless-stopped
21 volumes:
22 - redis_data:/data
23 networks:
24 - directus-network
25
26 directus:
27 image: directus/directus:latest
28 container_name: directus
29 restart: unless-stopped
30 ports:
31 - "${DIRECTUS_PORT:-8055}:8055"
32 environment:
33 KEY: ${KEY:-replace-with-random-value}
34 SECRET: ${SECRET:-replace-with-random-value}
35 DB_CLIENT: pg
36 DB_HOST: postgres
37 DB_PORT: 5432
38 DB_DATABASE: ${POSTGRES_DB:-directus}
39 DB_USER: ${POSTGRES_USER:-directus}
40 DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}
41 CACHE_ENABLED: "true"
42 CACHE_STORE: redis
43 REDIS: redis://redis:6379
44 ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
45 ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}
46 volumes:
47 - directus_uploads:/directus/uploads
48 depends_on:
49 - postgres
50 - redis
51 networks:
52 - directus-network
53
54volumes:
55 postgres_data:
56 redis_data:
57 directus_uploads:
58
59networks:
60 directus-network:
61 driver: bridge
62EOF
63
64# 2. Create the .env file
65cat > .env << 'EOF'
66# Directus
67DIRECTUS_PORT=8055
68KEY=your-random-key-here
69SECRET=your-random-secret-here
70POSTGRES_USER=directus
71POSTGRES_PASSWORD=directus
72POSTGRES_DB=directus
73ADMIN_EMAIL=admin@example.com
74ADMIN_PASSWORD=admin123
75EOF
76
77# 3. Start the services
78docker compose up -d
79
80# 4. View logs
81docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/directus-cms/run | bash

Troubleshooting

  • Directus shows 'Database connection failed': Check PostgreSQL container logs and verify POSTGRES_PASSWORD matches DB_PASSWORD in environment variables
  • API responses are slow despite Redis setup: Verify CACHE_ENABLED is 'true' and check Redis container connectivity with docker exec directus-redis redis-cli ping
  • Admin login fails with 'Invalid credentials': Reset admin password by setting new ADMIN_PASSWORD and restarting Directus container to recreate admin user
  • File uploads return 500 errors: Ensure directus_uploads volume has proper write permissions and check available disk space on Docker host
  • PostgreSQL container fails to start with 'data directory not empty': Remove postgres_data volume or check for conflicting PostgreSQL instances on port 5432
  • Directus shows 'Invalid key/secret' errors: Generate cryptographically secure random strings for KEY and SECRET environment variables using openssl rand -hex 32

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space