docker.recipes

KeystoneJS

intermediate

Headless CMS and web application framework built on Node.js.

Overview

KeystoneJS is a modern headless CMS and GraphQL-first application framework built on Node.js that bridges the gap between traditional content management and modern development practices. Originally created by Thinkmill, KeystoneJS provides a developer-friendly approach to building content-driven applications with a powerful admin interface, automatic GraphQL API generation, and TypeScript-first schema definition. Its architecture emphasizes flexibility and extensibility while maintaining the ease of use that content creators expect from traditional CMS platforms. This Docker configuration pairs KeystoneJS with PostgreSQL to create a robust content management platform that leverages PostgreSQL's advanced relational capabilities, ACID compliance, and superior JSON support for handling KeystoneJS's flexible content schemas. PostgreSQL's mature transaction system ensures data integrity for content operations, while its excellent JSON/JSONB support complements KeystoneJS's dynamic field types and relationship structures. The combination provides both the relational reliability needed for complex content relationships and the flexibility required for modern headless CMS architectures. This stack is ideal for development teams building content-heavy applications, marketing sites, or multi-tenant platforms where GraphQL API access, robust admin interfaces, and reliable data persistence are essential. Organizations migrating from traditional CMS platforms to headless architectures will find KeystoneJS's familiar admin UI reduces the learning curve for content creators, while developers benefit from TypeScript-driven schema definitions and PostgreSQL's proven scalability for growing content repositories.

Key Features

  • Auto-generated GraphQL API with real-time schema introspection based on TypeScript content models
  • Built-in Admin UI with customizable field types, file uploads, and relationship management
  • PostgreSQL JSONB field support for flexible content structures alongside relational data
  • Advanced access control with field-level permissions and authentication hooks
  • Content versioning and audit trails leveraging PostgreSQL's transaction capabilities
  • Real-time subscriptions through GraphQL with PostgreSQL LISTEN/NOTIFY support
  • Multi-tenancy support using PostgreSQL schemas and row-level security
  • Extensible field types including rich text, images, and custom React components

Common Use Cases

  • 1Marketing websites requiring frequent content updates with non-technical editor access
  • 2E-commerce platforms needing complex product catalogs with variant relationships
  • 3Multi-brand content management with shared asset libraries and cross-publishing
  • 4Developer portfolios and agency sites with project showcases and blog functionality
  • 5Enterprise knowledge bases with role-based content access and approval workflows
  • 6SaaS application backends requiring user-generated content and file management
  • 7News and media sites with article scheduling, categorization, and author management

Prerequisites

  • Minimum 1GB RAM (2GB recommended for PostgreSQL and KeystoneJS with admin UI)
  • Docker and Docker Compose with BuildKit support for multi-stage builds
  • Node.js development knowledge for KeystoneJS schema customization
  • Port 3000 available for KeystoneJS admin interface and GraphQL endpoint
  • Basic understanding of GraphQL for API integration and querying
  • PostgreSQL knowledge for database maintenance and performance tuning

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 keystone:
3 build:
4 context: .
5 dockerfile: Dockerfile
6 container_name: keystone
7 restart: unless-stopped
8 environment:
9 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
10 ports:
11 - "3000:3000"
12 depends_on:
13 - postgres
14 networks:
15 - keystone-network
16
17 postgres:
18 image: postgres:16-alpine
19 container_name: keystone-postgres
20 environment:
21 POSTGRES_DB: ${DB_NAME}
22 POSTGRES_USER: ${DB_USER}
23 POSTGRES_PASSWORD: ${DB_PASSWORD}
24 volumes:
25 - postgres_data:/var/lib/postgresql/data
26 networks:
27 - keystone-network
28
29volumes:
30 postgres_data:
31
32networks:
33 keystone-network:
34 driver: bridge

.env Template

.env
1DB_NAME=keystone
2DB_USER=keystone
3DB_PASSWORD=changeme

Usage Notes

  1. 1Docs: https://keystonejs.com/docs
  2. 2Requires Dockerfile: npx create-keystone-app creates project
  3. 3Access admin UI at http://localhost:3000
  4. 4GraphQL API at /api/graphql, REST possible via extensions
  5. 5Schema-driven: define content types in TypeScript
  6. 6Document and relationship fields, access control, hooks

Individual Services(2 services)

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

keystone
keystone:
  build:
    context: .
    dockerfile: Dockerfile
  container_name: keystone
  restart: unless-stopped
  environment:
    DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
  ports:
    - "3000:3000"
  depends_on:
    - postgres
  networks:
    - keystone-network
postgres
postgres:
  image: postgres:16-alpine
  container_name: keystone-postgres
  environment:
    POSTGRES_DB: ${DB_NAME}
    POSTGRES_USER: ${DB_USER}
    POSTGRES_PASSWORD: ${DB_PASSWORD}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  networks:
    - keystone-network

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 keystone:
5 build:
6 context: .
7 dockerfile: Dockerfile
8 container_name: keystone
9 restart: unless-stopped
10 environment:
11 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
12 ports:
13 - "3000:3000"
14 depends_on:
15 - postgres
16 networks:
17 - keystone-network
18
19 postgres:
20 image: postgres:16-alpine
21 container_name: keystone-postgres
22 environment:
23 POSTGRES_DB: ${DB_NAME}
24 POSTGRES_USER: ${DB_USER}
25 POSTGRES_PASSWORD: ${DB_PASSWORD}
26 volumes:
27 - postgres_data:/var/lib/postgresql/data
28 networks:
29 - keystone-network
30
31volumes:
32 postgres_data:
33
34networks:
35 keystone-network:
36 driver: bridge
37EOF
38
39# 2. Create the .env file
40cat > .env << 'EOF'
41DB_NAME=keystone
42DB_USER=keystone
43DB_PASSWORD=changeme
44EOF
45
46# 3. Start the services
47docker compose up -d
48
49# 4. View logs
50docker 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/keystone-cms/run | bash

Troubleshooting

  • Database connection refused: Ensure PostgreSQL container is fully initialized before KeystoneJS starts by adding healthcheck or longer depends_on delay
  • KeystoneJS schema migration errors: Check DATABASE_URL format and PostgreSQL user permissions for CREATE/ALTER operations
  • Admin UI shows 'Cannot read properties of undefined': Verify all required environment variables are set and PostgreSQL connection is stable
  • GraphQL introspection disabled in production: Set NODE_ENV appropriately or enable introspection explicitly in keystone.ts config
  • File upload failures: Ensure proper volume mounts for KeystoneJS uploads directory and sufficient disk space
  • PostgreSQL connection pool exhausted: Tune PostgreSQL max_connections setting and KeystoneJS database pool configuration

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