컨테이너로 올린 WordPress 가 느릴 때 손볼 곳은 대체로 셋이다. PHP 설정(메모리 한도와 OPcache), 웹 서버의 압축·캐시 헤더, 그리고 데이터베이스다. 플러그인 캐시를 붙이기 전에 이 셋을 먼저 맞추는 편이 효과가 크다.
공식 이미지는 웹 서버 조합에 따라 태그가 나뉜다.
| 태그 | 구성 | 쓰는 경우 |
|---|---|---|
wordpress:php8.3-apache |
Apache + mod_php | 단일 컨테이너로 간단히 |
wordpress:php8.3-fpm |
PHP-FPM 만 | 앞단에 Nginx 를 따로 둘 때 |
FPM 조합이 동시 접속이 많을 때 유리하지만, 개인 사이트 수준에서는 Apache 쪽이 구성이 단순해 관리가 쉽다.
환경 변수로 PHP 설정을 주는 방식은 공식 이미지가 보장하지 않는다. PHP_MEMORY_LIMIT 같은 변수는 무시될 수 있으므로 설정 파일을 마운트한다. 공식 이미지는 /usr/local/etc/php/conf.d/ 안의 .ini 를 모두 읽는다.
; uploads.ini
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
services:
wordpress:
image: wordpress:php8.3-apache
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
WORDPRESS_DB_NAME: wp_db
volumes:
- wordpress_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
ports:
- "8080:80"
depends_on:
- db
db:
image: mariadb:11
restart: always
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
MARIADB_DATABASE: wp_db
MARIADB_USER: wp_user
MARIADB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
volumes:
wordpress_data:
db_data:
upload_max_filesize 를 올릴 때는 post_max_size 를 그보다 크거나 같게 둔다. 앞단에 프록시가 있다면 그쪽 본문 크기 한도(Nginx 는 client_max_body_size)도 함께 올려야 실제로 업로드가 된다.
OPcache 의 revalidate_freq 를 크게 잡으면 파일을 바꿔도 반영이 늦다. 테마·플러그인을 자주 고치는 동안에는 작게 두거나 opcache.validate_timestamps=1 인 상태를 유지한다.
Apache 이미지에서 압축과 캐시 헤더를 켜려면 모듈을 활성화한 이미지를 만든다.
FROM wordpress:php8.3-apache
RUN a2enmod rewrite headers expires deflate
.htaccess 에 캐시 만료와 압축을 둔다.
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json
</IfModule>
Nginx 를 앞에 둔다면 정적 파일은 Nginx 가 직접 주고 .php 만 FPM 으로 넘긴다.
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass wordpress:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires max;
log_not_found off;
}
MariaDB 컨테이너에 InnoDB 버퍼 풀을 지정한다. 기본값은 대부분의 환경에서 너무 작다. 호스트 메모리의 절반 정도를 상한으로 보고, 다른 서비스와 공유하는 호스트라면 그보다 낮춘다.
; my.cnf — /etc/mysql/conf.d/ 에 마운트
[mysqld]
innodb_buffer_pool_size = 512M
innodb_flush_log_at_trx_commit = 2
max_connections = 100
innodb_flush_log_at_trx_commit = 2 는 성능을 얻는 대신 OS 가 죽었을 때 최대 1초 분량의 트랜잭션을 잃을 수 있다. 개인 블로그 수준에서는 쓸 만한 교환이지만 업무용 데이터에는 기본값 1 을 유지한다.