Contao ist ein Content Management System auf PHP-Basis. Die folgenden Hinweise sollen helfen, es mit Hilfe von Docker laufen zu lassen. Das Ergebnis sind 4 getrennte Container:
- PHP mit FPM-Schnittstelle zur Ausführung des Codes
- nginx zur Auslieferung der Webseiten und statischen Dateien
- MariaDB als Datenbank
- Adminer für den einfachen Zugriff auf die Datenbank
Als Voraussetzung habe ich Traefik installiert, um das Verteilen der Zugriffe auf die Container zu routen.
In der Datei Dockerfile-contao wird die PHP-Umgebung bereitgestellt. Zur Vereinfachung verwende ich die Drupal-Bereitstellung.
# from https://github.com/docker-library/drupal/blob/0bc267208f3f1405b8441588a48e0004508f65f8/9.4/php8.1/fpm-alpine3.16/Dockerfile
FROM php:8.1-fpm-alpine3.16
# install the PHP extensions we need
RUN set -eux; \
\
apk add --no-cache --virtual .build-deps \
coreutils \
freetype-dev \
libjpeg-turbo-dev \
libpng-dev \
libwebp-dev \
libzip-dev \
# postgresql-dev is needed for https://bugs.alpinelinux.org/issues/3642
postgresql-dev \
; \
\
docker-php-ext-configure gd \
--with-freetype \
--with-jpeg=/usr/include \
--with-webp \
; \
\
docker-php-ext-install -j "$(nproc)" \
gd \
opcache \
pdo_mysql \
pdo_pgsql \
zip \
; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-network --virtual .drupal-phpexts-rundeps $runDeps; \
apk del --no-network .build-deps
# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini
# Thanks to https://github.com/docker-library/php/issues/57#issuecomment-318056930
RUN set -xe \
&& apk add --update icu \
&& apk add --no-cache --virtual .php-deps make \
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS zlib-dev icu-dev \
&& docker-php-ext-configure intl \
&& docker-php-ext-install intl \
&& docker-php-ext-enable intl \
&& { find /usr/local/lib -type f -print0 | xargs -0r strip --strip-all -p 2>/dev/null || true; } \
&& apk del .build-deps \
&& rm -rf /tmp/* /usr/local/lib/php/doc/* /var/cache/apk/*
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/
WORKDIR /opt/contao
RUN set -eux; \
export COMPOSER_HOME="$(mktemp -d)"; \
composer create-project --no-interaction contao/managed-edition . 4.13; \
chown -R www-data:www-data var; \
rmdir /var/www/html; \
ln -sf /opt/contao/public /var/www/html; \
# delete composer cache
rm -rf "$COMPOSER_HOME"
ENV PATH=${PATH}:/opt/contao/vendor/bin
RUN /bin/sh -c "echo php_admin_flag[log_errors] = on >> /usr/local/etc/php-fpm.d/docker.conf"
Die Konfiguration des nginx-Webservers sorgt für die Übergabe aller Anfragen nach PHP-Dateien an den FPM-Prozess. Sonstige Dateien werden direkt ausgeliefert.
server {
server_name localhost;
root /var/www/html/public;
index index.php index.html index.htm;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM Configuration Nginx
location ~ \.php$ {
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param DOCUMENT_ROOT /var/www/html;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
}
}
Die Bereitstellung aller Container erfolgt mit docker-compose.
version: "3"
services:
php:
build:
context: .
dockerfile: Dockerfile-contao
depends_on:
- database
restart: 'no'
volumes:
- ./contao:/opt/contao
labels:
- traefik.enabled=false
networks:
- default
web:
image: nginx:1
depends_on:
- php
restart: 'no'
volumes:
- ./contao:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
labels:
- traefik.http.routers.contao.rule=Host(`contao.localhost`)
networks:
- default
- traefik
database:
image: mariadb:10
restart: 'no'
environment:
- MARIADB_ROOT_PASSWORD=contao
- MARIADB_DATABASE=contao
- MARIADB_PASSWORD=contao
- MARIADB_USER=contao
volumes:
- ./db_data:/var/lib/mysql:rw
labels:
- traefik.enabled=false
networks:
- default
adminer:
image: adminer
restart: 'no'
labels:
- traefik.http.routers.adminer-contao.rule=Host(`adminer-contao.localhost`)
networks:
- default
- traefik
volumes:
db_data:
networks:
traefik:
external: true
In der docker-compose-Datei wird das Verzeichnis ./contao dem Container-Verzeichnis /opt/contao zugeordnet. Damit die Inhalte am richtigen Platz landen, wird nach dem Starten der Container die Installation mittels composer wiederholt.
Anschließend ist die Installationsseite von contao unter http://contao.localhost/contao/install erreichbar.