Contao im Container

Gespeichert von Erik Wegner am/um
Body

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:

  1. PHP mit FPM-Schnittstelle zur Ausführung des Codes
  2. nginx zur Auslieferung der Webseiten und statischen Dateien
  3. MariaDB als Datenbank
  4. 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.

Dockerfile-contao
https://github.com/docker-library/drupal/blob/127ac213294bf7b623cb4cc7507ccd5c60dce082/10.3/php8.3/fpm-alpine3.20/Dockerfile
FROM php:8.3-fpm-alpine3.20

# 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 \
git \
; \
\
docker-php-ext-configure gd \
--with-freetype \
--with-jpeg=/usr/include \
--with-webp \
; \
\
docker-php-ext-install -j "$(nproc)" \
gd \
opcache \
pdo_mysql \
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'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini

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/

ENV COMPOSER_ALLOW_SUPERUSER 1

WORKDIR /opt/contao
RUN set -eux; \
export COMPOSER_HOME="$(mktemp -d)"; \
composer create-project --no-interaction contao/managed-edition . 5.3; \
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"

RUN /bin/sh -c "echo php_admin_flag[log_errors] = on >> /usr/local/etc/php-fpm.d/docker.conf"

# vim:set ft=dockerfile:

Die Konfiguration des nginx-Webservers sorgt für die Übergabe aller Anfragen nach PHP-Dateien an den FPM-Prozess. Sonstige Dateien werden direkt ausgeliefert.

nginx.conf
server {
server_name localhost;
root /opt/contao/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 /index.php$is_args$args;
}

# Haupt Einstiegspunkt
location ~ ^/index\.php(/|$) {
# the exact FastCGI configuration depends on your environment
fastcgi_pass contao-fpm:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
internal;
}

# preview.php und contao-manager.phar.php auch zur Verarbeitung erlauben
location ~ ^/(preview|contao-manager\.phar)\.php(/|$) {
# the exact FastCGI configuration depends on your environment
fastcgi_pass contao-fpm:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
}

#return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
}

Die Bereitstellung aller Container erfolgt mit docker-compose.

docker-compose.yml
services:
contao-fpm:
image: erikwegner/contao-fpm
build: ./fpm
depends_on:
- database
restart: "no"
volumes:
- ./contao:/opt/contao
labels:
- traefik.enabled=false
networks:
- default

web:
image: nginx:1
depends_on:
- contao-fpm
restart: "no"
volumes:
- ./contao:/opt/contao
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
labels:
- traefik.http.routers.contao.rule=Host(`contao.localhost`)
networks:
- default
- traefik

database:
image: mariadb:11
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

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.

$ sudo chown 82:82 contao
$ docker compose exec -it -u www-data contao-fpm /bin/sh
$ export COMPOSER_HOME="$(mktemp -d)"
$ composer create-project --no-interaction contao/managed-edition . 5.3
$ php vendor/bin/contao-console contao:migrate
$ php vendor/bin/contao-console contao:user:create -u admin -p admin1 --email admin@localhost.local --name admin --language de --admin

Anschließend ist die Installationsseite von contao unter http://contao.localhost/contao/install erreichbar.

Das Image ist auch auf DockerHub zu finden.