Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Last active July 26, 2024 01:21
Show Gist options
  • Save mikeschinkel/cc5bfdff3bc3d35794f0551460965391 to your computer and use it in GitHub Desktop.
Save mikeschinkel/cc5bfdff3bc3d35794f0551460965391 to your computer and use it in GitHub Desktop.
Statamic — Dockerfile and compose; FILES SHOWN DO NOT WORK, see the _README.md for the working solution.

If you happen onto this Gist looking for a solution to creating your own Dockerfile for Statamic, here are some related links that provide background and the ultimate working solution:


  1. Discussion on Statamic's Github about problems installing in a Docker build.
  2. Comment outlining root-cause and fix needed

  1. Docs page added about missing control panel assets
  2. Doc page updated for How to install on Linux (see the "Hot Top")

  1. The Dockerfile for Statamic that ended up working
  2. Files COPYed by Docker to the container during build
  3. The base Dockerfile with PHP 8.3.9
  4. Repo that provides context for this Dockerfile

IMPORTANT: The solution linked above assumes that the Statmic container is run in an infrastructure that supplies and fully handles the SSL/TLS certificate and thus HTTPS security. The solution configures Statmic to serve HTTPS URLs, but other than that just assumes that the host is handling the SSL/TLS certificates.

version: '3.8'
networks:
shared_network:
name: shared
external: true
services:
statamic:
image: statamic:latest
networks:
- shared_network
ports:
- 8787:80
restart: unless-stopped
environment:
LEGO_CA_CERTIFICATES: "/etc/step/certs/root_ca.crt"
LEGO_CA_SERVER_NAME: "step-ca.local"
labels:
- "traefik.enable=true"
- "traefik.http.routers.statamic.rule=Host(`statamic.local`)"
- "traefik.http.routers.statamic.service=statamic@docker"
- "traefik.http.routers.statamic.entrypoints=websecure,web"
- "traefik.http.routers.statamic.tls=true"
- "traefik.http.routers.statamic.tls.certresolver=default"
- "traefik.http.routers.statamic.tls.domains[0].main=statamic.local"
- "traefik.http.services.statamic.loadbalancer.server.port=80"
# Port 80 above matches internal port, i.e. <external>:<internal> e.g. 8888:80
volumes:
# Store the Statamic source code on the VM
- statamic-root:/var/www/html
# Requires configuration
# On macOS: Download https://step-ca.local:9000/roots.pem then `step certificate install ~/Downloads/roots.pem`
# So Traefik can access Step CA's root cert (read-only)
- /etc/step:/etc/step:ro
# Use the host's SLL certificate store
- /etc/ssl/certs:/etc/ssl/certs
volumes:
statamic-root:
# Use an official PHP image with FPM
FROM php:8.3-fpm
LABEL authors="gearbox.works"
ENV LARAVEL_STORAGE_PATH=/var/statamic/storage
# PHP Extension Installer
COPY --from=mlocati/php-extension-installer \
/usr/bin/install-php-extensions \
/usr/local/bin/
# Install necessary PHP extensions and tools
RUN apt-get update && apt-get install -y \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libzip-dev \
unzip \
nginx \
supervisor \
git \
curl \
jq \
nano \
less \
iputils-ping \
&& install-php-extensions gd zip fileinfo mbstring exif \
&& cd /usr/local/etc/php \
&& cp php.ini-development php.ini \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& echo ========================= \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& touch /var/log/xdebug.log \
&& chmod -R 755 /var/log/xdebug.log \
&& chown -R www-data:www-data /var/log/xdebug.log \
&& echo ========================= \
&& mkdir -p /var/log/php \
&& touch /var/log/php/errors.log \
&& chmod -R 755 /var/log/php \
&& chown -R www-data:www-data /var/log/php \
&& printf "\n\
display_errors = On\n\
display_startup_errors = On\n\
error_reporting = E_ALL\n\
log_errors = On\n\
error_log = /var/log/php/errors.log\n\
" > /usr/local/etc/php/conf.d/php-errors.ini \
&& echo ========================= \
&& printf "\n\
xdebug.mode=debug\n\
xdebug.client_port=9003\n\
xdebug.start_with_request=yes\n\
xdebug.log=/var/log/xdebug.log\n\
xdebug.idekey=PHPSTORM\n\
xdebug.discover_client_host=true\n\
xdebug.client_discovery_header=HTTP_X_REAL_IP\n\
" echo \
>> conf.d/docker-php-ext-xdebug.ini
# Create writable storage directories
# Symlink the storage directory
# Ensure permissions are correct
# See https://stackoverflow.com/a/39179261/102699
RUN mkdir -p /var/statamic/build \
&& mkdir -p /var/statamic/storage/framework/sessions \
&& mkdir -p /var/statamic/storage/framework/views \
&& mkdir -p /var/statamic/storage/framework/cache/data \
&& mkdir -p /var/statamic/storage/logs \
&& mkdir -p /var/statamic/storage/statamic/stache-locks \
&& chown -R www-data:www-data /var/statamic \
&& chmod -R 775 /var/statamic/storage
# Install PHP Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set the working directory
WORKDIR /var
# Install Statamic
RUN composer create-project --prefer-dist statamic/statamic statamic.local
COPY ./files/statamic/ /
RUN chmod +x /move-files.sh
EXPOSE 80
WORKDIR /var/www/html
# Start Supervisor to manage Nginx and PHP-FPM
CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
server {
listen 80;
server_name statamic.local;
root /var/www/html/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
set $try_location @static;
if ($request_method != GET) {
set $try_location @not_static;
}
if ($args ~* "live-preview=(.*)") {
set $try_location @not_static;
}
location / {
try_files $uri $try_location;
}
location @static {
try_files /static${uri}_$args.html $uri $uri/ /index.php?$args;
}
location @not_static {
try_files $uri /index.php?$args;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
# Set high timeout values
proxy_read_timeout 365d;
proxy_connect_timeout 365d;
proxy_send_timeout 365d;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
[supervisord]
nodaemon=true
user=root
[program:move_files]
command=/bin/bash /move-files.sh
autostart=true
startsecs=0
autorestart=false
priority=1
[program:php-fpm]
command=/usr/local/sbin/php-fpm -F
autostart=true
autorestart=true
priority=2
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
priority=3
#!/usr/bin/env bash
set -e
if ! [ -d /var/statamic.local ]; then
# All files already moved
exit 0
fi
# Ensure directory is empty
rm -rf /var/www/html/*
# Move all files and directories including hidden
# ones — excluding . and .. — to serve directory.
shopt -s dotglob
mv /var/statamic.local/* /var/www/html/
shopt -u dotglob
chown -R www-data:www-data /var/www/html
chmod -R 775 /var/www/html/bootstrap/cache
find /var/www/html -type f -exec chmod 644 {} \;
find /var/www/html -type d -exec chmod 755 {} \;
# Remove temporary build directory
rm -rf /var/statamic.local
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment