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 的架構上,才會展現出優勢。