{"id":1044,"date":"2018-11-02T09:51:59","date_gmt":"2018-11-02T09:51:59","guid":{"rendered":"http:\/\/192.168.2.32:8082\/?p=1044"},"modified":"2020-06-30T11:10:51","modified_gmt":"2020-06-30T11:10:51","slug":"wordpress-container-auf-docker","status":"publish","type":"post","link":"https:\/\/www.dev-metal.ch\/?p=1044","title":{"rendered":"WordPress Container auf Docker"},"content":{"rendered":"\r\n<p>Dieser Blog-Eintrag beschreibt, wie man auf WordPress auf einem Docker-Host installieren und damit mehrere WordPress-Instanzen auf einem Host betreiben kann.<br \/>Ich betreibe die Docker-Container hinter einem Proxy-Server, der aber nicht als Container l\u00e4uft. Der Proxy-Server leitet die HTTPS-Requests an die entsprechenden Docker-Container weiter.<\/p>\r\n\r\n\r\n\r\n<p>Dieser Beitrag setzt ein vorinstalliertes Photon 3.0 inkl. Docker und Docker-Compose voraus. Siehe <a href=\"https:\/\/www.dev-metal.ch\/?p=1014\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"hier (\u00f6ffnet in neuem Tab)\">hier<\/a>.<\/p>\r\n\r\n\r\n\r\n<p>Die Docker-Container k\u00f6nnen \u00fcber diverse Befehle gemanaged werden. Siehe dazu eine kleine \u00dcbersicht <a href=\"https:\/\/www.dev-metal.ch\/?p=1070\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"hier (\u00f6ffnet in neuem Tab)\">hier<\/a>.<\/p>\r\n\r\n\r\n\r\n<h3 class=\"wp-block-heading\">WordPress installieren<\/h3>\r\n\r\n\r\n\r\n<p>Wir installieren WordPress mit Hilfe von Docker Compose. Dazu erstellen wir ein template:<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">mkdir wordpress\r\ncd wordpress\r\nvi docker-compose.yml<\/pre>\r\n\r\n\r\n\r\n<p>Im yml-Script erstellen wir eine WordPress- inkl. DB-Instanz.<\/p>\r\n\r\n\r\n\r\n<p>WordPress-Instanz<\/p>\r\n\r\n\r\n\r\n<ul class=\"wp-block-list\">\r\n<li>Die WordPress-Instanz hat eine Abh\u00e4ngigkeit zur DB.<\/li>\r\n<li>Die WordPress-Files werden unter \/var\/www\/html abgelegt<\/li>\r\n<li>der Host-Port 80 wird zur wordpress-Instanz port 80 weitergeleitet (&#8222;80:80&#8220;)<\/li>\r\n<li>Die DB ist \u00fcber Port 3306 anzusprechen (WORDPRESS_DB_HOST: db:3306)<\/li>\r\n<li>Der DB-User ist wordpress (WORDPRESS_DB_USER: wordpress)<\/li>\r\n<li>Das DB-Passowort ist zu setzen: WORDPRESS_DB_PASSWORD: &lt;wordpress_db_password&gt;<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<p>DB-Instanz<\/p>\r\n\r\n\r\n\r\n<ul class=\"wp-block-list\">\r\n<li>Die DB-Files werden hier abgelegt: db_data:\/var\/lib\/mysql<\/li>\r\n<li>Passort setzen: MYSQL_ROOT_PASSWORD: &lt;mysql root password&gt;<\/li>\r\n<li>Datenbank definieren: MYSQL_DATABASE: wordpress<\/li>\r\n<li>User definieren: MYSQL_USER &lt;wordpress&gt;<\/li>\r\n<li>DB-Passwort setzen: MYSQL_PASSWORD: (wordpress db password)<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\r\n<pre class=\"lang:vim decode:true\">version: '3.3' services:\r\n\r\nwordpress:\r\n   depends_on:\r\n     - db\r\n   image: wordpress:latest\r\n   volumes:\r\n     - wordpress_files:\/var\/www\/html\r\n   ports:\r\n     - \"8080:80\"\r\n   restart: always\r\n   environment:\r\n     WORDPRESS_DB_HOST: db:3306\r\n     WORDPRESS_DB_USER: wordpress\r\n     WORDPRESS_DB_PASSWORD: (wordpress_db_password)\r\n\r\ndb:\r\n   image: mysql:5.7\r\n   command: '--default-authentication-plugin=mysql_native_password'\r\n   volumes:\r\n     - db_data:\/var\/lib\/mysql\r\n   restart: always\r\n   environment:\r\n     MYSQL_ROOT_PASSWORD: (mysql root password)\r\n     MYSQL_DATABASE: wordpress\r\n     MYSQL_USER: wordpress\r\n     MYSQL_PASSWORD: (wordpress db password)\r\n   volumes:\r\n     wordpress_files:\r\n     db_data:<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/blockquote>\r\n\r\n\r\n\r\n<p>Die letzten beiden Linien restellen lokale Verzeichnisse auf dem Photon-Host. Hier werden die WordPress- und SQL-Files abgespeichert. Diese Files \u00fcberleben somit, wenn der container zerst\u00f6rt und neu generiert wird.<\/p>\r\n\r\n\r\n\r\n<p>Die Volumes werden unter<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">cd \/var\/lib\/docker\/volumes<\/pre>\r\n\r\n\r\n\r\n<p>erstellt und bleiben bestehen. Dies solange bis die Volumes mittels<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">docker-compose down -v<\/pre>\r\n\r\n\r\n\r\n<p>zerst\u00f6rt werden.<\/p>\r\n\r\n\r\n\r\n<h3 class=\"wp-block-heading\">WordPress Container starten<\/h3>\r\n\r\n\r\n\r\n<p>Nun kann der Container einfach gestartet werden. Dank Docker Compose braucht man nur noch einen Befehl. Docker Compose erkennt automatisch das YAML im aktuellen Verzeichnis, durchl\u00e4uft die Konfiguration und startet die Container-Anwendung:<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">docker-compose up -d<\/pre>\r\n\r\n\r\n\r\n<p>Den Prozess kann man anzeigen lassen<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">docker ps<\/pre>\r\n\r\n\r\n\r\n<p>Nun ist \u00fcber http:\/\/&lt;ip&gt;:8080 auf die WordPress-Instanz zugegriffen werden.<\/p>\r\n\r\n\r\n\r\n<h3 class=\"wp-block-heading\">WordPress Container mit SSL erweitern<\/h3>\r\n\r\n\r\n\r\n<p>Das so bereitgestellte Container-Image bietet WordPress &#8222;out-of-the-Box&#8220; \u00fcber Port 80 an. Port 443 ist nicht aktiviert. Man geht dabei davon aus, dass die Verschl\u00fcsselung (https) eine zus\u00e4tzliche, neue Funktion darstellt und damit \u00fcber einen weiteren Container abzubilden ist. Dazu kann ein Proxy-Container aufgebaut werden, f\u00fcr den es auch bereits fertige Docker-Images gibt. Architektonisch mag das Sinn machen.<\/p>\r\n\r\n\r\n\r\n<p>Ich m\u00f6chte das aber nicht so umsetzen. Ich betreibe bereits einen Proxy-Server und dieser soll auch so weiter beibehalten werden. Ich verzichte also auf einen Proxy-Container und erweitere das WordPress-Image durch die SSL-Funktionalit\u00e4t. Damit das geht, muss ich das docker-compose.yml bzw. die WordPress-Container Beschreibung erweitern.<\/p>\r\n\r\n\r\n\r\n<p>Als erstes erstelle ich ein zus\u00e4tzliches File<\/p>\r\n\r\n\r\n\r\n<pre class=\"lang:sh decode:true wp-block-preformatted\">vi wordpress\/wp-init.sh<\/pre>\r\n\r\n\r\n\r\n<pre class=\"lang:vim decode:true wp-block-preformatted\">!\/usr\/bin\/env bash\r\napt-get update\r\napt-get install -y --no-install-recommends ssl-cert\r\nrm -r \/var\/lib\/apt\/lists\/*\r\na2enmod ssl\r\na2dissite 000-default.conf\r\na2ensite apache2-vhosts.conf\r\ndocker-entrypoint.sh apache2-foreground<\/pre>\r\n\r\n\r\n\r\n<p>Dieses Bash-Script soll bei jedem Starten des Containers ausgef\u00fchrt werden. Mittels diesem Script wird<br \/>&#8211; SSL nachinstalliert<br \/>&#8211; Die Default Konfig &#8222;000-default.conf&#8220; auf dem Apachen entfernt und stattdessen <br \/>&#8211; eine neue Konfig &#8222;apache2-vhosts.conf&#8220; installiert.<br \/>&#8211; Anschliessend wird der Apache neu gestartet.<\/p>\r\n\r\n\r\n\r\n<p>Damit das Script funktioniert braucht es noch eine Apache-Config. Diese Config wird in den WordPress-Container gemappt und beim Container-Start aktiviert. Damit kann ich von ausserhalb des Containers, die Apache-Config manipulieren:<\/p>\r\n<pre class=\"lang:sh decode:true\">vi wordpress\/apache2-vhosts.conf<\/pre>\r\n\r\n<pre class=\"lang:vim decode:true\">NameVirtualHost * \r\n&lt;VirtualHost *:443&gt; \r\n   ServerName domain.ch \r\n   DocumentRoot \/var\/www\/html\/ \r\n   DirectoryIndex index.php \r\n   Options -Indexes \r\n   SSLEngine On \r\n   SSLCertificateFile \/etc\/ssl\/certs\/ssl-cert-snakeoil.pem \r\n   SSLCertificateKeyFile \/etc\/ssl\/private\/ssl-cert-snakeoil.key \r\n   SSLCACertificateFile \/etc\/ssl\/certs\/ssl-cert-snakeoil.pem \r\n&lt;\/VirtualHost&gt;<\/pre>\r\n<!-- \/wp:post-content -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Nun ist das das docker-compose.yml zu erweitern (siehe die <strong>markierten Erweiterungen<\/strong>):<\/p>\r\n<pre class=\"lang:vim mark:9-10,13,20 decode:true\">version: '3.3'\r\n   services:\r\n   wordpress:\r\n     depends_on:\r\n       - db_node\r\n     image: wordpress:latest\r\n     volumes:\r\n       - wordpress_files:\/var\/www\/html\r\n       - .\/wp-init.sh:\/usr\/local\/bin\/apache2-custom.sh\r\n       - .\/apache2-vhosts.conf:\/etc\/apache2\/sites-available\/apache2-vhosts.conf\r\n     ports:\r\n       - \"8080:80\"\r\n       - \"8443:443\"\r\n     restart: always\r\n     environment:\r\n       WORDPRESS_DB_HOST: db_node:3306\r\n       WORDPRESS_DB_USER: wordpress\r\n       WORDPRESS_DB_PASSWORD: (wordpress db password)\r\n     container_name: wordpress_web\r\n     command: \"bash -c apache2-custom.sh\"\r\n\r\n   db_node:\r\n     image: mysql:5.7\r\n     command: '--default-authentication-plugin=mysql_native_password'\r\n     volumes:\r\n       - db_data:\/var\/lib\/mysql\r\n     ports:\r\n       - 6601:3306\r\n     restart: always\r\n     environment:\r\n       MYSQL_ROOT_PASSWORD: (wordpress root password)\r\n       MYSQL_DATABASE: wordpress\r\n       MYSQL_USER: wordpress\r\n       MYSQL_PASSWORD: (wordpress db password)\r\n     container_name: wordpress_db\r\n     volumes:\r\n       wordpress_files:\r\n       db_data:<\/pre>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Wie man sieht wird <br \/>&#8211; das wp-init.sh Skript in den Container gemappt<br \/>&#8211; Die Apache-Config apache2-vhosts.conf in den Container gemappt.<br \/>&#8211; Der Container um den Port 8443 erweitert, der Container-Intern auf 443 routet und<br \/>&#8211; Das Commando &#8222;bash -c apache2-custom.sh&#8220; bei starten ausgef\u00fchrt.<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Damit startet der Container ab sofort mit aktiviertem SSL und der Apache-Container kann \u00fcber das File apache2-vhosts.conf konfiguriert werden.<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:heading -->\r\n<h3>Reverse Proxy<\/h3>\r\n<!-- \/wp:heading -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Auf dem Reverse-Proxy wird nun einfach eine Reverse-Rule f\u00fcr den Container eingef\u00fchrt. Der Reverse-Proxy leitet die HTTPS-Anfragen intern an den Container-Host mit Port 8443 weiter. Diese kann so aussehen:<\/p>\r\n<pre class=\"lang:vim decode:true  \">&lt;VirtualHost serverIp:80&gt; \r\nServerAdmin info@domain.ch \r\nServerName www.domain.ch \r\nServerAlias domain.ch \r\nRewriteEngine on \r\nReWriteCond %{SERVER_PORT} !^443$ RewriteRule ^\/(.*) https:\/\/www.domain.ch\/$1 [NC,R,L] \r\n&lt;\/VirtualHost&gt;\r\n\r\n&lt;VirtualHost serverIp:443&gt; \r\nServerAdmin info@domain.ch \r\nServerName www.domain.ch \r\n\r\n#aktiviert SSL Unterstuetzung \r\nSSLEngine On \r\nSSLProxyEngine on \r\nSSLProxyVerify none \r\nSSLProxyCheckPeerCN off \r\nSSLProxyCheckPeerName off \r\nSSLProxyCheckPeerExpire off \r\n\r\nSSLCertificateKeyFile \/etc\/letsencrypt\/live\/www.domain.ch\/privkey.pem \r\nSSLCertificateFile \/etc\/letsencrypt\/live\/www.domain.ch\/cert.pem \r\nSSLCertificateChainFile \/etc\/letsencrypt\/live\/www.domain.ch\/chain.pem \r\n\r\n# Regeln zum umleiten auf den internen Server \r\nProxyPreserveHost On \r\nProxyRequests Off \r\nProxyPass \/ https:\/\/www.domain.ch:8443\/ \r\nProxyPassReverse \/ https:\/\/www.domain.ch:8443\/ \r\n\r\nRequestHeader unset Accept-Encoding \r\n\r\nErrorLog \/var\/log\/apache2\/error.log \r\n\r\n# Possible values include: debug, info, notice, warn, error, crit, \r\n# alert, emerg. \r\nLogLevel warn \r\n\r\nCustomLog \/var\/log\/apache2\/access.log combined \r\nServerSignature On \r\n&lt;\/VirtualHost&gt;<\/pre>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:heading -->\r\n<h3>SMTP auf WordPress-Container<\/h3>\r\n<!-- \/wp:heading -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Ich betreibe einen eigenen Mailserver. Ich stellte rasch fest, dass WordPress keine Mails \u00fcber diesen Server versenden kann. Dies, weil das WordPress-Image einerseits grunds\u00e4tzlich keinen SMTP-Agent mit dabei hat und andererseits mein Mailserver auch nicht aus dem Container heraus erreichbar war:<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:list -->\r\n<ul>\r\n<li><a href=\"https:\/\/github.com\/docker-library\/php\/issues\/135\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"https:\/\/github.com\/docker-library\/php\/issues\/135 (\u00f6ffnet in neuem Tab)\">https:\/\/github.com\/docker-library\/php\/issues\/135<\/a><\/li>\r\n<li><a href=\"https:\/\/github.com\/docker-library\/wordpress\/issues\/30\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"https:\/\/github.com\/docker-library\/wordpress\/issues\/30 (\u00f6ffnet in neuem Tab)\">https:\/\/github.com\/docker-library\/wordpress\/issues\/30<\/a><\/li>\r\n<\/ul>\r\n<!-- \/wp:list -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Um das Problem zu l\u00f6sen habe ich mir einfach das Plugin &#8222;WP Mail SMTP&#8220; installiert. Dieses erweitert WordPress um die Mailfunktion. Das Connectivity-Problem konnte ich mit einer einfach Erweiterung von \/etc\/hosts l\u00f6sen:<\/p>\r\n<pre class=\"lang:vim decode:true \">192.168.xx.xx    mx.domain.ch<\/pre>\r\n<p>Man beachte, dass ich die interne IP des Mailservers verwende.<\/p>\r\n<p>Damit diese Erweiterung auch bei einem neuen Create des Containers \u00fcbernommen wird, muss wordpress\/wp-init.sh noch modifiziert werden:<\/p>\r\n<pre class=\"lang:vim mark:3-8 decode:true  \">#!\/usr\/bin\/env bash\r\n\r\n# modify \/etc\/hosts with mx.intelli.ch\r\ncat &gt;&gt; \/etc\/hosts &lt;&lt;-EOF\r\n\r\n\/* mx.intelli.ch *\/\r\n192.168.xx.xx    mx.domain.ch\r\nEOF\r\n\r\napt-get update\r\napt-get install -y  --no-install-recommends ssl-cert   # SSL\r\nrm -r \/var\/lib\/apt\/lists\/*\r\n\r\na2enmod ssl\r\na2dissite 000-default.conf\r\na2ensite apache2-vhosts.conf\r\n\r\n# finally execute default command\r\ndocker-entrypoint.sh apache2-foreground<\/pre>\r\n<h1>Links<\/h1>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:list -->\r\n<ul>\r\n<li><a href=\"https:\/\/docs.docker.com\/compose\/overview\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker-Compose Referenz<\/a><\/li>\r\n<li><a href=\"https:\/\/justthecloud.com\/wordpress-on-photonos-under-docker\/\" target=\"_blank\" rel=\"noreferrer noopener\">WordPress auf Docker<\/a><\/li>\r\n<li><a href=\"https:\/\/gridscale.io\/community\/tutorials\/dockerize-wordpress-docker-compose\/\" target=\"_blank\" rel=\"noreferrer noopener\">WordPress auf Docker 2<\/a><\/li>\r\n<li><a href=\"https:\/\/www.pattonwebz.com\/docker\/multiple-wordpress-containers-proxy\/\" target=\"_blank\" rel=\"noreferrer noopener\">Multiple WordPress on Docker<\/a><\/li>\r\n<li><a href=\"https:\/\/github.com\/docker-library\/wordpress\/issues\/46\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Aktivierung Port 443 auf WordPress-Docker-Image (\u00f6ffnet in neuem Tab)\">Aktivierung Port 443 auf WordPress-Docker-Image<\/a><\/li>\r\n<li><a href=\"https:\/\/github.com\/debtcollective\/docker-wordpress\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Beispiel Image inkl. aktivierten SMTP-Agent (\u00f6ffnet in neuem Tab)\">Beispiel Image inkl. aktivierten SMTP-Agent<\/a><\/li>\r\n<li><a href=\"https:\/\/help.nextcloud.com\/t\/how-to-set-up-sending-emails-in-docker\/35138\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/help.nextcloud.com\/t\/how-to-set-up-sending-emails-in-docker\/35138<\/a><\/li>\r\n<\/ul>\r\n<!-- \/wp:list -->","protected":false},"excerpt":{"rendered":"<p>Dieser Blog-Eintrag beschreibt, wie man auf WordPress auf einem Docker-Host installieren und damit mehrere WordPress-Instanzen auf einem Host betreiben kann.Ich betreibe die Docker-Container hinter einem Proxy-Server, der aber nicht als Container l\u00e4uft. Der Proxy-Server leitet die HTTPS-Requests an die entsprechenden Docker-Container weiter. Dieser Beitrag setzt ein vorinstalliertes Photon 3.0 inkl. Docker und Docker-Compose voraus. Siehe [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"no","_lmt_disable":"","footnotes":""},"categories":[34,32,3,10],"tags":[],"class_list":["post-1044","post","type-post","status-publish","format-standard","hentry","category-apachewebserver","category-docker","category-linux","category-techdocs"],"modified_by":"ralph","_links":{"self":[{"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/posts\/1044","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1044"}],"version-history":[{"count":84,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/posts\/1044\/revisions"}],"predecessor-version":[{"id":1383,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=\/wp\/v2\/posts\/1044\/revisions\/1383"}],"wp:attachment":[{"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dev-metal.ch\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}