In diesem HowTo geht es darum ein Docker Image mit einem Apache2 Server mit Perl-Umgebung zu erstellen.
Dieses Image setze ich mittlerweile in meinem Tommatic Projekt ein.
Das "docker-apache-perl" Image basiert auf meinem eigenen "raspbian-buster" Basis-Image welche ich im HowTo "Eigenes Raspian Basis-Image erzeugen" vorgestellt habe.
Die Veröffentlichung dieses Howtos erfolgt in der Hoffnung, dass es dem Ein oder Anderen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK.
In der ersten Version dieses Howto konnte ich den Container nicht über die Docker Befehle starten, stoppen und neu starten. Hierbei kam es zu Problemen mit dem ausführen von CGI/Perl-Skripten und der Fehlermeldung "Apache: 503 Service Unavailable".
In der ersten Version hatte ich schon erkannt, dass im Container im Verzeichnis "/var/run/apache2" ein PID-File und Socket-Dateien übrigblieben, welche das starten des cgid verhinderten.
Die Lösung ist dabei recht einfach: vor dem Start des Apache2 müssen eventuelle Dateien im Verzeichnis "/var/run/apache2" gelöscht werden! Dann gehören die Probleme der Vergangenheit an.
Ich habe dieses Howto nun dahingehend abgewandelt, dass das Starten des Apache 2 über ein mini Skript innerhalb des Containers geschieht, welches vor dem Start die Dateien im Verzeichnis "/var/run/apache2" löscht.
Damit der Apache-Server von außen konfiguriert und überwacht werden kann hat er folgende Volumes:
Diese Volumes werden beim Erzeugen eines Containers auf lokale Verzeichnisse außerhalb des Containers gemappt. In den Lokalen Verzeichnissen werden dann die Konfigurationen abgelegt und die Logfiles von Apache2 können dort eingesehen werden.
Als erstes wird ein Verzeichnis angelegt, in dem alles bearbeitet wird:
mkdir apache2-perl-imagecd apache2-perl-image
In diesem Verzeichnis legen wir nun das Skript an, welches den Apache2 innerhalb des Containers sicher startet:
touch startapache2.sh"chmod 755 startapache2.shvi startapache2.sh
Das Skript "startapache2.sh" hat den folgenden Inhalt:
#!/bin/bash"rm -rf /var/run/apache2/*/usr/sbin/apache2ctl -D FOREGROUND
In selben Verzeichnis wird eine Datei mit dem Namen "Dockerfile" angelegt. Diese hat den folgenden Inhalt:
FROM "raspbian-buster"COPY startapache2.sh /usr/sbin/startapache2.shRUN \DEBIAN_FRONTEND=noninteractive && \apt-get update && \apt-get install -y \apache2 \libwww-perl \libxml-simple-perl \libgd-gd2-perl \libdate-calc-perl \libdata-uniqid-perl \liburi-encode-perl \libxml-libxml-perl \libxml-twig-perl \libxml-xpathengine-perl \libcgi-pm-perl \python-libxml2 \python-lxml \libgraphics-colorobject-perl \libmath-round-perl \make \gcc \vim && \cpan JSON::Parse && \a2enmod cgid && \a2enmod rewrite && \a2enmod cgi && \a2enmod ssl && \a2ensite default-ssl.conf && \apt-get update -y && \apt-get upgrade -y && \apt-get -y clean && \mkdir /etc/letsencrypt && \echo "ServerName localhost" >>/etc/apache2/apache2.confVOLUME ["/var/www/html", "/usr/lib/cgi-bin", "/etc/apache2/sites-available", "/var/log/apache2", "/etc/letsencrypt"]ENV APACHE_RUN_USER www-dataENV APACHE_RUN_GROUP www-dataEXPOSE 80 443
Zeile 02
Mit dem Befehl COPY wird das Startskript aus dem lokalen Verzeichnis in das Image kopiert.
Zeilen 05 - 24
Hier werden alle notwendigen Raspian-Pakete installiert. Die Liste kann den eigenen Bedürfnissen angepasst werden.
Hinter dem letzen Paketnamen muss zwingend ein "&&" stehen!
Zeile 25
In dieser Zeile wird ein CPAN-Modul heruntergeladen und installiert.
Zeilen 26 - 30
Hier werden zusätzliche Apache2 Module und die "default-ssl.conf" aktiviert.
Zeilen 31 - 33
Aufräumen von "apt-get".
Zeile 34
In dieser Zeile wird ein Verzeichnis innerhalb des Docker Containers angelegt.
Zeile 35
Damit es wegen eines fehlenden Servername zu keinen Fehlermeldungen kommt wird an die Datei "apache2.conf" die Zeile "ServerName localhost" angehängt.
Zeile 37
Hier werden die Volumes als Schnittstelle zur Außenwelt erzeugt .
Zeile 42
Der HTTP und der HTTPS Port wird nach außen geöffnet.
Um das eigentliche Image zu erzeugen wird der folgende Befehl ausgeführt. Dabei ist zu beachten, dass der Befehl im Verzeichnis der Datei "Dockerfile" ausgeführt wird.
docker build -t apache-perl .
Bevor wir den eigentlichen Container erzeugen und starten müssen einige Verzeichnisse angelegt und teilweise auch gefüllt werden.
/root/docker/apache/html
Das Basisverzeichnis für HTML-Seiten des Apache2. Hier werden die Webinhalte abgelegt.
Da meine Webanwendungen samt und sonders Perl-Anteile haben verwend ich dieses Verzeichnis nicht und es bleibt bei mir immer leer.
mkdir /root/docker/apache/html
/root/docker/apache/cgi-bin
Das Basisverzeichnis für CGI-Skripte. In meinem Fall liegen hier die HTML-Seiten, Perl-Skripte, und, und, und.
mkdir /root/docker/apache/cgi-bin
/root/docker/apache/log
In diesem Verzeichnis werden die Logdateien des Apache2 angelegt und können hier eingesehen werden.
mkdir /root/docker/apache/log
/root/docker/apache/sites-available
Hier werden die Konfigurationsdateien für HTTP (000-default.conf) und HTTPS (default-ssl.conf) abgelegt .
Beispiele habe ich weiter unten aufgeführt.
mkdir /root/docker/apache/sites-available
/root/docker/apache/letsencrypt
In diesem Verzeichnis lege ich meine Zertifikate für die HTTPS-Verschlüsselung ab.
mkdir /root/docker/apache/letsencrypt
Los geht's
Nun wird es Zeit, aus dem gerade erzeugten Image einen Container zu erstellen. Dies kann aus der Kommandozeile oder aber auch durch ein Skript erfolgen.
docker run -d \--name="apache2" \--restart=always \-v /root/docker/apache/html:/var/www/html \-v /root/docker/apache/cgi-bin:/usr/lib/cgi-bin \-v /root/docker/apache/log:/var/log/apache2 \-v /root/docker/apache/sites-available:/etc/apache2/sites-available \-v /root/docker/apache/letsencrypt:/etc/letsencrypt \-p 80:80 \-p 443:443 \-d apache-perl \/usr/sbin/startapache2.sh
Zeile 02
Hier wird der zukünftige Name des Docker Containers angegeben.
Zeile 03
In dieser Zeile wird das Restartverhalten angegeben. Ich stelle es so ein, dass der Container immer automatisch neu gestartet wird.
Zeilen 04 - 08
Mappen der Volumes zu lokalen Verzeichnissen.
Zeilen 09 - 10
Mappen der externen zu den internen TCP-Ports.
Zeile 11
Das Image das als Grundlage für diesen Container verwendet wird.
Zeile 12
Hier steht der eigentliche Startbefehl - das Startskript
<VirtualHost *:80>ServerAdmin webmaster@localhostDocumentRoot /usr/lib/cgi-bin/<Directory />Options FollowSymLinksAllowOverride None</Directory><Directory "/usr/lib/cgi-bin">Options +Indexes +ExecCGI -MultiViews +FollowSymLinks +Includes -SymLinksIfOwnerMatchAddHandler default-handler .xml .tar .rom .d64 .prg .txt .png .js .gif .jpg .htm .html .jar .cssAddHandler cgi-script .cgi .pl .shAllowOverride NoneOrder allow,denyallow from 192.168.0.0/255.255.255.0</Directory>#ErrorLog /var/log/apache2/error.logErrorLog /dev/null#CustomLog /var/log/apache2/access.log combinedCustomLog /dev/null combinedServerName localhost</VirtualHost>
<VirtualHost *:443>ServerAdmin webmaster@localhostDocumentRoot /usr/lib/cgi-bin/# SSLSSLEngine OnSSLCipherSuite HIGH:MEDIUM<Directory />Options FollowSymLinksAllowOverride None</Directory><Directory "/usr/lib/cgi-bin">Options +Indexes +ExecCGI -MultiViews +FollowSymLinks +Includes -SymLinksIfOwnerMatchAddHandler default-handler .xml .tar .rom .d64 .prg .txt .png .js .gif .jpg .htm .html .jar .cssAddHandler cgi-script .cgi .plAllowOverride NoneSatisfy AnyOrder allow,denyallow from 192.168.0.0/255.255.255.0AuthType BasicAuthName "Geschuetzter Bereich"AuthUserFile /usr/lib/cgi-bin/htpasswdRequire valid-user</Directory>#ErrorLog /var/log/apache2/error_ssl.logErrorLog /dev/null#CustomLog /var/log/apache2/access_ssl.log combinedCustomLog /dev/null combinedServerName localhostSSLCertificateFile /etc/letsencrypt/fullchain.pemSSLCertificateKeyFile /etc/letsencrypt/privkey.pemInclude /etc/letsencrypt/options-ssl-apache.conf</VirtualHost>