KeystoneJS
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: Dockerfile6 container_name: keystone7 restart: unless-stopped8 environment: 9 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}10 ports: 11 - "3000:3000"12 depends_on: 13 - postgres14 networks: 15 - keystone-network1617 postgres: 18 image: postgres:16-alpine19 container_name: keystone-postgres20 environment: 21 POSTGRES_DB: ${DB_NAME}22 POSTGRES_USER: ${DB_USER}23 POSTGRES_PASSWORD: ${DB_PASSWORD}24 volumes: 25 - postgres_data:/var/lib/postgresql/data26 networks: 27 - keystone-network2829volumes: 30 postgres_data: 3132networks: 33 keystone-network: 34 driver: bridge.env Template
.env
1DB_NAME=keystone2DB_USER=keystone3DB_PASSWORD=changemeUsage Notes
- 1Docs: https://keystonejs.com/docs
- 2Requires Dockerfile: npx create-keystone-app creates project
- 3Access admin UI at http://localhost:3000
- 4GraphQL API at /api/graphql, REST possible via extensions
- 5Schema-driven: define content types in TypeScript
- 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 file2cat > docker-compose.yml << 'EOF'3services:4 keystone:5 build:6 context: .7 dockerfile: Dockerfile8 container_name: keystone9 restart: unless-stopped10 environment:11 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}12 ports:13 - "3000:3000"14 depends_on:15 - postgres16 networks:17 - keystone-network1819 postgres:20 image: postgres:16-alpine21 container_name: keystone-postgres22 environment:23 POSTGRES_DB: ${DB_NAME}24 POSTGRES_USER: ${DB_USER}25 POSTGRES_PASSWORD: ${DB_PASSWORD}26 volumes:27 - postgres_data:/var/lib/postgresql/data28 networks:29 - keystone-network3031volumes:32 postgres_data:3334networks:35 keystone-network:36 driver: bridge37EOF3839# 2. Create the .env file40cat > .env << 'EOF'41DB_NAME=keystone42DB_USER=keystone43DB_PASSWORD=changeme44EOF4546# 3. Start the services47docker compose up -d4849# 4. View logs50docker compose logs -fOne-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 | bashTroubleshooting
- 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
Shortcuts: C CopyF FavoriteD Download