In ons vorige artikel WordPress & Kubernetes: de voordelen hebben we de voordelen beschreven waar je van kunt profiteren als je WordPress op Kubernetes draait. Wil je WordPress op een Kubernetes-omgeving draaien? Dan is het noodzakelijk dat je een image maakt met daarin je WordPress-installatie. Er zijn diverse images in omloop die klaar zijn voor gebruik als je met een lege WordPress-installatie wilt beginnen, maar er zijn vaak veel redenen om een eigen image te bouwen, bijvoorbeeld als onderdeel van je development pipeline. In dit artikel leggen we je uit hoe je een Docker-image met WordPress maakt.

Best practices van WordPress in containers

We zien in de praktijk dat er veel verschillende manieren gebruikt worden om een image met WordPress te maken. Dat komt doordat de manier waarop je een WordPress-image bouwt vaak samenhangt met je deployment proces en met het platform waarop je je WordPress-containers uiteindelijk wilt draaien. Bij het schrijven van deze handleiding nemen we als uitgangspunt dat het image op Kubernetes komt te draaien en dat het image de basis zal vormen voor een schaalbare, high available WordPress-deployment.

Voordat je begint met het maken van een WordPress-image, is het van belang om een aantal aspecten van elkaar te onderscheiden:

  • De WordPress-applicatie zelf
  • Je thema’s en plugins (wp-content/themes en wp-content/plugins)
  • De map wp-content/uploads, die alle media bevat die je hebt geüpload in WordPress.
  • De database waarin onder andere het grootste deel van de instellingen, je berichten, pagina’s en gebruikers staan.

Het onderscheid van deze punten is van belang. De WordPress-core is in iedere WordPress-omgeving identiek en dient niet aangepast te worden. Doe je dat wel, dan krijg je problemen als je WordPress in de toekomst wilt updaten. Doordat de WordPress-core geen eigen code bevat, wordt de core steeds minder vaak onder versiebeheer gebracht maar via composer geinstalleerd of op een andere manier binnengehaald. In deze handleiding halen we de core rechtstreeks van WordPress.org binnen.

Het tweede onderdeel van WordPress dat we onderscheiden zijn de thema’s en plugins. Deze zullen net als de WordPress core in de container gaan draaien. De map uploads zal om een aantal redenen geen onderdeel vormen van je container. In de eerste plaats wil je je container zo klein mogelijkhouden om performance- en schaalbaarheidsredenen. Daarnaast wil je alles dat in je images en containers komt, onder versiebeheer hebben.

In de meeste gevallen staat de map uploads niet onder versiebeheer. Je wilt niet alleen voorkomen dat je eigen code repository outdated is zodra een WordPress-gebruikt een afbeelding upload, maar je wilt de Docker container ook zo klein mogelijk houden voor schaalbaarheids- en performancedoeleinden. Het is gebruikelijk om de uploads-folder als volume te koppelen aan je container of op bijvoorbeeld een S3-bucket te plaatsen in combinatie met een CDN zoals CloudFront.

Het derde punt dat van belang is om te bekijken is de database. Omdat een container op ieder moment vervangbaar moet zijn door een nieuwe container die vanaf je image is opgebouwd, dient je container geen unieke data te bevatten. Een database bevat wel unieke data, bijvoorbeeld de berichten of comments die geplaatst worden. Om die reden wil je je database niet in een reguliere container draaien, maar in een StatefulSet of extern. Daar komen we later in dit artikel op terug.

Dockerfile: de basis van je WordPress image

Een Docker image wordt gemaakt met een Dockerfile waarin je specifieert wel besturingssysteem je wilt gebruiken, welke applicatie moet draaien en welke environment variabelen je meegeeft aan je applicatie. Daarnaast geef je in je dockerfile aan welke volumes gekoppeld moeten worden, welke data je naar je image wilt kopieeren en welke commando’s je wilt uitvoeren voordat de daadwerkelijke WordPress-applicatie wordt gestart.

Er zijn veel bestaande Dockerfiles in omloop, onder andere van WordPress zelf. Het is de moeite waard om op hub.docker.com te kijken of er goede images of herbruikbare Dockerfiles bestaan, voordat je zelf het wiel vanaf het begin opnieuw uitvindt. Voor deze handleiding maken we gebruik van de officiele Dockerfiles van WordPress. De Dockerfiles van WordPress zelf zijn prima als je wilt starten met een nieuwe WordPress-installatie. Wil je een Docker image maken van een bestaande WordPress-installatie, dan kan je dat doen met een kleine aanpassing van de standaard Dockerfile van WordPress. Beide scenarios zullen we beschrijven.

Uitleg van de default Dockerfile van WordPress

