Tiga Isu, Satu Upgrade
Baru-baru ni aku kena deal dengan tiga isu sekaligus bila upgrade WordPress yang jalan dalam Docker. DNS tak boleh resolve, PHP masih 7.4, dan MySQL auto-upgrade dari 8.0 ke 8.4 yang terus broke database connection.
Aku document semua fix kat sini. Kalau ko hadapi isu sama, harap ni membantu.
Masalah 1: DNS Container Tak Boleh Resolve
Tengok dalam wp-content/debug.log, ada warning macam ni:
translations_api(): WordPress could not establish a secure connection to WordPress.org
Masalah ni biasanya sebab Docker container guna DNS yang salah atau tak configured langsung.
Fix: Set DNS Global untuk Docker
Edit /etc/docker/daemon.json:
{
"dns": ["192.168.1.2", "192.168.1.1"]
}
Tukar IP tu ikut DNS server ko sendiri. Lepas tu restart Docker dan recreate container:
systemctl daemon-reexec
systemctl restart docker
docker-compose down
docker-compose up -d
Masalah 2: PHP Masih Versi 7.4
WordPress tunjuk warning ni:
Your site is running on an outdated version of PHP (7.4.29)...
Sebabnya image dalam docker-compose.yml tak dikunci ke versi PHP terbaru.
Fix: Tukar Image ke PHP 8.3
Dalam docker-compose.yml, tukar baris image:
image: wordpress:php8.3-fpm
Lepas tu pull dan restart:
docker-compose pull
docker-compose up -d
Masalah 3: MySQL Auto-Upgrade Broke Database Connection
Ini yang paling sakit. MySQL Docker auto-upgrade dari 8.0.30 ke 8.4.5, terus WordPress bagi error:
Error establishing a database connection
Log MySQL pula tunjuk dua error ni:
unknown variable 'default-authentication-plugin=mysql_native_password'
Plugin 'mysql_native_password' is not loaded
MySQL 8.4 dah buang sokongan untuk mysql_native_password. Plugin tu deprecated sejak 8.0, dan 8.4 terus remove. Default sekarang ialah caching_sha2_password.
Langkah 1: Buang Config Lama
Dalam docker-compose.yml, buang atau comment out baris ni:
# REMOVE this block:
# command:
# - '--default-authentication-plugin=mysql_native_password'
Langkah 2: Reset Plugin dan Password via Safe Mode
Masuk ke dalam container MySQL, jalankan dalam safe mode:
mysqld --skip-grant-tables --skip-networking --user=mysql &
Lepas tu dalam MySQL CLI, update plugin untuk kedua-dua user:
UPDATE mysql.user
SET plugin = 'caching_sha2_password', authentication_string = ''
WHERE user IN ('root', 'wordpress');
FLUSH PRIVILEGES;
Langkah 3: Set Semula Password
Restart container, masuk semula sebagai user wordpress:
docker exec -it azmidotmy-wp-database mysql -u wordpress
Set password baru dengan betul:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'rootpassword123!';
ALTER USER 'wordpress'@'%' IDENTIFIED BY 'password123!';
Bonus: Kunci Versi Supaya Tak Auto-Upgrade Lagi
Kalau ko biarkan image guna tag latest atau tag minor, ada risiko auto-upgrade berlaku secara senyap. Kunci versi explicit dalam docker-compose.yml:
image: mysql:8.4.5
Buat benda sama untuk WordPress dan PHP. Upgrade manual bila dah ready, bukan bila Docker rasa nak upgrade sendiri.
Ringkasan Fix
- DNS: Tambah
dnsdalam/etc/docker/daemon.json, restart Docker. - PHP: Tukar image ke
wordpress:php8.3-fpm, pull semula. - MySQL 8.4: Buang
default-authentication-plugin, migrate kecaching_sha2_password, set semula password. - Versi: Kunci image tag explicitly. Jangan trust
latest.
Tips Tambahan: Manage Semua Ni dengan Ansible
Kalau ko manage lebih dari satu server WordPress, buat semua benda ni manually setiap kali adalah a waste of time. Ansible boleh automate banyak bahagian ni.
Tip 1: Deploy daemon.json Guna Ansible Template
Jangan hardcode DNS server berbeza-beza kat setiap host manually. Guna template:
# roles/docker/templates/daemon.json.j2
{
"dns": {{ docker_dns_servers | to_json }}
}
# playbook
- name: Configure Docker DNS
template:
src: daemon.json.j2
dest: /etc/docker/daemon.json
notify:
- restart docker
# group_vars/all.yml
docker_dns_servers:
- "192.168.1.2"
- "192.168.1.1"
Senang nak tukar DNS untuk semua host sekaligus. Ubah kat group_vars, run playbook, siap.
Tip 2: Kunci Versi Image dalam Ansible Vars
Daripada edit docker-compose.yml secara manual setiap kali ada upgrade, simpan versi dalam Ansible variables:
# group_vars/wordpress.yml
wp_image: "wordpress:php8.3-fpm"
mysql_image: "mysql:8.4.5"
# roles/wordpress/templates/docker-compose.yml.j2
services:
wordpress:
image: {{ wp_image }}
database:
image: {{ mysql_image }}
Bila nak upgrade, tukar versi kat satu tempat je. Ansible propagate ke semua server yang affected.
Tip 3: Automate MySQL Password Reset dengan Ansible
Proses reset plugin dan password tadi boleh jadi messy kalau buat manually. Ansible ada module community.mysql.mysql_user yang boleh handle ni dengan bersih:
- name: Ensure MySQL user pakai caching_sha2_password
community.mysql.mysql_user:
login_host: 127.0.0.1
login_port: 3306
login_user: root
login_password: "{{ mysql_root_password }}"
name: wordpress
host: "%"
password: "{{ mysql_wp_password }}"
plugin: caching_sha2_password
state: present
update_password: always
Simpan password dalam Ansible Vault, bukan plaintext. Kalau ko belum guna Vault lagi, ini masa yang sesuai nak start.