使用Docker Compose配置Apache多虚拟主机(FPM)遇404错误求助
解决Apache虚拟主机配置404问题(主站+子路径WordPress)
让我来帮你排查下问题,你的配置里有几个关键问题导致了访问时出现“Not Found”错误,咱们一步步来修正:
1. 核心问题分析
- 重复的ServerName:你创建了两个
VirtualHost都用了www.mysite.com作为ServerName,Apache会优先匹配第一个加载的虚拟主机,导致另一个的规则完全不生效,这是404的主要原因。 - 错误的路径代理逻辑:WordPress FPM容器的根目录是
/var/www/html,但你当前的ProxyPassMatch把/blog/xxx.php代理到了blog:9000/var/www/html/$1,这里的$1是blog/xxx.php,相当于找容器里的/var/www/html/blog/xxx.php,但WordPress的文件都在根目录,自然找不到。 - 过时的Docker Compose语法:
links已经被弃用了,建议用networks来保证服务间的连通性。
2. 修正Docker Compose配置
先更新你的docker-compose.yml,改用networks确保所有服务在同一个网络内,同时完善WordPress的环境变量配置:
version: '3.8' volumes: webroot: dbdata: wpdbdata: networks: app-network: driver: bridge services: server: build: ./docker/apache image: server:latest networks: - app-network ports: - 80:80 - 443:443 volumes: - webroot:/var/www/html/mysite.com # 可选:如果想让Apache直接处理WordPress静态文件,加快速度,添加下面的挂载 # - wp-static:/var/www/html/blog/wp-content fpm: build: ./docker/php image: fpm:latest networks: - app-network depends_on: - database volumes: - webroot:/var/www/html/mysite.com database: build: ./docker/mariadb image: database:latest env_file: - ./docker/mariadb/env networks: - app-network volumes: - dbdata:/var/lib/mysql wpdatabase: image: mysql:latest networks: - app-network volumes: - wpdbdata:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: your-root-password MYSQL_DATABASE: wordpress MYSQL_USER: wordpress-user MYSQL_PASSWORD: wordpress-pass blog: image: wordpress:4.9.1-php7.1-fpm-alpine networks: - app-network depends_on: - wpdatabase environment: WORDPRESS_DB_HOST: wpdatabase:3306 WORDPRESS_DB_USER: wordpress-user WORDPRESS_DB_PASSWORD: wordpress-pass WORDPRESS_DB_NAME: wordpress # 配合上面的可选挂载,把WordPress静态文件共享出来 # volumes: # - wp-static:/var/www/html/wp-content
3. 修正Apache虚拟主机配置
把两个VirtualHost合并成一个,通过路径匹配分别代理主站和/blog的请求,同时处理静态文件和PHP:
<VirtualHost *:80> ServerName www.mysite.com ServerAlias mysite.com ServerAdmin webmaster@localhost DocumentRoot /var/www/html/mysite.com # 处理主站的PHP请求(排除/blog路径) ProxyPassMatch ^/(?!blog)(.*\.php(/.*)?)$ fcgi://fpm:9000/var/www/html/mysite.com/$1 timeout=120 # 方案1:如果挂载了WordPress静态文件,直接让Apache处理 # Alias /blog/wp-content /var/www/html/blog/wp-content # <Directory /var/www/html/blog/wp-content> # Require all granted # Options FollowSymLinks MultiViews # </Directory> # 方案2:如果没挂载静态文件,用反向代理把静态文件请求转发到WordPress容器 ProxyPass /blog/wp-content http://blog:80/wp-content ProxyPassReverse /blog/wp-content http://blog:80/wp-content # 处理/blog路径的PHP请求:把/blog/xxx.php代理到容器的/var/www/html/xxx.php ProxyPassMatch ^/blog/(.*\.php(/.*)?)$ fcgi://blog:9000/var/www/html/$1 timeout=120 # 设置/blog的默认首页 <Location /blog> DirectoryIndex index.php </Location> ErrorLog /usr/local/apache2/logs/error.log CustomLog /usr/local/apache2/logs/access.log combined </VirtualHost>
4. 确保Apache启用必要模块
在你的Apache Dockerfile里,要启用代理相关的模块,否则配置不会生效:
FROM httpd:2.4 RUN apt-get update && apt-get install -y \ libapache2-mod-proxy-html \ libxml2-dev \ && a2enmod proxy proxy_fcgi proxy_http rewrite headers # 复制你的虚拟主机配置到Apache的配置目录 COPY ./vhost.conf /usr/local/apache2/conf/extra/httpd-vhosts.conf # 在主配置里包含虚拟主机配置 RUN echo "Include conf/extra/httpd-vhosts.conf" >> /usr/local/apache2/conf/httpd.conf
5. 配置WordPress站点URL
最后,要确保WordPress知道它的外部访问路径是/blog,可以通过两种方式设置:
- 登录WordPress后台,在「设置」→「常规」里,把「站点地址(URL)」和「WordPress地址(URL)」都改成
http://www.mysite.com/blog。 - 如果暂时无法访问后台,可以在WordPress容器的
wp-config.php里添加:
define('WP_HOME','http://www.mysite.com/blog'); define('WP_SITEURL','http://www.mysite.com/blog');
做完这些后,重启Docker Compose服务,应该就能正常访问主站和/blog路径了。
内容的提问来源于stack exchange,提问作者javal88