Op de Docker Hub-pagina van WordPress vind je diverse Dockerfiles. Je kunt een Dockerfile kiezen op basis van je gewenste WordPress versie, PHP-versie en het gewenste besturingssysteem in de container. De Dockerfiles van WordPress hebben met elkaar gemeen dat ze allemaal een lege installatie van WordPress neerzetten. We zullen de belangrijkste delen van de Dockerfile voor de meest recente versie van WordPress in combinatie met Apache en PHP 7.2 (hier te vinden).  Als we de Dockerfile bekijken, dan zien we globaal een aantal opeenvolgende stappen die uitgevoerd worden:

  • FROM php:7.2-apache: Het base-image van php met de tag 7.2-apache wordt opgehaald en als basis gebruikt voor alle volgende stappen.
  • Na het commando RUN worden de noodzakelijke PHP-extensies geinstalleerd en toegevoegd aan het base-image uit voorgaande stap. (bekijk de relevante regels)
  • In de daaropvolgende RUN-commando’s worden de te gebruiken PHP-instellingen gezet en worden de Apache-modules expires en rewrite geactiveerd. (bekijk de relevante regels)
  • Met de regel VOLUME /var/www/html wordt het volume aangemaakt. De webserver in het image zal de content uit /var/www/html serveren.
  • Vervolgens wordt WordPress gedownload, uitgepakt naar de map /usr/src/wordpress en uitvoerbaar gemaakt. (bekijk de relevante regels)
  • Als alle data correct staat, wordt met de regel ENTRYPOINT [“docker-entrypoint.sh”] het bestand docker-entrypoint.sh uitgevoerd. In dit bestand staan een aantal noodzakelijke commando’s gedefinieerd die uitgevoerd worden voordat je daadwerkelijke applicatie kan starten. Belangrijke, relevante stap voor je begrip van de werking van het image is dat het entrypoint de WordPress-installatie die in bovenstaande stap in /usr/src/wordpress is geplaatst, naar het volume /var/www/html kopieert.
  • Tot slot wordt de webserver gestart met de regel CMD [“apache2-foreground”]. Hiermee start je de Apache-webserver die met voorgaande stappen voor WordPress-geoptimaliseerde instellingen heeft.

De WordPress Dockerfile naar eigen inzicht aanpassen

De Dockerfiles van WordPress zetten een nieuwe, lege WordPress-installatie neer. Dat kan een prima basis zijn om te beginnen, maar het ligt voor de hand dat je een aantal zaken wilt aanpassen. Veel voorkomende aanpassingen/toevoegingen:

  • Je eigen plugins en/of thema’s toevoegen aan het image. In de regel staat je plugins en themas in de directories wp-content/plugins en wp-content/themes, maar er zijn enkele uitzonderingen. Er zijn plugins die in wp-content/ een eigen map aanmaken met configuratiebestanden. Kijk daarom welke bestanden en mappen in jouw situatie aan het image toegevoegd moeten worden.
    • Om de plugins en themes aan het image toe te voegen, kan je onderstaande regels toevoegen aan je Dockerfile Je kunt ze onderaan het bestand plaatsen, net boven de regel die begint met ENTRYPOINT.

      COPY ./wp-content/plugins /usr/src/wordpress/wp-content/plugins
      COPY ./wp-content/themes /usr/src/wordpress/wp-content/themes

  • De configuratie van apache aanpassen, PHP-extensies installeren of Apache-modules activeren:
    • In de meeste gevallen is de standaard-configuratie passend, maar er zijn situaties waarbij je (bijvoorbeeld vanwege WordPress-plugins) aanpassingen wilt in de configuratie van Apache, aanvullende PHP-extensies nodig hebt of extra Apache-modules wilt activeren. De stukken code die we in het vorige hoofdstuk hebben beschreven, kan je natuurlijk naar eigen wens aanpassen.
  • Aanpassingen aan .htaccess doorvoeren -> dit kan je doen in docker-entrypoint.sh
  • Een gedeeld volume koppelen.
    • Als je meerdere replica-containers van je image tegelijkertijd wilt draaien vanwege schaalbaarheid of high-availability, zal een deel van de data gedeeld moeten worden tussen de containers. Bijvoorbeeld de inhoud van de map wp-content/uploads. Als een gebruiker een afbeelding toevoegt aan een bericht of pagina in WordPress, dan moet deze afbeelding immers vanuit iedere container bereikbaar moeten zijn. Daarnaast wil je dat deze afbeelding behouden blijft als je containers herstarten. In de Dockerfile is het volume /var/www/html al aangemaakt. Daarmee ontstaat de mogelijkheid om, zodra je een container op basis van je image start, een extern volume te koppelen. Je kunt een directory buiten de container koppelen aan /var/www/html. Hoe dit werkt valt buiten dit artikel, want dit artikel beperkt zich tot het aanmaken van een WordPress-image.

Wellicht vraag je je af of je niets met de instellingen van wp-config.php dient te doen. Dat hoeft niet. Je wilt namelijk niet hard-coded configuratie in je container plaatsen. Dat zou de beheerbaarheid in het geval je meerdere identieke containers draait niet ten goede komen. Daarnaast het levert een onwerkbare situatie op als je een ontwikkelstraat opzet, waarbij je andere credentials wilt gebruiken voor de ontwikkelomgeving. Zodra je je image uitvoert, kan je environmentvariabelen meegeven voor onder andere de database host, gebruiker en wachtwoord en de database prefix. Het volledige overzicht van opties kan je vinden in de README op Github. De environment variabelen geeft je mee op het moment dat je het image uitrolt dat je in de volgende stap gaat bouwen op basis van je Dockerfile.

WordPress image maken op basis van je Dockerfile

Heb je op met bovenstaande informatie je Dockerfile klaar? Dan kan je daarmee je image met WordPess maken. Zorg dat je Docker hebt geïnstalleerd op voer onderstaande commando uit in de map waar je Dockerfile, het bestand docker-entrypoint.sh en de WordPress-installatie zich bevinden:

docker build -t ‘mijn-wordpress-image’ .

Na het uitvoeren van dit commando worden alle stappen uitgevoerd die je in je Dockerfile hebt gedefinieerd. Zodra dit proces klaar is, staat er een image klaar met alle inhoud van je WordPress-installatie. Dit image kan je op iedere omgeving met Docker en ieder containerplatform uitrollen. Om je image uit te rollen op een andere omgeving dan de omgeving waarop je het image gemaakt hebt, dien je het image naar een image registry te pushen. Vervolgens kan je vanuit iedere omgeving dat image ophalen en uitrollen naar containers.