Docker Compose部署WordPress时自定义主题在WP自动更新后被清空的解决方案咨询
问题描述
我有一个运行在Docker容器里的WordPress站点,遇到了一个棘手的问题:每次WordPress自动更新后,我的自定义主题文件夹都会被清空。
当前配置文件
docker-compose.yml
version: '3.8' services: db: image: mariadb:latest container_name: seaf_db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: ${DB_NAME} MYSQL_USER: ${DB_USER} MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - db_seaf_data:/var/lib/mysql networks: - seaf-backend-wrwmqu wordpress: depends_on: - db build: context: . dockerfile: Dockerfile container_name: seaf_wp restart: unless-stopped environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_NAME: ${DB_NAME} WORDPRESS_DB_USER: ${DB_USER} WORDPRESS_DB_PASSWORD: ${DB_PASSWORD} CACHE_API_URL: ${CACHE_API_URL} CACHE_API_URL_GLOBAL: ${CACHE_API_URL_GLOBAL} CACHE_API_TOKEN: ${CACHE_API_TOKEN} WORDPRESS_CONFIG_EXTRA: | define('WP_MEMORY_LIMIT', '512M'); define('WP_ENVIRONMENT_TYPE', 'production'); define('CACHE_API_URL', $_ENV['CACHE_API_URL'] ?? $_SERVER['CACHE_API_URL'] ?? ''); define('CACHE_API_TOKEN', $_ENV['CACHE_API_TOKEN'] ?? $_SERVER['CACHE_API_TOKEN'] ?? ''); volumes: - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - ./.htaccess:/var/www/html/.htaccess # persistant volume for uploads and plugins - wp_content_seaf_data:/var/www/html/wp-content # custom theme -- tried to remove it and only keep the COPY from Dockerfile to no avail - ./custom-theme:/var/www/html/wp-content/themes/custom-theme:ro ports: - 80 networks: - seaf-backend-wrwmqu volumes: db_seaf_data: wp_content_seaf_data: networks: seaf-backend-wrwmqu: external: true
Dockerfile
FROM wordpress:latest RUN a2enmod rewrite headers COPY uploads.ini /usr/local/etc/php/conf.d/uploads.ini COPY ./custom-theme /var/www/html/wp-content/themes/custom-theme
我试过移除本地主题挂载,只保留Dockerfile里的COPY命令,但问题依然存在。想请教各位:如何既能保留uploads和plugins的持久化卷,又能避免自定义主题在WP自动更新时被清空?
解决方案
嗨,我之前也遇到过完全相同的问题,折腾了好一阵才找到根源——你把整个wp-content目录挂载到了命名卷,而WordPress核心更新时会对wp-content目录执行清理、重置类的操作,这就会牵连到里面的主题目录。哪怕你后来用只读方式挂载了本地主题,也会因为卷挂载的优先级、WP更新的目录操作逻辑导致主题被清空。
下面给你几个可行的解决办法,按推荐度排序:
1. 拆分wp-content的持久化卷(最推荐)
不要把整个wp-content挂载到命名卷,只针对需要持久化的uploads和plugins目录单独挂载卷,让主题目录直接使用容器镜像内的内容(或本地只读挂载)。这样WP更新时只会处理核心文件,完全碰不到你的自定义主题。
修改docker-compose.yml中的volumes部分:
volumes: - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - ./.htaccess:/var/www/html/.htaccess # 仅持久化uploads和plugins,放弃整个wp-content的卷挂载 - wp_uploads_seaf_data:/var/www/html/wp-content/uploads - wp_plugins_seaf_data:/var/www/html/wp-content/plugins # 自定义主题保持本地只读挂载,确保内容不会被容器内操作修改 - ./custom-theme:/var/www/html/wp-content/themes/custom-theme:ro
然后在文件末尾的volumes块中添加这两个新的命名卷:
volumes: db_seaf_data: wp_uploads_seaf_data: wp_plugins_seaf_data:
这个方法我自己一直在用,调整后再也没出现过主题被清空的情况,同时uploads和plugins的数据也能正常持久化。
2. 禁用WordPress主题自动更新(临时应急)
如果暂时不想调整卷配置,可以在wp-config.php中添加配置禁用主题自动更新:
// 禁用所有自动更新(不推荐,会错过核心安全更新) define('AUTOMATIC_UPDATER_DISABLED', true); // 更灵活的配置:保留核心小版本更新和插件更新,仅禁用主题更新 define('WP_AUTO_UPDATE_CORE', 'minor'); add_filter('auto_update_theme', '__return_false');
不过这个办法只适合临时应急,因为长期禁用更新会带来安全风险,尤其是如果你使用第三方主题的话;但如果是完全自定义的主题,倒是可以临时用一下。
3. 将自定义主题固化到镜像中(适合稳定生产环境)
如果你不需要频繁修改主题,可以把主题直接打包进Docker镜像,同时设置好正确的权限,确保WP更新时无法修改主题目录:
FROM wordpress:latest RUN a2enmod rewrite headers COPY uploads.ini /usr/local/etc/php/conf.d/uploads.ini # 复制主题并设置www-data用户权限(WordPress容器的运行用户) COPY ./custom-theme /var/www/html/wp-content/themes/custom-theme RUN chown -R www-data:www-data /var/www/html/wp-content/themes/custom-theme
这个方法的缺点是每次修改主题都要重新构建镜像,不够灵活,适合主题稳定后的生产环境使用。
优先试试第一个方案,应该就能彻底解决你的问题了!
备注:内容来源于stack exchange,提问作者Xanthous

