Chapter 73: DevOps Projects Part 3: Docker Websites, APIs, Compose, Registry and ECR
73.8 Project 24: WordPress and MySQL with volumes and backups
Friends, WordPress is a common Compose lab. Today we run WordPress with MySQL, keep data in named volumes, prove the install page with curl, and learn a simple volume backup pattern.
मित्रांनो, WordPress सामान्य Compose lab आहे. आज WordPress + MySQL, named volumes, curl ने install page, आणि साधा volume backup.
दोस्तों, WordPress आम Compose lab है. आज WordPress + MySQL, named volumes, curl से install page, और सादा volume backup.
What you will build in this project
- wordpress + mysql services.
- Named volumes for both.
- curl on port 8080.
- mysqladmin ping and backup tip.
1. Start from a real company story
At a Pune media startup, a marketing site ran WordPress in a container with no volume. A recreate wiped two weeks of blog drafts the night before a launch.
The team rebuilt posts by hand. Rough cost: about ₹4 lakh in overtime and delayed ads.
Ravi added named volumes and a nightly volume tar to S3.
Today we practice that WordPress Compose lab.
Ravindra Bagale's Tip
Many students delete volumes with compose down -v by habit. That flag wipes data. Use plain down unless you mean to erase. Keep that habit.
खूप students compose down -v सवयने मारतात. तो flag data पुसतो. जाणूनबुजून erase करत नसल्यास plain down. सवय ठेवा.
बहुत students आदत से compose down -v मारते हैं. वह flag data मिटाता है. जानबूझकर erase न हो तो plain down. आदत रखिए.
2. Start and prepare
Step 1: Write compose
Why: Compose holds WP+DB. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: services wordpress mysql. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 1: dir
Type this:
mkdir -p /tmp/wp && echo ready
You will see:
ready
What it means: Folder.
Example 2: compose
Type this:
printf '%s\n' 'services:' ' db:' ' image: mysql:8.0' ' environment:' ' MYSQL_DATABASE: wordpress' ' MYSQL_USER: wp' ' MYSQL_PASSWORD: wppass' ' MYSQL_ROOT_PASSWORD: rootpass' ' volumes: ["dbdata:/var/lib/mysql"]' ' wordpress:' ' image: wordpress:6.4-php8.2-apache' ' ports: ["8080:80"]' ' environment:' ' WORDPRESS_DB_HOST: db:3306' ' WORDPRESS_DB_USER: wp' ' WORDPRESS_DB_PASSWORD: wppass' ' WORDPRESS_DB_NAME: wordpress' ' volumes: ["wpdata:/var/www/html"]' ' depends_on: [db]' 'volumes:' ' dbdata:' ' wpdata:' > /tmp/wp/compose.yaml && wc -l /tmp/wp/compose.yaml
You will see:
24 /tmp/wp/compose.yaml
What it means: Compose.
Example 3: mode
Type this:
stat -c '%a' /tmp/wp/compose.yaml
You will see:
644
What it means: Safe.
Step 2: Set MySQL env
Why: DB needs user db password. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: MYSQL_* vars. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 4: db img
Type this:
grep mysql /tmp/wp/compose.yaml | head -1
You will see:
image: mysql:8.0
What it means: Pinned.
Example 5: user
Type this:
grep MYSQL_USER /tmp/wp/compose.yaml
You will see:
MYSQL_USER: wp
What it means: User.
Example 6: lab note
Type this:
echo 'Lab passwords only; never reuse in real life'
You will see:
Lab passwords only; never reuse in real life
What it means: Habit.
Step 3: Set WordPress env
Why: WP needs DB host. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: WORDPRESS_DB_*. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 7: host
Type this:
grep WORDPRESS_DB_HOST /tmp/wp/compose.yaml
You will see:
WORDPRESS_DB_HOST: db:3306
What it means: Service DNS.
Example 8: name
Type this:
grep WORDPRESS_DB_NAME /tmp/wp/compose.yaml
You will see:
WORDPRESS_DB_NAME: wordpress
What it means: DB name.
Example 9: img wp
Type this:
grep wordpress: /tmp/wp/compose.yaml | head -1
You will see:
image: wordpress:6.4-php8.2-apache
What it means: Pinned WP.
3. Build the main pieces
Step 4: Named volumes
Why: Volumes keep posts. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: volumes wpdata dbdata. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 10: vols
Type this:
grep -E 'dbdata|wpdata' /tmp/wp/compose.yaml | head -4
You will see:
volumes lines
What it means: Two volumes.
Example 11: why
Type this:
echo 'Without volumes, posts and themes vanish on recreate'
You will see:
Without volumes, posts and themes vanish on recreate
What it means: Reason.
Example 12: ls tip
Type this:
echo 'docker volume ls | grep -E dbdata|wpdata'
You will see:
docker volume ls | grep -E dbdata|wpdata
What it means: Later.
Step 5: Up the stack
Why: up starts both. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: compose up -d. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 13: up
Type this:
cd /tmp/wp && docker compose -f compose.yaml up -d
You will see:
... Started
What it means: Up.
Example 14: ps
Type this:
cd /tmp/wp && docker compose -f compose.yaml ps
You will see:
wordpress ... db ...
What it means: Two.
Example 15: vol
Type this:
docker volume ls | grep -E 'dbdata|wpdata' | wc -l
You will see:
2
What it means: Volumes.
Step 6: Wait healthy
Why: WP needs DB ready. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: sleep + curl. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 16: wait
Type this:
sleep 15; echo waited
You will see:
waited
What it means: MySQL init.
Example 17: ps2
Type this:
cd /tmp/wp && docker compose -f compose.yaml ps --format '{{.Name}} {{.Status}}'
You will see:
... Up ...
What it means: Up.
Example 18: logs db
Type this:
cd /tmp/wp && docker compose -f compose.yaml logs db --tail 2
You will see:
ready for connections
What it means: DB ready.
4. Automate and verify
Step 7: curl install page
Why: Browser path. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: curl :8080. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 19: curl
Type this:
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/
You will see:
200
What it means: Install/UI.
Example 20: title
Type this:
curl -s http://127.0.0.1:8080/ | grep -oi wordpress | head -1
You will see:
WordPress
What it means: Body.
Example 21: port
Type this:
cd /tmp/wp && docker compose -f compose.yaml port wordpress 80
You will see:
0.0.0.0:8080
What it means: Mapped.
Step 8: DB exec
Why: mysql proves data. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: mysql -e. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 22: mysql
Type this:
cd /tmp/wp && docker compose -f compose.yaml exec -T db mysql -uwp -pwppass wordpress -e 'show tables;' 2>/dev/null | head || echo 'empty_or_init'
You will see:
empty_or_init
What it means: OK early.
Example 23: root ping
Type this:
cd /tmp/wp && docker compose -f compose.yaml exec -T db mysqladmin -uroot -prootpass ping
You will see:
mysqld is alive
What it means: Alive.
Example 24: dbs
Type this:
cd /tmp/wp && docker compose -f compose.yaml exec -T db mysql -uroot -prootpass -e 'show databases;' | grep wordpress
You will see:
wordpress
What it means: DB exists.
Step 9: Backup volume tip
Why: Backup before change. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: docker run --volumes-from or volume backup. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 25: backup tip
Type this:
echo 'Backup: docker run --rm -v wp_dbdata:/v -v /tmp:/out alpine tar czf /out/dbdata.tgz -C /v .'
You will see:
Backup: docker run --rm -v wp_dbdata:/v -v /tmp:/out alpine tar czf /out/dbdata.tgz -C /v .
What it means: Pattern.
Example 26: list vol
Type this:
docker volume ls --format '{{.Name}}' | grep dbdata
You will see:
...dbdata
What it means: Name for backup.
Example 27: note
Type this:
echo 'Schedule backups before plugins or upgrades'
You will see:
Schedule backups before plugins or upgrades
What it means: Ops.
5. Harden and accept
Step 10: Logs
Why: Logs show boot. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: compose logs. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 28: logs wp
Type this:
cd /tmp/wp && docker compose -f compose.yaml logs wordpress --tail 3
You will see:
Apache ...
What it means: Boot.
Example 29: follow
Type this:
echo 'docker compose logs -f wordpress'
You will see:
docker compose logs -f wordpress
What it means: Follow.
Example 30: env
Type this:
cd /tmp/wp && docker compose -f compose.yaml exec -T wordpress printenv WORDPRESS_DB_HOST
You will see:
db:3306
What it means: Host.
Step 11: Restart test
Why: Restart must keep data. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: compose restart. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 31: restart
Type this:
cd /tmp/wp && docker compose -f compose.yaml restart && sleep 5 && curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/
You will see:
200
What it means: Survived.
Example 32: vol still
Type this:
docker volume ls | grep -E 'dbdata|wpdata' | wc -l
You will see:
2
What it means: Volumes stay.
Example 33: ps
Type this:
cd /tmp/wp && docker compose -f compose.yaml ps -q | wc -l
You will see:
2
What it means: Two up.
Step 12: Acceptance checklist
Why: Ravi signs off when WP answers and volume survives. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the stack is healthy today.
What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn Compose and registries.
Example 34: http
Type this:
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/
You will see:
200
What it means: Green.
Example 35: alive
Type this:
cd /tmp/wp && docker compose -f compose.yaml exec -T db mysqladmin -uroot -prootpass ping
You will see:
mysqld is alive
What it means: DB.
Example 36: Sign-off
Type this:
echo 'Ravi: PASS'
You will see:
Ravi: PASS
What it means: Done.
Check yourself
Q1. Who fixed the Pune media wipe?
Ravi
Q2. WP host port?
8080
Q3. DB image?
mysql:8.0
Q4. Dangerous compose flag?
down -v
Q5. DB host env?
db:3306
Q6. Backup tool idea?
tar a named volume
Friends, you ran WordPress with durable volumes. Did you understand? Let us try it once more. Take a volume backup tar and restore it into a fresh stack.
मित्रांनो, तुम्ही durable volumes सह WordPress चालवला. volume backup tar घेऊन fresh stack मध्ये restore करा.
दोस्तों, आपने durable volumes के साथ WordPress चलाया. volume backup tar लेकर fresh stack में restore करें.
Lab: try at home
- Write compose with WP and MySQL.
- Up and wait for DB.
- curl the UI.
- mysqladmin ping.
- Practice the volume backup command.
Recap
- WORDPRESS_DB_HOST uses service DNS.
- Named volumes keep posts.
- down -v deletes data.
- Lab passwords are not for production.
- Backup before upgrades.