我自定义了一个php的dockerfile镜像,启动报错:
FROM php:7.2-apache
RUN docker-php-ext-install mysqli
RUN apt-get update -y && apt-get install -y sendmail libpng-dev
RUN apt-get update &&
apt-get install -y
zlib1g-dev
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install zip
RUN docker-php-ext-install gd
RUN apt-get install -y libxml2-dev
RUN docker-php-ext-install simplexml
RUN a2enmod rewrite
RUN apt-get update && apt-get install -y
libjpeg-dev
libxml2-dev
libmcrypt-dev
libmhash2
libc6
zlib1g
bzip2
&& rm -rf /var/lib/apt/lists/*
&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr
&& docker-php-ext-install gd mysqli opcache soap
docker-compose配置:
version: '3'
services:
my_web:
build: ./php
image: my_web
volumes:
- ./web:/var/www/html/
ports:
- "8080:80"
启动报错为:
AH00534: apache2: Configuration error: More than one MPM loaded.
排查
使用下面命令强制启动镜像:
services:
your_service_name:
image: your_image_name
# ... 其他配置 ...
# 使用这个 command 替换默认的启动命令
command: sleep infinity
使用下面命令进入容器命令行:
docker exec -it my-debug-container bash
使用下面命令诊断:
# 命令一:查看启用了哪些 MPM 模块
ls -l /etc/apache2/mods-enabled/mpm*
# 命令二:在整个 Apache 配置中搜索 MPM 的踪迹
grep -r "mpm_" /etc/apache2/
# 命令三:尝试手动启动 Apache,直接看报错
apache2-foreground
诊断输出:
ls -l /etc/apache2/mods-enabled/mpm*
lrwxrwxrwx 1 root root 32 Mar 27 2019 /etc/apache2/mods-enabled/mpm_event.load ->
../mods-available/mpm_event.load
lrwxrwxrwx 1 root root 34 Mar 27 2019 /etc/apache2/mods-enabled/mpm_prefork.conf
-> ../mods-available/mpm_prefork.conf
lrwxrwxrwx 1 root root 34 Mar 27 2019 /etc/apache2/mods-enabled/mpm_prefork.load
-> ../mods-available/mpm_prefork.load
grep -r "mpm_" /etc/apache2/
/etc/apache2/mods-available/mpm_prefork.load:# Conflicts: mpm_event mpm_worker
/etc/apache2/mods-available/mpm_prefork.load:LoadModule mpm_prefork_module /usr/lib/apache2/modules/mod_mpm_prefork.so
/etc/apache2/mods-available/mpm_prefork.conf:<IfModule mpm_prefork_module>
/etc/apache2/mods-available/mpm_event.conf:<IfModule mpm_event_module>
/etc/apache2/mods-available/mpm_worker.load:# Conflicts: mpm_event mpm_prefork
/etc/apache2/mods-available/mpm_worker.load:LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so
/etc/apache2/mods-available/mpm_event.load:# Conflicts: mpm_worker mpm_prefork
/etc/apache2/mods-available/mpm_event.load:LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so
/etc/apache2/mods-available/mpm_worker.conf:<IfModule mpm_worker_module>
apache2-foreground
AH00534: apache2: Configuration error: More than one MPM loaded.
问题根源分析
从第一个命令输出中,我们找到了罪魁祸首:
ls -l /etc/apache2/mods-enabled/mpm*
lrwxrwxrwx 1 root root 32 Mar 27 2019 /etc/apache2/mods-enabled/mpm_event.load -> ../mods-available/mpm_event.load
lrwxrwxrwx 1 root root 34 Mar 27 2019 /etc/apache2/mods-enabled/mpm_prefork.conf -> ../mods-available/mpm_prefork.conf
lrwxrwxrwx 1 root root 34 Mar 27 2019 /etc/apache2/mods-enabled/mpm_prefork.load -> ../mods-available/mpm_prefork.load
你的 Apache 配置同时启用了 mpm_event 和 mpm_prefork 这两个相互冲突的 MPM。
- mpm_event.load: 这个文件告诉 Apache 去加载 mpm_event 模块。
- mpm_prefork.conf 和 mpm_prefork.load: 这两个文件告诉 Apache 去加载并配置 mpm_prefork 模块。
Apache 启动时,它会读取 mods-enabled 目录下的所有配置文件。当它发现既要加载 mpm_event 又要加载 mpm_prefork 时,就产生了冲突,并报告 AH00534: More than one MPM loaded. 错误。
对于 PHP 的 mod_php(这是 php:7.2-apache 镜像的工作方式),必须使用 mpm_prefork,因为它不是线程安全的。所以,正确的做法是禁用 mpm_event,并确保 mpm_prefork 是唯一启用的 MPM。
最终解决方案:修正启动命令
现在我们知道了确切的问题,就可以制定一个精准的启动命令来修复它。这个命令需要在启动 Apache 之前,禁用掉多余的 mpm_event。
对于 docker run:
请使用这个命令来启动你的容器。它会先用 a2dismod 禁用 mpm_event,然后正常启动 Apache。
docker run ...你的其他参数... 你的镜像名称 /bin/bash -c "a2dismod mpm_event && apache2-foreground"
对于 docker-compose.yml:
在你的 docker-compose.yml 文件中,使用这个 command 指令:
services:
your_service_name:
image: your_image_name
# ... 其他配置 ...
command: /bin/bash -c "a2dismod mpm_event && apache2-foreground"
命令解释:
- a2dismod mpm_event: 这个命令会从 /etc/apache2/mods-enabled/ 目录中移除 mpm_event.conf 和 mpm_event.load 的软链接,从而禁用这个模块。
- &&: 逻辑与操作符。它表示只有在 a2dismod 命令成功执行后,才会继续执行后面的命令。
- apache2-foreground: 在禁用了冲突的模块后,正常启动 Apache。
这个命令直接解决了你诊断出的问题,应该能让你的容器正常启动并运行 Apache 服务了。