A hands-on path from your first container image to a Helm-packaged WordPress + MariaDB stack on Kubernetes.
flowchart LR
L0[Lab 0<br/>workstation] --> L1[Lab 1<br/>first image]
L1 --> L2[Lab 2<br/>monolith]
L2 --> L3[Lab 3<br/>two services]
L3 --> L4[Lab 4<br/>Kubernetes]
L4 --> L5[Lab 5<br/>Helm]
By Lab 5 you are running this:
flowchart TB
user[Browser] --> ing[Ingress or Route]
ing --> wp[WordPress<br/>Apache + PHP 8.2<br/>port 8080]
wp --> db[MariaDB 10.5<br/>port 3306]
wp --> up[PVC: uploads]
db --> data[PVC: database]
Images are built by you, from UBI 9, not pulled as a black-box wordpress:latest. That is the point of the workshop.
| Lab | Directory | You do | Time |
|---|---|---|---|
| 0 | labs/lab0 |
Install Docker or Podman (and later kubectl / kind / Helm) | 15–30 min |
| 1 | labs/lab1 |
Build an Apache image, run a local registry | 20–30 min |
| 2 | labs/lab2 |
WordPress and MariaDB in one container (anti-pattern) | 30–40 min |
| 3 | labs/lab3 |
Split them, wire them with Compose | 30–40 min |
| 4 | labs/lab4 |
Same images as Deployments + Ingress on kind / minikube / OpenShift | 40–60 min |
| 5 | labs/lab5 |
Package the app as a Helm chart | 30–40 min |
Each lab directory has its own README with concepts, commands, verification, and troubleshooting. Do them in order. Later labs reuse images from earlier ones.
If you want to skip ahead, the scripts in labs/answers/ replay the mechanical parts:
./labs/answers/complete-lab1.sh
./labs/answers/complete-lab2.sh # optional; Lab 3 does not need the monolith running
./labs/answers/complete-lab3.sh
./labs/answers/complete-lab4.sh
./labs/answers/complete-lab5.shThe path through the labs is: image → monolith → split → orchestrate → package.
Required for Labs 1–3:
- Docker Engine + Compose v2, or Podman 4.x with compose
- Internet access to pull UBI and WordPress (no Red Hat subscription)
Also required for Labs 4–5:
Every docker command in the labs works as podman. Every docker compose works as podman compose.
labs/
lab0/ workstation setup
lab1/ httpd image + registry wrapper
lab2/bigapp/ monolithic WordPress+MariaDB
lab3/ split images + compose.yaml
mariadb/
wordpress/
lab4/k8s/ Kubernetes manifests (Kustomize)
lab5/wordpress/ Helm chart
answers/ skip-ahead scripts
There is no application source beyond the Dockerfiles, start scripts, and cluster YAML. WordPress itself is fetched from wordpress.org at image build time.
- Image names:
workshop/httpd:1.0,workshop/mariadb:1.0,workshop/wordpress:1.0 - HTTP port:
8080in the container, published as host8080in Compose - DB contract:
MARIADB_*on the database image,WORDPRESS_DB_*on the web image (same names the official images use) - Health:
HEALTHCHECKin Dockerfiles for Compose;livenessProbe/readinessProbein Kubernetes - Secrets: Kubernetes
Secretobjects, not plaintext in Deployments (Lab 2/3 still use env vars, which is honest for local Compose)
# Lab 0 — once
docker version && docker compose version
# Lab 1
cd labs/lab1
docker build -t workshop/httpd:1.0 .
docker run --rm -p 8080:8080 workshop/httpd:1.0
# curl http://127.0.0.1:8080/
# Lab 3 (the first “real” app)
cd labs/lab3
docker compose up -d --build
# open http://127.0.0.1:8080/- Default passwords in the labs (
wppassword,rootpassword) are for a laptop workshop. Do not reuse them. - UBI 9’s MariaDB stream is 10.5. PHP is enabled as the
php:8.2module; if a mirror lacks that module, drop thednf module enableline and you get PHP 8.0, which still runs WordPress 7.1. - OpenShift Local is the option if you specifically want
ocand Routes. kind is faster and is what the Lab 4 write-up leads with.
Questions and fixes belong in the lab README you are stuck on — each one has a troubleshooting table.