Docker Compose untuk PHP, MySQL, dan Redis di Satu Berkas
Compose memudahkan menjalankan beberapa layanan sekaligus, dan sekaligus memudahkan membuat kesalahan yang tidak terlihat sampai data hilang.
Berkas contoh
services:
app:
build: .
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
environment:
DB_HOST: db
REDIS_HOST: cache
volumes:
- ./src:/var/www/html
ports:
- "8080:80"
db:
image: mysql:8.4
command: --default-authentication-plugin=caching_sha2_password
environment:
MYSQL_DATABASE: app
MYSQL_ROOT_PASSWORD: rahasia-lokal
volumes:
- dbdata:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 5s
timeout: 3s
retries: 20
cache:
image: redis:7-alpine
volumes:
- cachedata:/data
volumes:
dbdata:
cachedata:
Tiga hal yang menentukan
Volume bernama, bukan direktori dari host. Baris - dbdata:/var/lib/mysql menyimpan data di volume yang dikelola Docker. Kalau diganti menjadi ./data:/var/lib/mysql tanpa memahami izin berkasnya, MySQL bisa gagal start karena tidak boleh menulis ke direktori itu.
condition: service_healthy, bukan depends_on biasa. depends_on biasa hanya menunggu kontainer berjalan, bukan siap menerima koneksi. MySQL butuh beberapa detik pertama untuk menyiapkan skema, dan aplikasi yang mencoba konek di detik itu akan gagal.
Periksa kesiapan tiap layanan, jangan percaya status "running".
docker compose ps
docker compose exec db mysqladmin ping -h 127.0.0.1 -p
docker compose exec cache redis-cli ping
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/
Membersihkan tanpa menghapus data
docker compose down # hentikan dan hapus kontainer, volume tetap
docker compose down -v # ini yang menghapus volume beserta datanya
Selisih satu huruf itu yang membedakan data tetap ada dan data hilang. Biasakan memakai perintah pertama, dan anggap perintah kedua sebagai tindakan yang perlu disebutkan alasannya.
Catatan untuk pengembangan dan produksi
Susunan di atas untuk pengembangan: kode dari direktori host, port terbuka, kata sandi ada di berkas. Untuk produksi, hal-hal itu dipisahkan: kode dibekukan ke dalam image, port tidak dipublikasikan langsung, dan kata sandi datang dari berkas rahasia atau variabel lingkungan yang tidak ikut masuk ke repositori.