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-image
cd 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.sh
vi 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.sh
RUN \
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.conf
VOLUME ["/var/www/html", "/usr/lib/cgi-bin", "/etc/apache2/sites-available", "/var/log/apache2", "/etc/letsencrypt"]
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
EXPOSE 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@localhost
DocumentRoot /usr/lib/cgi-bin/
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/usr/lib/cgi-bin">
Options +Indexes +ExecCGI -MultiViews +FollowSymLinks +Includes -SymLinksIfOwnerMatch
AddHandler default-handler .xml .tar .rom .d64 .prg .txt .png .js .gif .jpg .htm .html .jar .css
AddHandler cgi-script .cgi .pl .sh
AllowOverride None
Order allow,deny
allow from 192.168.0.0/255.255.255.0
</Directory>
#ErrorLog /var/log/apache2/error.log
ErrorLog /dev/null
#CustomLog /var/log/apache2/access.log combined
CustomLog /dev/null combined
ServerName localhost
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /usr/lib/cgi-bin/
# SSL
SSLEngine On
SSLCipherSuite HIGH:MEDIUM
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/usr/lib/cgi-bin">
Options +Indexes +ExecCGI -MultiViews +FollowSymLinks +Includes -SymLinksIfOwnerMatch
AddHandler default-handler .xml .tar .rom .d64 .prg .txt .png .js .gif .jpg .htm .html .jar .css
AddHandler cgi-script .cgi .pl
AllowOverride None
Satisfy Any
Order allow,deny
allow from 192.168.0.0/255.255.255.0
AuthType Basic
AuthName "Geschuetzter Bereich"
AuthUserFile /usr/lib/cgi-bin/htpasswd
Require valid-user
</Directory>
#ErrorLog /var/log/apache2/error_ssl.log
ErrorLog /dev/null
#CustomLog /var/log/apache2/access_ssl.log combined
CustomLog /dev/null combined
ServerName localhost
SSLCertificateFile /etc/letsencrypt/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>