Docker 中的 WordPress
2018年的時候我就說要容器化了,但是一直沒有做這件事情,最主要的原因是我一直使用FreeBSD 而不是很愛用Linux,這幾天終於完整的把既有環境遷入了docker container,遇到的問題主要有這樣幾個:
1)一些必要的 php-fpm modules 需使用dockerfile compile,這可能會花費一些時間,在第一次運行時。
2)因為我使用php.sock,so both containers need to access /tmp or wherever you put the php.sock,如果您使用port 9000,那就更簡單一些。
3)php-fpm和nginx 的配置文件中需要修改對應的run as user,因為目前大多數的docker images 是使用debian 系統構建的,所以需要修改為www-data user 才不會有file permission 的問題,同時host 上的文件權限也要對應,如何對應呢? 不要費勁去找什麼uid,docker exec -it nginx bash 然後chown -R www-data:www-data /home/www。
4)systemd 啟動文件要手動加一個。
5)wordpress 的wp-config.php 中需要將database host 修改為container name mysql-server,以及 redis object cache 的redis host 需要將其修改為redis 或者valkey container name。
6)php.ini 中如果有使用redis 存儲session 的話,也需要將其修改為redis 或者valkey。
看起來docker 應該在debian 或者ubuntu 上運行是最好的,因為container 內的app 如果需要讀寫host 的文件,通常他們的OS level user 是很容易對齊的,當然,對於那些不需要讀寫host 的micro services 來說,就沒有任何區別。
——
docker-compose.yaml
——
services:
mysql:
image: mysql:8.4
container_name: mysql-server
restart: always
ports:
- "3306:3306"
environment:
- TZ=Asia/Taipei
- MYSQL_ROOT_PASSWORD=password
volumes:
- /var/lib/mysql:/var/lib/mysql
- /etc/my.cnf:/etc/my.cnf
memcached:
image: memcached:latest
container_name: memcached
restart: always
ports:
- "11211:11211"
command: ["memcached", "-m", "8"]
redis:
image: redis:latest
container_name: redis
restart: always
ports:
- "6379:6379"
command: redis-server --maxmemory 8mb --maxmemory-policy allkeys-lru
valkey:
image: valkey/valkey:latest
container_name: valkey
restart: always
ports:
- "6380:6379"
environment:
- VALKEY_EXTRA_FLAGS=--maxmemory 8mb --maxmemory-policy allkeys-lru
redisinsight:
image: redis/redisinsight:latest
container_name: redisinsight
restart: always
ports:
- "5540:5540"
environment:
- TZ=Asia/Taipei
volumes:
- /home/ec2-user/redis-insight:/data
nginx:
image: nginx:latest
container_name: nginx
restart: always
ports:
- "80:80"
- "443:443"
- "3000:3000"
volumes:
- /etc/nginx:/etc/nginx:ro
- /home/www:/home/www
- /tmp:/tmp
environment:
- TZ=Asia/Taipei
php-fpm:
build: .
container_name: php-fpm
restart: always
volumes:
- /home/www:/home/www
- /etc/php/php.ini:/usr/local/etc/php/php.ini
- /etc/php/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf
- /etc/php/php-fpm.d/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf
- /tmp:/tmp
environment:
- TZ=Asia/Taipei
# zabbix-server:
# image: zabbix/zabbix-server-mysql:latest
# container_name: zabbix-server
# restart: always
# ports:
# - "10051:10051"
# environment:
# - TZ=Asia/Taipei
# - ZBX_HOSTNAME=zabbix-server
# - DB_SERVER_HOST=database-mysql.ap-northeast.rds.amazonaws.com
# - DB_SERVER_PORT=3306
# - MYSQL_DATABASE=zabbix
# - MYSQL_PASSWORD=zabbix
# - MYSQL_USER=zabbix
# zabbix-web:
# image: zabbix/zabbix-web-nginx-mysql:latest
# container_name: zabbix-web
# restart: always
# ports:
# - "8080:8080"
# environment:
# - TZ=Asia/Taipei
# - PHP_TZ=Asia/Taipei
# - ZBX_HOSTNAME=zabbix-web
# - ZBX_SERVER_HOST=zabbix-server
# - DB_SERVER_HOST=database-mysql.ap-northeast.rds.amazonaws.com
# - DB_SERVER_PORT=3306
# - MYSQL_DATABASE=zabbix
# - MYSQL_PASSWORD=zabbix
# - MYSQL_USER=zabbix
# zabbix-agent:
# image: zabbix/zabbix-agent2:latest
# container_name: zabbix-agent
# restart: always
# privileged: true
# ports:
# - "10050:10050"
# pid: host
# volumes:
# - /proc:/host/proc:ro
# - /sys:/host/sys:ro
# - /dev:/host/dev:ro
# - /:/host/root:ro
# environment:
# - TZ=Asia/Taipei
# - ZBX_HOSTNAME=Zabbix server
# - ZBX_SERVER_HOST=zabbix-server
# - ZBX_SERVERACTIVE=zabbix-server:10051
# - ZBX_LISTENIP=0.0.0.0
# n8n:
# image: docker.n8n.io/n8nio/n8n
# container_name: n8n
# restart: always
# ports:
# - "5678:5678"
# environment:
# - TZ=Asia/Taipei
# - N8N_SECURE_COOKIE=false
# - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
# volumes:
# - /home/ec2-user/n8ndata:/home/node/.n8n
——
cat dockerfile
——
FROM php:fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
libicu-dev \
libmagickwand-dev \
libgmp-dev \
libxslt1-dev \
libbz2-dev \
libcurl4-openssl-dev \
libxml2-dev \
libsqlite3-dev \
&& rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install -j$(nproc) \
bz2 calendar ctype curl dom exif fileinfo filter ftp gd gettext gmp \
intl mysqli opcache pcntl pdo pdo_mysql pdo_sqlite posix session \
shmop sockets sysvmsg sysvsem sysvshm xml xmlreader xmlwriter xsl zip
RUN pecl install redis igbinary msgpack imagick \
&& docker-php-ext-enable redis igbinary msgpack imagick
——
cat run-docker.sh
——
docker-compose down
sleep 2
docker-compose pull
docker-compose up -d --force-recreate
cat /etc/systemd/system/docker-compose-app.service
[Unit]
Description=Docker Compose Application Service
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/root
ExecStart=/usr/local/bin/docker-compose up -d
ExecStop=/usr/local/bin/docker-compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
——
cat nginx.conf | grep www-data
——
user www-data;
——
cat php-fpm.d/www.conf |grep www-data
——
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
——
wordpress wp-config.php
——
define('WP_REDIS_HOST', 'valkey');
...
define('DB_HOST', 'mysql-server');

但是完成之後,我並沒有想要遷移到Docker ,這種管理一致性對於單個節點的blog 來說並沒有帶來多大的好處。
因為在現代的FreeBSD(以前的不行,repo 裡面的software 都too old)上可以定時pkg upgrade 以達成升級到最新版本組件的目的,而大多數Linux 可以通過dnf-automatic 來自動升級。
一個適用的場景應該是,每一個網站使用不同的容器,可以進行彼此的隔離,還可以對容器的資源使用進行限制,非常適合大家共享一台主機資源的時候。
或者是,多個服務組件在不同的host 上分別部署,互相作為cluster 的節點,只有在cluster 的架構上,才會展現出優勢。










