Strapi Headless CMS
Open-source headless CMS with REST and GraphQL APIs.
Overview
Strapi is an open-source headless CMS that has gained significant traction since its launch in 2015, becoming one of the most popular content management solutions for modern web applications. Unlike traditional CMSs, Strapi provides a powerful admin interface for content creators while delivering content through REST and GraphQL APIs, making it ideal for JAMstack applications, mobile apps, and multi-channel content distribution. Its JavaScript-based architecture offers extensive customization capabilities through plugins and custom code.
This stack combines Strapi with PostgreSQL to create a robust content management platform that can handle complex relational data requirements. PostgreSQL's ACID compliance and advanced querying capabilities complement Strapi's flexible content modeling system, enabling sophisticated content relationships and data integrity. The combination provides superior performance for content-heavy applications compared to simpler database solutions, while maintaining the developer-friendly experience Strapi is known for.
This configuration is particularly valuable for development teams building content-driven applications that require both editorial workflows and developer flexibility. Startups launching content platforms, agencies managing multiple client sites, and enterprises needing headless CMS capabilities will benefit from this stack's balance of ease-of-use and technical power. The PostgreSQL backend ensures the system can scale from prototype to production while supporting complex content relationships and custom business logic.
Key Features
- Visual Content-Type Builder for creating custom data models without code
- Dual API support with auto-generated REST endpoints and optional GraphQL
- Role-based access control with granular permissions for team collaboration
- Internationalization (i18n) support for multi-language content management
- Media Library with drag-and-drop asset management and automatic optimization
- Plugin ecosystem including email providers, upload providers, and custom extensions
- PostgreSQL's JSONB support for flexible schema-less fields within structured content
- Advanced PostgreSQL features like full-text search and geospatial data with PostGIS compatibility
Common Use Cases
- 1JAMstack websites using Next.js, Gatsby, or Nuxt.js for content delivery
- 2Mobile application backends requiring structured content and user management
- 3Multi-brand content platforms serving different websites from a single CMS
- 4E-commerce product catalogs with complex relationships and inventory management
- 5News and publishing platforms requiring editorial workflows and content scheduling
- 6Corporate websites with multiple content types and approval processes
- 7API-first applications serving content to multiple frontend frameworks simultaneously
Prerequisites
- Minimum 1.5GB RAM (512MB for Strapi + 256MB for PostgreSQL + overhead)
- Docker and Docker Compose installed with support for named volumes
- Available ports 1337 (Strapi admin/API) and ensure no conflicts
- Basic understanding of headless CMS concepts and API consumption
- Familiarity with environment variable configuration for database credentials
- Knowledge of content modeling principles for effective schema design
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 strapi: 3 image: strapi/strapi:latest4 container_name: strapi5 restart: unless-stopped6 environment: 7 DATABASE_CLIENT: postgres8 DATABASE_HOST: postgres9 DATABASE_PORT: 543210 DATABASE_NAME: ${DATABASE_NAME}11 DATABASE_USERNAME: ${DATABASE_USERNAME}12 DATABASE_PASSWORD: ${DATABASE_PASSWORD}13 volumes: 14 - strapi_data:/srv/app15 ports: 16 - "1337:1337"17 depends_on: 18 - postgres19 networks: 20 - strapi-network2122 postgres: 23 image: postgres:16-alpine24 container_name: strapi-postgres25 environment: 26 POSTGRES_DB: ${DATABASE_NAME}27 POSTGRES_USER: ${DATABASE_USERNAME}28 POSTGRES_PASSWORD: ${DATABASE_PASSWORD}29 volumes: 30 - postgres_data:/var/lib/postgresql/data31 networks: 32 - strapi-network3334volumes: 35 strapi_data: 36 postgres_data: 3738networks: 39 strapi-network: 40 driver: bridge.env Template
.env
1DATABASE_NAME=strapi2DATABASE_USERNAME=strapi3DATABASE_PASSWORD=changemeUsage Notes
- 1Docs: https://docs.strapi.io/
- 2Access admin at http://localhost:1337/admin - create first admin user
- 3Content-type Builder: define schemas visually
- 4REST API at /api/[content-type], GraphQL at /graphql (install plugin)
- 5Media Library for asset management
- 6For v4: use npx create-strapi-app, not the Docker image directly
Individual Services(2 services)
Copy individual services to mix and match with your existing compose files.
strapi
strapi:
image: strapi/strapi:latest
container_name: strapi
restart: unless-stopped
environment:
DATABASE_CLIENT: postgres
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- strapi_data:/srv/app
ports:
- "1337:1337"
depends_on:
- postgres
networks:
- strapi-network
postgres
postgres:
image: postgres:16-alpine
container_name: strapi-postgres
environment:
POSTGRES_DB: ${DATABASE_NAME}
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- strapi-network
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 strapi:5 image: strapi/strapi:latest6 container_name: strapi7 restart: unless-stopped8 environment:9 DATABASE_CLIENT: postgres10 DATABASE_HOST: postgres11 DATABASE_PORT: 543212 DATABASE_NAME: ${DATABASE_NAME}13 DATABASE_USERNAME: ${DATABASE_USERNAME}14 DATABASE_PASSWORD: ${DATABASE_PASSWORD}15 volumes:16 - strapi_data:/srv/app17 ports:18 - "1337:1337"19 depends_on:20 - postgres21 networks:22 - strapi-network2324 postgres:25 image: postgres:16-alpine26 container_name: strapi-postgres27 environment:28 POSTGRES_DB: ${DATABASE_NAME}29 POSTGRES_USER: ${DATABASE_USERNAME}30 POSTGRES_PASSWORD: ${DATABASE_PASSWORD}31 volumes:32 - postgres_data:/var/lib/postgresql/data33 networks:34 - strapi-network3536volumes:37 strapi_data:38 postgres_data:3940networks:41 strapi-network:42 driver: bridge43EOF4445# 2. Create the .env file46cat > .env << 'EOF'47DATABASE_NAME=strapi48DATABASE_USERNAME=strapi49DATABASE_PASSWORD=changeme50EOF5152# 3. Start the services53docker compose up -d5455# 4. View logs56docker 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/strapi-cms/run | bashTroubleshooting
- Strapi container exits with database connection error: Ensure PostgreSQL container is fully started before Strapi - add healthcheck or increase depends_on wait time
- Admin panel shows 'Application not found' after restart: Strapi data volume permissions issue - check that volume mount has correct ownership (1000:1000)
- API returns 404 for content endpoints: Content types need to be published in admin panel and API permissions enabled for public role
- GraphQL playground not available at /graphql: Install GraphQL plugin through Strapi admin panel marketplace
- Slow query performance with large datasets: Enable PostgreSQL query logging and add appropriate indexes through Strapi's database layer
- Media uploads failing with file size errors: Configure Strapi's file upload limits in server configuration and ensure adequate disk space
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