How to Self-Host Statamic with Docker Compose

What Is Statamic?

Statamic is a flat-file CMS built on Laravel that stores content as YAML and Markdown files instead of a database. This makes your entire site — content, configuration, and structure — version-controllable with Git. It features a polished Vue.js control panel with 40+ fieldtypes, live preview, and a flexible content modeling system. Statamic can also run in headless mode with REST API and GraphQL endpoints (Pro feature). Official site.

Licensing note: Statamic Core is free (limited to 1 admin user, 1 form). Statamic Pro costs $275/site (one year of updates, $65/year renewal) and adds unlimited users, REST API, GraphQL, multi-site, revisions, and Git integration. The source code is visible on GitHub but uses a commercial license, not an open-source license.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 500 MB of free disk space
  • 512 MB of RAM minimum (1 GB recommended)
  • PHP 8.2+ and Composer (for initial project creation)
  • A domain name (optional, for remote access)

Docker Compose Configuration

First, create a new Statamic project:

composer create-project statamic/statamic ~/statamic-site
cd ~/statamic-site

Create a Dockerfile in the project root:

FROM php:8.3-apache

RUN apt-get update && apt-get install -y \
    libpng-dev libjpeg-dev libfreetype6-dev \
    libzip-dev libxml2-dev unzip git \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd zip mbstring opcache exif bcmath \
    && a2enmod rewrite \
    && rm -rf /var/lib/apt/lists/*

# Configure Apache document root
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' \
    /etc/apache2/sites-available/*.conf \
    /etc/apache2/apache2.conf

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html
COPY . .

RUN composer install --no-dev --optimize-autoloader \
    && chown -R www-data:www-data /var/www/html/storage \
    && chown -R www-data:www-data /var/www/html/content \
    && chown -R www-data:www-data /var/www/html/public

EXPOSE 80

Create docker-compose.yml:

services:
  statamic:
    build: .
    container_name: statamic
    ports:
      - "8080:80"
    volumes:
      - ./content:/var/www/html/content
      - ./users:/var/www/html/users
      - statamic_storage:/var/www/html/storage
      - ./public/assets:/var/www/html/public/assets
    environment:
      - APP_ENV=production
      - APP_DEBUG=false
      - APP_URL=http://localhost:8080
      - APP_KEY=base64:generate-this-with-artisan
      - STATAMIC_STACHE_WATCHER=true
      - STATAMIC_STATIC_CACHING_STRATEGY=null
    restart: unless-stopped

volumes:
  statamic_storage:

Generate an application key and create the first user:

docker compose build
docker compose up -d
docker compose exec statamic php artisan key:generate
docker compose exec statamic php please make:user

Initial Setup

  1. Run docker compose exec statamic php please make:user to create your admin account
  2. Open http://your-server-ip:8080/cp to access the control panel
  3. Log in with the credentials you just created
  4. Start creating collections, pages, and entries through the control panel
  5. Content is saved as YAML/Markdown files in the content/ directory

Configuration

SettingEnvironment VariableDescription
Site URLAPP_URLFull URL including protocol
Debug modeAPP_DEBUGSet false in production
File watcherSTATAMIC_STACHE_WATCHERAuto-detect content file changes (true/false)
Static cachingSTATAMIC_STATIC_CACHING_STRATEGYnull, half, or full for static page caching
License keySTATAMIC_LICENSE_KEYRequired for Pro features in production

Content Storage

Statamic stores all content as flat files:

DirectoryContents
content/collections/Collection entries (blog posts, pages, etc.)
content/globals/Global variable sets
content/navigation/Navigation menus
content/taxonomies/Taxonomy terms
users/User accounts (YAML files)
resources/blueprints/Content type definitions
resources/fieldsets/Reusable field groups

Because everything is in flat files, you can edit content directly in your text editor, commit changes to Git, and deploy via CI/CD — no database migrations needed.

Optional Database Backend

For larger sites or when you need SQL queries, Statamic supports database storage via Laravel’s Eloquent driver:

# In docker-compose.yml, add a database service and set:
# DB_CONNECTION=mysql
# DB_HOST=statamic-db
# ...standard Laravel database env vars

Reverse Proxy

Example Nginx Proxy Manager configuration:

  • Scheme: http
  • Forward Hostname: statamic
  • Forward Port: 80

See Reverse Proxy Setup for full configuration guides.

Backup

The flat-file architecture makes backup straightforward:

  • content/ — all site content (YAML/Markdown files). Commit to Git for version history.
  • users/ — user accounts
  • public/assets/ — uploaded media files
  • statamic_storage volume — cache, logs, sessions

With Git-based content, your entire site is backed up every time you commit. For media files, use a separate backup strategy.

See Backup Strategy for automated approaches.

Troubleshooting

Control Panel Returns 404

Symptom: Visiting /cp returns a 404 error. Fix: Ensure Apache’s mod_rewrite is enabled and the document root points to /var/www/html/public (not /var/www/html). The Dockerfile above handles this, but verify with docker compose exec statamic apache2ctl -M | grep rewrite.

Content Changes Not Reflecting

Symptom: Edits to YAML files don’t appear on the site. Fix: Set STATAMIC_STACHE_WATCHER=true to enable file watching. If changes still don’t appear, clear the Stache cache: docker compose exec statamic php artisan stache:clear.

Permission Errors When Saving Content

Symptom: Control panel shows “Permission denied” when saving entries. Fix: Ensure the web server user owns the content and storage directories: docker compose exec statamic chown -R www-data:www-data content storage users.

Asset Uploads Failing

Symptom: Uploading images or files through the control panel fails. Fix: Check that public/assets/ is writable and the volume mount is correct. Verify the asset container is configured in config/statamic/assets.php.

Resource Requirements

  • RAM: ~100 MB idle, ~300 MB under load
  • CPU: Low — flat-file reads are fast, no database queries
  • Disk: ~50 MB for application, plus content and media uploads

Verdict

Statamic is the best flat-file CMS available if you value Git-based content workflows. The control panel is polished, content modeling is flexible, and the Laravel foundation means you can extend it with any Laravel package. The flat-file approach means exceptional performance and dead-simple backups. The main drawback is cost — Pro features ($275/site) are needed for multi-user setups, APIs, and revisions. For a free, database-backed CMS with similar quality, Ghost is the strongest alternative. For a fully open-source flat-file option, Grav is worth considering, though its control panel is less polished.

Frequently Asked Questions

Is Statamic free to use?

Statamic Core is free but limited to 1 admin user and 1 form. Statamic Pro ($275/site with $65/year renewal) adds unlimited users, REST API, GraphQL, multi-site support, revisions, and Git integration. The source code is publicly visible on GitHub but uses a commercial license, not an open-source license.

How does Statamic compare to WordPress?

Statamic is a flat-file CMS that stores content as YAML/Markdown files — no database needed, everything is Git-versionable. WordPress uses MySQL and has a massive plugin ecosystem. Statamic is better for developer-friendly workflows and performance; WordPress is better for non-technical users and extensive third-party integrations.

Can Statamic work as a headless CMS?

Yes, with the Pro license. Statamic Pro includes REST API and GraphQL endpoints, allowing you to use it as a headless CMS that serves content to a separate frontend built with React, Vue, Next.js, or any other framework.

Does Statamic need a database?

No. By default, Statamic stores all content as flat YAML and Markdown files. For larger sites needing SQL queries, it optionally supports database storage via Laravel’s Eloquent driver (MySQL, PostgreSQL, SQLite). Most sites work well with flat files.

Can I use Statamic with Git-based deployments?

Yes — this is one of Statamic’s core strengths. Since content is stored as flat files, you can commit everything to Git, review changes in pull requests, and deploy via CI/CD pipelines. The Pro license adds a built-in Git integration that auto-commits content changes from the control panel.

How does Statamic compare to Ghost?

Statamic is a general-purpose CMS with flexible content modeling (40+ fieldtypes, custom collections, taxonomies). Ghost is focused on publishing and newsletters with a simpler content model. Ghost is free and open-source; Statamic Pro is paid. Choose Statamic for complex content structures, Ghost for straightforward blogging and newsletter publishing.

Comments