docker.recipes

Strapi Headless CMS

intermediate

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:latest
4 container_name: strapi
5 restart: unless-stopped
6 environment:
7 DATABASE_CLIENT: postgres
8 DATABASE_HOST: postgres
9 DATABASE_PORT: 5432
10 DATABASE_NAME: ${DATABASE_NAME}
11 DATABASE_USERNAME: ${DATABASE_USERNAME}
12 DATABASE_PASSWORD: ${DATABASE_PASSWORD}
13 volumes:
14 - strapi_data:/srv/app
15 ports:
16 - "1337:1337"
17 depends_on:
18 - postgres
19 networks:
20 - strapi-network
21
22 postgres:
23 image: postgres:16-alpine
24 container_name: strapi-postgres
25 environment:
26 POSTGRES_DB: ${DATABASE_NAME}
27 POSTGRES_USER: ${DATABASE_USERNAME}
28 POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
29 volumes:
30 - postgres_data:/var/lib/postgresql/data
31 networks:
32 - strapi-network
33
34volumes:
35 strapi_data:
36 postgres_data:
37
38networks:
39 strapi-network:
40 driver: bridge

.env Template

.env
1DATABASE_NAME=strapi
2DATABASE_USERNAME=strapi
3DATABASE_PASSWORD=changeme

Usage Notes

  1. 1Docs: https://docs.strapi.io/
  2. 2Access admin at http://localhost:1337/admin - create first admin user
  3. 3Content-type Builder: define schemas visually
  4. 4REST API at /api/[content-type], GraphQL at /graphql (install plugin)
  5. 5Media Library for asset management
  6. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 strapi:
5 image: strapi/strapi:latest
6 container_name: strapi
7 restart: unless-stopped
8 environment:
9 DATABASE_CLIENT: postgres
10 DATABASE_HOST: postgres
11 DATABASE_PORT: 5432
12 DATABASE_NAME: ${DATABASE_NAME}
13 DATABASE_USERNAME: ${DATABASE_USERNAME}
14 DATABASE_PASSWORD: ${DATABASE_PASSWORD}
15 volumes:
16 - strapi_data:/srv/app
17 ports:
18 - "1337:1337"
19 depends_on:
20 - postgres
21 networks:
22 - strapi-network
23
24 postgres:
25 image: postgres:16-alpine
26 container_name: strapi-postgres
27 environment:
28 POSTGRES_DB: ${DATABASE_NAME}
29 POSTGRES_USER: ${DATABASE_USERNAME}
30 POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
31 volumes:
32 - postgres_data:/var/lib/postgresql/data
33 networks:
34 - strapi-network
35
36volumes:
37 strapi_data:
38 postgres_data:
39
40networks:
41 strapi-network:
42 driver: bridge
43EOF
44
45# 2. Create the .env file
46cat > .env << 'EOF'
47DATABASE_NAME=strapi
48DATABASE_USERNAME=strapi
49DATABASE_PASSWORD=changeme
50EOF
51
52# 3. Start the services
53docker compose up -d
54
55# 4. View logs
56docker 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/strapi-cms/run | bash

Troubleshooting

  • 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