Contao mittels Docker-Container einrichten

Eine gekapselte Web-Anwendung mittels Docker starten, ist recht einfach. Man benötigt einen Webserver, eine Datenbank und einen PHP-Parser.

Docker installieren

Unter Ubuntu 17.10 installieren (falls noch nicht geschehen) wir die Docker-CE-Edition:

curl -s https://download.docker.com/linux/ubuntu/dists/artful/stable/binary-amd64/Packages.gz | gunzip && \
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu zesty stable" && \
sudo apt update && \
sudo apt install docker-ce && \
docker version

Im Anschluss wird noch docker-compose installiert:

sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose && \
docker-compose --version

Umgebungsvariablen setzen

Docker-Container erzeugen standardmäßig Ordner und Dateien mit root-Rechten. Das ist natürlich doof, wenn wir gemappte / gemountete Ordner im Docker-Container und auf dem Host bearbeiten möchten. Der Plan ist die gleiche User- und Group-ID zu benutzen. Dazu legen wir 2 Environment-Variablen in unserer Bash fest:

echo 'export DOCKER_ENV_USER_ID="$(id -u)"' >> ${HOME}/.bashrc && \
echo 'export DOCKER_ENV_GROUP_ID="$(id -g)"' >> ${HOME}/.bashrc && \
echo 'export DOCKER_ENV_CERT_PATH="${HOME}/docker/data/certs"' >> ${HOME}/.bashrc

... und starten die Bash neu, damit die Umgebungsvariablen auch zur Verfügung stehen:

exec bash

Proxy für mehrere Projekte

Damit wir mehrere Projekte gleichzeitig ohne Angabe eines Ports laufen lassen, benötigen wir noch einen Reverse-Proxy. Dazu legen wir eine docker-compose.yml-Datei mit folgenden Inhalt an:

version: '3'
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ${DOCKER_ENV_CERT_PATH}:/etc/nginx/certs
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always
    networks:
      - nginx-proxy-network

networks:
  nginx-proxy-network:
    external: true

Als globalen SSL-Zertifikatsspeicher erstellen wir einen zentralen Ablageort. Dieser Zertifikatsordner wird für den Reverse-Proxy und zukünftige Docker-Server benötigt. Damit wir den Ordner überall direkt einbinden können, setzen wir dafür auch eine Umgebungsvariable:

mkdir ${HOME}/docker/data/certs -p && \
echo 'export DOCKER_ENV_CERT_PATH="${HOME}/docker/data/certs"' >> ${HOME}/.bashrc && \
exec bash

Im Anschluss wird ein neues Netzwerk erstellt und der nginx-Reverse-Proxy wird gestartet. Damit der Reverse-Proxy funktioniert muss das Reverse-Proxy-Netzwerk in jedem zukünftigen Docker-Container angegeben werden.

docker network create nginx-proxy-network
docker-compose up -d

Docker-Container-Landschaft für Contao erstellen

Wir clonen folgendes GitHub-Repository https://github.com/xuad/docker-contao.git und öffnen den Ordner mit PhpStorm und sehen folgende Struktur:

docker-contao_1

Da wir alle Services in extra Container erstellen, bauen wir zu erst einen für den Dienst: composer. Wir öffnen wieder das Terminal und lassen uns den composer-Container bauen. Als Argumente reichen wir noch unsere UID und GUID, welche in der Umgebungsvariable gespeichert ist mit. Damit laufen zukünftig alle Befehle mit unsere UID und GUID!

docker build build/composer-php-7.1 --build-arg PHP_USER_ID=${DOCKER_ENV_USER_ID} --build-arg PHP_GROUP_ID=${DOCKER_ENV_GROUP_ID} -t xuad/composer:7.1

SSL-Zertifikat

Als nächster Schritt steht das Erzeugen eines SSL-Schlüssel für unsere docker-contao.local - Domain an:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
     -keyout ${DOCKER_ENV_CERT_PATH}/docker-contao.local.key \
     -out ${DOCKER_ENV_CERT_PATH}/docker-contao.local.crt \
     -subj "/C=DE/ST=Deutschland/L=Musterhausen/O=docker-contao.local/CN=docker-contao.local"

Das Zertifikat wird wie gewünscht in unseren globalen Zertifikatsordner abgelegt.

Xdebug

Damit xdebug korrekt funktioniert muss unter Umständen die lokale IP-Adresse in der docker-compose.yml angepasst werden. Diese findet ihr mit dem Befehl ifconfig heraus. Eure lokale IP-Adresse könnt Ihr unter php-fpm -> environment -> PHP_XDEBUG_REMOTE_HOST anpassen

docker-contao_1.jpg

Docker-Landschaft starten

Die Docker-Container lasst ihr mit docker-compose bauen und danach gleich starten:

docker-compose build && docker-compose up

Nach dem Bauen sollten 4 Container mittels

docker ps

erscheinen.

docker-contao_2

Jetzt ist es Zeit um Contao zu installieren. Dazu befindet sich die composer.json (https://github.com/contao/managed-edition/blob/master/composer.json) der Managed-Edition im Ordner source. Dieser Ordner wird innerhalb der Docker-Container nach /app gemountet. Um die Komponenten zu installieren in das Terminal folgendes eingeben:

./composer.sh install

Das startet dem zuvor erstellten Composer-PHP-Container und mountet die wichtigsten Ordner in den Docker-Container.

Contao einrichten

Damit wir docker-contao.local auch aufrufen können, müssen wir unseren Vhost noch in der Host-Datei bekannt machen:

echo "127.0.0.1 docker-contao.local" | sudo tee --append /etc/hosts

Jetzt können wir mit dem Browser unsere Wahl die Contao-Startseite betrachten:

docker-contao_3

Bei der Datenbank-Verbindung müssen die Einstellungen welche in der docker-compose.yml hinterlegt sind, angegeben werden:

docker-contao_4

Viel Spaß mit dem Entwickeln von Contao-Plugins unter Docker-Containern.

Kommentar von Frank am

Danke für diesen Artikel. Hat mir als Vorlage und Ideengeber für meinen Anwendungsfall sehr geholfen.

Speziell die Steuerung des Benutzer- und Gruppen-IDs und die Projektstruktur finde ich gut.

Unterschiede ist dass ich z.B. das SSL-Zertifikat innerhalb meines kombinierten PHP-Apache-Images erzeuge und ablege.

Den Anwendungsfall für den Reverse-Proxy habe ich hier allerdings noch nicht so richtig verstanden...?

Grüße

Antwort von xuad

Freut mich das es dir weiter hilft. Durch den Reverse-Proxy kann man mehrere Projekte mit eigenen Vhost laufen lassen und muss nicht für jede Apache / Nginx - Instanz einen eigenen Port definieren.

Einen Kommentar schreiben