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.

Comments