Docker环境中PHP mail()结合Mailcatcher无法使用的问题排查
解决Docker Compose环境中PHP mail()函数无法工作的问题
问题背景
使用Docker Compose搭建了包含Nginx、PHP-FPM、MariaDB、Mailcatcher的本地开发环境,其余组件运行正常,但PHP的mail()函数无法正常工作。已尝试修改SMTP配置为localhost/mailcatcher、更换镜像、安装sendmail,均无效果。
现有配置
compose.yaml
version: '3.8' services: nginx: image: nginx:latest ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./html:/var/www/html networks: - internal depends_on: - php php: build: context: . dockerfile: ./php/Dockerfile volumes: - ./html:/var/www/html - ./custom-php.ini:/usr/local/etc/php/conf.d/custom-php.ini environment: PHP_INI_SCAN_DIR: /usr/local/etc/php/conf.d networks: - internal mariadb: image: mariadb:10.4 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: dbname MYSQL_USER: dbuser MYSQL_PASSWORD: dbpassword ports: - "3306:3306" volumes: - mariadb_jazdy_data:/var/lib/mysql networks: - internal mailcatcher: image: sj26/mailcatcher ports: - "1080:1080" - "1025:1025" networks: internal: volumes: mariadb_jazdy_data:
PHP Dockerfile
FROM php:7.4-fpm RUN curl -sSLf \ -o /usr/local/bin/install-php-extensions \ https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \ chmod +x /usr/local/bin/install-php-extensions && \ install-php-extensions mysqli
custom-php.ini
; Enable mysqli extension extension=mysqli.so [mail function] SMTP=127.0.0.1 smtp_port=1025 sendmail_from=sender@example.com
核心问题分析
- 网络连通性缺失:Mailcatcher服务未加入
internal网络,导致PHP容器无法通过服务名访问它。 - Linux环境下PHP mail()的特性:PHP在Linux系统中,
mail()函数默认调用系统的sendmail命令,完全忽略php.ini中的SMTP配置,这是修改SMTP参数无效的根本原因。
解决方案
1. 修复容器网络连通性
修改compose.yaml中mailcatcher服务的配置,将其加入internal网络:
mailcatcher: image: sj26/mailcatcher ports: - "1080:1080" - "1025:1025" networks: - internal
2. 配置邮件转发工具替代sendmail
安装msmtp作为轻量级邮件转发工具,将PHP的mail()调用转发到Mailcatcher:
更新PHP Dockerfile
FROM php:7.4-fpm RUN curl -sSLf \ -o /usr/local/bin/install-php-extensions \ https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \ chmod +x /usr/local/bin/install-php-extensions && \ install-php-extensions mysqli && \ # 安装msmtp并设置为sendmail替代 apt-get update && apt-get install -y --no-install-recommends msmtp && \ rm -rf /var/lib/apt/lists/* && \ ln -sf /usr/bin/msmtp /usr/sbin/sendmail && \ # 配置msmtp默认指向mailcatcher服务 echo "account default host mailcatcher port 1025 from sender@example.com" > /etc/msmtprc
3. 验证并重启服务
- 重新构建PHP镜像:
docker-compose build php - 重启所有服务:
docker-compose up -d - 创建测试脚本
html/test-mail.php:<?php $to = 'test@example.com'; $subject = 'Test Mail'; $message = 'This is a test email from PHP'; $headers = 'From: sender@example.com' . "\r\n" . 'Reply-To: sender@example.com' . "\r\n" . 'X-Mailer: PHP/' . phpversion(); if(mail($to, $subject, $message, $headers)) { echo "Email sent successfully"; } else { echo "Failed to send email"; } ?>
访问http://localhost/test-mail.php,然后打开http://localhost:1080即可在Mailcatcher中查看发送的测试邮件。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

