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
- Run
docker compose exec statamic php please make:userto create your admin account - Open
http://your-server-ip:8080/cpto access the control panel - Log in with the credentials you just created
- Start creating collections, pages, and entries through the control panel
- Content is saved as YAML/Markdown files in the
content/directory
Configuration
| Setting | Environment Variable | Description |
|---|---|---|
| Site URL | APP_URL | Full URL including protocol |
| Debug mode | APP_DEBUG | Set false in production |
| File watcher | STATAMIC_STACHE_WATCHER | Auto-detect content file changes (true/false) |
| Static caching | STATAMIC_STATIC_CACHING_STRATEGY | null, half, or full for static page caching |
| License key | STATAMIC_LICENSE_KEY | Required for Pro features in production |
Content Storage
Statamic stores all content as flat files:
| Directory | Contents |
|---|---|
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 accountspublic/assets/— uploaded media filesstatamic_storagevolume — 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.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments