{"id":6118,"date":"2019-06-20T15:40:50","date_gmt":"2019-06-20T13:40:50","guid":{"rendered":"https:\/\/u-labs.de\/portal\/?p=6118"},"modified":"2019-06-20T15:52:24","modified_gmt":"2019-06-20T13:52:24","slug":"apache2-4-mit-php7-in-docker-compose-performant-ausfuehren","status":"publish","type":"post","link":"https:\/\/u-labs.de\/portal\/apache2-4-mit-php7-in-docker-compose-performant-ausfuehren\/","title":{"rendered":"Apache2.4 mit PHP7 in Docker-Compose performant ausf\u00fchren"},"content":{"rendered":"<p>Der Apache-Webserver ist aufgrund seiner Vielseitigkeit und Flexibilit\u00e4t bis heute beliebt. H\u00e4ufig wird er zusammen mit der Skriptsprache PHP eingesetzt. Apache und PHP stellen offizielle Images bereit, die den einfachen Betrieb auf Basis von Docker und Docker-Compose erm\u00f6glichen. Dieser Artikel zeigt eine minimalistische Konfiguration. <\/p>\n<p>Beginnen wir mit der Struktur unseres Arbeitsverzeichnisses:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 htdocs\n\u2502  \u2514\u2500\u2500 index.php\n\u251c\u2500\u2500 htdpcs\n\u2514\u2500\u2500 httpd.conf\n<\/pre>\n<\/div>\n<p>Der Ordner htdocs wird sp\u00e4ter vom Webserver ausgeliefert. Die index.php Datei liefert beispielhaft phpinfo(); aus. So k\u00f6nnen wir sp\u00e4ter die korrekte Konfiguration von PHP testen. <\/p>\n<p>Als Basis wird die <strong>docker-compose.yml<\/strong> Datei erstellt:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nversion: &quot;2.4&quot;\nservices: \n  apache:\n    image: httpd:2.4\n    volumes:\n      - .\/httpd.conf:\/usr\/local\/apache2\/conf\/httpd.conf\n      - .\/htdocs:\/usr\/local\/apache2\/htdocs\n    ports:\n      - 80:80\n\n  php:\n    image: php:7.3-fpm\n    volumes_from:\n      - apache\n<\/pre>\n<\/div>\n<p>Wir definieren also einen Apache-Container, der sowohl die Konfigurationsdatei, als auch den htdocs-Ordner als Volume gemountet erh\u00e4lt. Durch die Portfreigabe ist der Webserver auf dem Host lokal \u00fcber Port 80 erreichbar. Abgesehen von kleineren Umgebungen wird man produktiv daf\u00fcr eher einen Reverse-Proxy wie traefik einsetzen. <\/p>\n<p>Der PHP-Container erh\u00e4lt diese Volumes auch, damit er die PHP-Skripte ausf\u00fchren kann. Zum Einsatz kommt das jeweils aktuellste PHP 7.3 Image. So erh\u00e4lt der Container die aktuellsten Sicherheitsaktualisierungen. Bei darf kann hier auch eine \u00e4ltere Version genutzt werden. <strong>php:7.2-fpm<\/strong><em> <\/em>w\u00fcrde beispielsweise die Vorversion ausf\u00fchren. <\/p>\n<h2 class=\"wp-block-heading\">Apache2 Konfiguration<\/h2>\n<p>Die Datei <strong>httpd.conf<\/strong> f\u00fcllen wir mit folgender Konfiguration:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nListen 80\nLogLevel info\nErrorLog \/proc\/self\/fd\/2\nUser daemon\nGroup daemon\nServerRoot &quot;\/usr\/local\/apache2&quot;\nServerName localhost\nDirectoryIndex index.php index.html\n\n# https:\/\/httpd.apache.org\/docs\/2.4\/mod\/\nLoadModule mpm_event_module modules\/mod_mpm_event.so\nLoadModule authz_core_module modules\/mod_authz_core.so\nLoadModule access_compat_module modules\/mod_access_compat.so\nLoadModule unixd_module modules\/mod_unixd.so\nLoadModule mime_module modules\/mod_mime.so\nLoadModule log_config_module modules\/mod_log_config.so\nLoadModule dir_module modules\/mod_dir.so\n\nLoadModule proxy_module modules\/mod_proxy.so\nLoadModule proxy_fcgi_module modules\/mod_proxy_fcgi.so\n\nLoadModule filter_module modules\/mod_filter.so\nLoadModule deflate_module modules\/mod_deflate.so\n\n\nCustomLog \/proc\/self\/fd\/1 common\nLogFormat &quot;%h %l %u %t \\&quot;%r\\&quot; %&gt;s %b \\&quot;%{Referer}i\\&quot; \\&quot;%{User-Agent}i\\&quot;&quot; combined\nLogFormat &quot;%h %l %u %t \\&quot;%r\\&quot; %&gt;s %b&quot; common\n\nTypesConfig conf\/mime.types\nAddType application\/x-compress .Z\nAddType application\/x-gzip .gz .tgz\n\nSetOutputFilter DEFLATE\nAddOutputFilterByType DEFLATE text\/html text\/plain text\/xml \nAddOutputFilterByType DEFLATE text\/css \nAddOutputFilterByType DEFLATE application\/x-javascript application\/javascript application\/ecmascript \nAddOutputFilterByType DEFLATE application\/rss+xml \nAddOutputFilterByType DEFLATE application\/xml \n\n&amp;lt;Directory \/&gt;\n    AllowOverride none\n    Require all denied\n&amp;lt;\/Directory&gt;\n\n&amp;lt;Files &quot;.ht*&quot;&gt;\n    Require all denied\n&amp;lt;\/Files&gt;\n\n#ProxyPassMatch ^\/(.*\\.php(\/.*)?)$ fcgi:\/\/php:9000\/usr\/local\/apache2\/htdocs\/$1\n&amp;lt;VirtualHost *:80&gt;\n    DocumentRoot &quot;\/usr\/local\/apache2\/htdocs&quot;\n    &amp;lt;Directory &quot;\/usr\/local\/apache2\/htdocs&quot;&gt;\n        Options Indexes FollowSymlinks\n        AllowOverride None\n        Require all granted\n\n        &amp;lt;FilesMatch &quot;\\.php$&quot;&gt;\n            SetHandler &quot;proxy:fcgi:\/\/php:9000\/&quot;\n        &amp;lt;\/FilesMatch&gt;\n    &amp;lt;\/Directory&gt;\n&amp;lt;\/VirtualHost&gt;\n\n<\/pre>\n<\/div>\n<p>Hierbei handelt es sich um eine minimalistische Basiskonfiguration f\u00fcr Apache2. Es werden nur die Kernmodule geladen. Sie aktiviert das Logging auf dem stdout Kanal. So lassen sich die Logs auf der Konsole bzw. mit docker logs im Detached-Modus abrufen. Dar\u00fcber hinaus wird das standardm\u00e4\u00dfige MIME-Mapping von Apache aktiviert sowie die GZIP-Kompromierung. Und das wichtigste f\u00fcr diesen Stack: Weiterreichen von PHP-Dateien an PFP-FPM mit dem FastCGI-Modul. <\/p>\n<h2 class=\"wp-block-heading\">Testlauf<\/h2>\n<p>Final wird <strong>htdocs\/index.php<\/strong> angelegt und gef\u00fcllt:<\/p>\n<pre class=\"wp-block-preformatted\">&lt;?php phpinfo();<\/pre>\n<p>Nun sind alle erforderlichen Dateien vorhanden. Die Container k\u00f6nnen gestartet werden:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndocker-compose up \n<\/pre>\n<\/div>\n<p>Wahlweise kann man auch <strong>-d<\/strong> anh\u00e4ngen, damit die Container in Hintergrund gestartet werden. Gerade zum testen finde ich attached besser, hier sind alle Ausgaben auf dem Terminal sichtbar. <\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/u-img.net\/img\/6559Vr.png\" alt=\"\"\/><\/figure>\n<p>Durch den Aufruf von <strong>http:\/\/localhost<\/strong> im Browser sollte die PHP Infoseite sichtbar werden:<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/u-img.net\/img\/8672Lj.png\" alt=\"\"\/><\/figure>\n<h2 class=\"wp-block-heading\">Warum nicht nur die Standard httpd.conf anpassen?<\/h2>\n<p>Teils wird in Beispielen keine eigene Apache-Konfigurationsdatei namens <strong>httpd.conf<\/strong> erstellt. Sondern ein Docker-Image, worin dann Ersetzungen auf der Standard-Konfigurationsdatei durchgef\u00fchrt werden. Beispielsweise l\u00e4sst sich mit <strong>sed<\/strong> die Raute vor einer <strong>LoadModule<\/strong> Direktive entfernen, um ein Modul zu laden. Oder man f\u00fcgt einfach eigene Zeilen hinzu. Grunds\u00e4tzlich funktioniert das, doch ich empfehle dieses Vorgehen aus zwei Gr\u00fcnden nicht: <\/p>\n<h3 class=\"wp-block-heading\">Potenzielle Fehlerquellen<\/h3>\n<p>Je nach Einsatzzweck k\u00f6nnen manche Standardwerte einem Probleme bereiten. Diese muss man ermitteln und entsprechend anpassen oder entfernen. Danach verl\u00e4sst man sich auf die verbliebenen Standardwerte. Werden diese irgendwann mal ge\u00e4ndert, funktioniert die daraus entstehende Konfiguration u.u. nicht mehr wie erwartet. <\/p>\n<h3 class=\"wp-block-heading\">\u00dcbersicht und Wartbarkeit<\/h3>\n<p>Selten bleibt es bei 1 oder 2 \u00c4nderungen. Je mehr angepasst werden muss, um so un\u00fcbersichtlicher wird das Dockerfile. Die Komplexit\u00e4t steigt dadurch sowohl f\u00fcr die Fehlerauche, als auch sp\u00e4tere Erweiterungen.<\/p>\n<h3 class=\"wp-block-heading\">Performance und Sicherheit<\/h3>\n<p>Die Standard-Konfiguration ist darauf ausgelegt, in vielen F\u00e4llen m\u00f6glichst einfach zu funktionieren. Das beugt Frust bei Einsteigern vor, aber ist nicht optimal f\u00fcr die Leistung. Beispielsweise sind standardm\u00e4\u00dfig viele Module aktiviert, die oft gar nicht alle ben\u00f6tigt werden. Der Apache l\u00e4dt sie aber trotzdem bei jeder Anfrage. Dies entspricht auch nicht den Best Practices hinsichtlich Sicherheit. <\/p>\n<h3 class=\"wp-block-heading\">Schlussfolgerung: Eigene Konfiguration<\/h3>\n<p>Aus diesen Gr\u00fcnden halte ich eine eigene, explizite Konfiguration f\u00fcr sinnvoller. Darin aktiviert man nur das, was ben\u00f6tigt wird. Unabh\u00e4ngig von Docker hat sich dieses Vorgehen bereits in mehreren Szenarien bew\u00e4hrt. Der Mehraufwand ist \u00fcberschaubar. Wird mit mehreren Projekten gearbeitet, kann eine Basis-Konfiguration wie aus diesem Artikel als Grundlage genommen werden. Diese passt man dann an und l\u00e4dt beispielsweise zus\u00e4tzliche Module, welche im jeweiligen Projekt ben\u00f6tigt werden. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Der Apache-Webserver ist aufgrund seiner Vielseitigkeit und Flexibilit\u00e4t bis heute beliebt. H\u00e4ufig wird er zusammen mit der Skriptsprache PHP eingesetzt. Apache und PHP stellen offizielle Images bereit, die den einfachen Betrieb auf Basis von Docker und Docker-Compose erm\u00f6glichen. Dieser Artikel zeigt eine minimalistische Konfiguration. Beginnen wir mit der Struktur unseres Arbeitsverzeichnisses: Der Ordner htdocs wird &#8230;<\/p>\n","protected":false},"author":5,"featured_media":6123,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[74,5,78],"tags":[718,497,55],"class_list":["post-6118","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-news","category-software","tag-apache","tag-docker","tag-php"],"_links":{"self":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/6118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/comments?post=6118"}],"version-history":[{"count":16,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/6118\/revisions"}],"predecessor-version":[{"id":6135,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/6118\/revisions\/6135"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media\/6123"}],"wp:attachment":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media?parent=6118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/categories?post=6118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/tags?post=6118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}