You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

核心问题分析

  1. 网络连通性缺失:Mailcatcher服务未加入internal网络,导致PHP容器无法通过服务名访问它。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 10:03:09