Proyek ini adalah proyek pertama kita yang tidak menulis satu baris Dockerfile pun. Tiga proyek sebelumnya selalu bermuara pada berkas resep — situs statis dikemas ke image nginx, API Go dikompilasi lewat multi-stage build, service Rust dibangun bertingkat — sementara di sini kedua komponen sudah tersedia sebagai image resmi siap pakai: wordpress:6.8-apache untuk aplikasi lengkap dengan web server-nya, dan mysql:8.4 untuk database. Kecerdasan proyek justru pindah tempat, dari Dockerfile ke compose.yaml: bagaimana dua service dihubungkan, kredensial disuntikkan tanpa bocor ke repositori, data dipersist-kan pada dua volume terpisah, dan urutan penyalaan dijaga sebuah healthcheck. Peran kita berubah dari penulis resep menjadi perancang konfigurasi — keterampilan yang sama pentingnya di dunia nyata, karena mayoritas stack produksi memang dirangkai dari image jadi, bukan dibangun dari nol.
Apa yang Kita Bangun #
Kita berperan sebagai pengelola Toko Kopi Kita, kedai kopi yang ingin punya situs web berisi cerita dan menu tanpa harus memasang PHP, Apache, dan MySQL di mesin host. Stack yang kita bangun memiliki karakter berikut:
- situs WordPress 6.8 yang berjalan utuh dalam container — aplikasi, PHP, dan Apache menyatu dalam satu image resmi, tanpa satu baris
RUNpun kita tulis, - service
dbMySQL 8.4 (seri LTS) yang menyala lebih dulu dan dijaga healthcheckmysqladmin ping, sehingga WordPress tidak pernah menyala menghadapi database yang setengah siap, - dua volume terpisah:
db-datauntuk isi database danwp-contentuntuk tema, plugin, serta unggahan — masing-masing dengan alat backup yang berbeda, - kredensial yang hidup di
.env(disalin dari.env.example), dijaga interpolasi fail-fast${VAR:?pesan}dan.gitignore, sehingga stack menolak menyala bila sandi belum disiapkan, - resep backup dan restore untuk kedua dunia data —
mysqldumpuntuk tabel,taruntuk berkas — yang diuji lewat disaster drill: menghapus seluruh data dengan sadar lalu membangkitkannya kembali dari arsip.
Hasil Akhir dalam Dua Perintah #
Seluruh proyek bermuara pada dua perintah berikut, dijalankan dari dalam folder proyek setelah keempat bagian selesai — di antara keduanya cukup satu penyuntingan kecil untuk mengganti dua sandi di .env:
$ cp .env.example .env
$ docker compose up -dOutput yang Dihasilkan:
[+] Pulling 2/2
✔ db Pulled 21.6s
✔ wordpress Pulled 13.1s
[+] Running 3/3
✔ Network wordpress-dan-mysql_default Created 0.2s
✔ Container wordpress-dan-mysql-db-1 Healthy 11.4s
✔ Container wordpress-dan-mysql-wordpress-1 Started 1.9sBaris Healthy pada db adalah jantung stack ini: Compose menunggu database benar-benar siap — inisialisasi volume pertama memakan 11,4 detik — sebelum menghidupkan WordPress. Setelah kedua container menyala, browser tinggal diarahkan ke localhost:8090, dan wizard instalasi berjalan dalam empat langkah: pilih bahasa, isi judul situs Toko Kopi Kita beserta akun admin budi, klik pasang, lalu masuk ke dashboard. Tidak ada halaman pengisian koneksi database di wizard itu — wp-config.php sudah ditulis otomatis oleh entrypoint image dari variabel WORDPRESS_DB_*, mekanisme yang kita bedah tuntas di Bagian 1.
Tujuan Pembelajaran #
Setelah menyelesaikan proyek ini, kita mampu:
- menyusun stack multi-service yang utuh dari image resmi, tanpa membangun image sendiri,
- menjelaskan mekanisme entrypoint image WordPress yang menerjemahkan
WORDPRESS_DB_*menjadiwp-config.php, - mengelola kredensial dengan pola
.env.example→.env, interpolasi${VAR:?pesan}, dan.gitignore, - merancang healthcheck dengan tanda dolar terpelihara (
$$) serta gerbangdepends_onbertipeservice_healthy, - membedakan volume
wp-contentdandb-data, membuktikan persistensinya, lalu mencadangkan dan memulihkan keduanya lewat disaster drill.
Prasyarat #
Proyek ini tidak memperkenalkan materi baru; ia merangkai yang lama dengan sudut yang berbeda. Tiga section menjadi bekal utama:
- Docker Compose — struktur
compose.yaml,environment,.envuntuk interpolasi,depends_on, dan healthcheck service dari chapter Struktur compose.yaml, Environment dan env File, Variable Interpolation, depends_on dan Startup Order, serta Healthcheck dan Service Readiness, - Penyimpanan Data — konsep persistence dan perilaku volume bernama dari chapter Konsep Persistence dan Volume,
- Docker dan Database — ritual image MySQL, inisialisasi, dan pola backup/restore dari chapter Menjalankan MySQL, Inisialisasi Database, Backup Database, dan Restore Database.
Pastikan juga Docker Engine 29.9.0 dengan plugin Compose v5.6.0 terpasang, koneksi cukup untuk menarik dua image resmi yang berukuran ratusan megabyte, dan tersedia browser — wizard instalasi serta halaman admin WordPress hanya bisa kita jalani lewat browser, bukan lewat curl.
Peta File Proyek #
Struktur lengkap proyek yang kita bangun:
wordpress-dan-mysql/
├── compose.yaml
├── .env.example
├── .gitignore
└── README.mdPeran setiap berkas dan bagian tempat ia lahir:
| Berkas | Peran | Bagian |
|---|---|---|
compose.yaml | Service db (mysql:8.4) dan wordpress (wordpress:6.8-apache), healthcheck, dua volume | Bagian 1 |
.env.example | Template kredensial yang disalin menjadi .env | Bagian 1 |
.gitignore | Menahan .env agar tidak ter-commit | Bagian 1 |
README.md | Ringkasan cara menjalankan, backup, restore, dan disaster drill | — |
Tahapan #
Proyek dikerjakan dalam empat bagian berurutan. Setiap bagian berdiri di atas konfigurasi bagian sebelumnya:
- Bagian 1: Menyiapkan Service —
compose.yamllengkap kedua service, mekanismeWORDPRESS_DB_*menujuwp-config.php,.env.exampledengan gerbang fail-fast, hingga stack pertama menyala dan wizard empat langkah selesai. - Bagian 2: Mengonfigurasi Database — bedah empat variabel
MYSQL_*, healthcheck dengan$$yang dijelaskan tuntas, dan pembuktian least privilege: akun root versus akun aplikasiwordpress. - Bagian 3: Volume dan Persistence — dua volume dipisah, bukti ditanam di kedua dunia (post dan unggahan), diuji dengan siklus
downdanup, lalu diperiksa dari luar lewatdocker volume. - Bagian 4: Backup dan Restore —
mysqldumpdantardijadikan ritual, otomasi cron dan rotasi arsip, lalu disaster drill yang menghapus segalanya dan membangkitkan situs dari dua berkas backup.
Mulailah dari Bagian 1 dan pertahankan urutannya: pembuktian volume di Bagian 3 hanya bermakna bila wizard di Bagian 1 sudah kita lalui, dan disaster drill di Bagian 4 menagih data yang ditanam di Bagian 3.
Referensi #
- WordPress — Docker Hub
— halaman image resmi yang menjadi inti proyek, beserta variabel
WORDPRESS_DB_*dan mekanismewp-config.php. - Docker Compose — Docker Docs — kerangka deklaratif tempat seluruh konfigurasi proyek ini hidup.
Susun compose.yaml WordPress dan MySQL dengan environment dan .env.
Buka → # Bagian 2: Mengonfigurasi DatabasePahami environment MYSQL_*, healthcheck, dan least privilege user.
Buka → # Bagian 3: Volume dan PersistencePisahkan volume wp-content dan db-data lalu buktikan persistensinya.
Buka → # Bagian 4: Backup dan RestoreCadangkan database dan berkas, lalu jalankan disaster drill pemulihan.
Buka → # Buka →Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
compose.yaml
Unduh berkas# WordPress + MySQL: dua service jadi, dua volume, tanpa Dockerfile.
# Nama proyek Compose otomatis diambil dari nama folder karena berkas
# ini sengaja tidak memakai kunci `name:`.
services:
db:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD wajib diisi lewat .env}"
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: "${MYSQL_PASSWORD:?MYSQL_PASSWORD wajib diisi lewat .env}"
volumes:
- db-data:/var/lib/mysql
healthcheck:
# $$ membuat dolar lolos dari interpolasi Compose; shell di dalam
# container yang mengekspansi $MYSQL_ROOT_PASSWORD saat test berjalan.
test: ["CMD-SHELL", "mysqladmin ping -h localhost -p$$MYSQL_ROOT_PASSWORD"]
interval: 3s
timeout: 3s
retries: 20
start_period: 30s
wordpress:
image: wordpress:6.8-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "8090:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: "${MYSQL_PASSWORD:?MYSQL_PASSWORD wajib diisi lewat .env}"
WORDPRESS_DB_NAME: wordpress
volumes:
- wp-content:/var/www/html/wp-content
volumes:
db-data:
wp-content: