Docker で MailHog コンテナを作る方法

この記事は最終更新日から 1年以上 が経過しています。

Docker の PHP コンテナで開発する際に、PHP のメール送信関数 mail() もしくは mb_send_mail() を使うと、エラーが出てしまい困ることがあります。 とはいえ、本物のメールサーバーを用意するわけにもいきません。 開発時にはメールが外部に送信されてしまうと困ります。 メールを外部に送信せずに、メールの動作確認をしたい場合はどのようにすればよいでしょうか。

MailHog とは?

MailHog はテスト用に開発されたメールサーバーです。 Go 言語で実装されています。 本物のメールサーバーのように振舞いながらも、メールを外部には送信しませんので、メールの動作確認をする場合はとても便利です。

mailhog.png

Docker で MailHog コンテナを作る

Docker で MailHog のコンテナを作成してみましょう。

コンテナのイメージは、下記のイメージを使用します。 イメージのバージョン(タグ)は特にこだわりが無ければ最新版(latest)で良いと思います。

MailHog のコンテナの中には、メールを受け取る用の SMTP サーバーと、受け取ったメールの内容を表示するための Web サーバーが含まれています。

MailHog の Web サーバーのコンテナ側のポート番号は 8025 番です。 80 番ではないので注意してください。 ホスト側から Web ブラウザ(Chrome など)で接続できるよう、コンテナ側のポート 8025 番へのマッピングを設定しましょう。 ホスト側のポート番号は、他で使用されていないものなら何番でも良いと思います。

PHP から MailHog コンテナにメールを送る方法は後述します。

例:ホスト側のポート 18025 番と、コンテナ側のポート 8025 番をマッピングする場合
docker-compose.yml
version: "3.8"
services:

  # MailHog コンテナ
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - 18025:8025

データが消えないようにする

MailHog はデフォルトではメモリにメールデータを保存するため、コンテナを再起動すると受け取ったメールが消えてしまいます。 また、Docker がコンテナを再作成したりした場合も同様に、受け取ったメールが消えてしまいます。 MailHog の主な用途は開発時のテストだと思いますので、メールが消えて困る場面は少ないと思うのですが、 メールが消えてしまうと困るという場合は、消えないように設定しましょう。

メールをファイルに保存する

メールが消えないようにするためには、メールをメモリではなくファイルに保存させる必要があります。

なお、現状の MailHog では、メールをファイルに保存するように設定すると、 メールが日付でソートされなくなるバグが存在するので注意してください。 日付でソートされなくなるとメールを探すのがかなりつらくなります。

メールをファイルに保存させるには、環境変数 MH_STORAGEmaildir と指定します。

次に環境変数 MH_MAILDIR_PATH で、保存先のディレクトリを指定します。 書き込み権限が無いとエラーになってしまうので、誰でも書き込める "/tmp" がよく使われているようです。

例:メールをファイルとして "/tmp" ディレクトリに保存する場合
docker-compose.yml
version: "3.8"
services:

  # MailHog コンテナ
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - 18025:8025
    environment:
      MH_STORAGE: maildir
      MH_MAILDIR_PATH: /tmp

ボリュームを使用する

メールをファイルに保存させることでコンテナ再起動時には消えなくなりますが、 それでもまだ Docker がコンテナを再作成すると消えてしまいますので、 コンテナを再作成されても消えないようにボリュームを設定しましょう。

例:名前付きボリューム "mailhog-data" を使用する場合
docker-compose.yml
version: "3.8"
services:

  # MailHog コンテナ
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - 18025:8025
    volumes:
      - mailhog-data:/tmp
    environment:
      MH_STORAGE: maildir
      MH_MAILDIR_PATH: /tmp

volumes:
  mailhog-data:

PHP から MailHog コンテナにメールを送る

MailHog コンテナにメールを送る際は、MailHog コンテナの SMTP サーバーに送る必要があります。 ホスト名として docker-compose.yml で定義しているサービス名(つまり、services 項目で指定しているキー)を使用できます。 上記の例では、ホスト名として "mailhog" が使用できます。 ポート番号は 1025 番です。

PHP でメールを送る際、大きく分けて2つの方法があります。 どちらの方法を使用しているかによって設定方法が異なります。

1つ目は、PHP のメール送信関数 mail() もしくは mb_send_mail() を使用する方法です。 mail() もしくは mb_send_mail() は、 メールを直接メールサーバーに送っているわけではなく、sendmail コマンドにメールを送っています。 実際にメールを送信しているのは sendmail コマンドなのです。 つまり、sendmail コマンドから MailHog コンテナに接続するよう設定しなければなりません。 これがちょっと難しい。 そこで sendmail コマンドの代わりになるコマンド mhsendmail コマンドが用意されていますので、 これを使用すると良いでしょう。

2つ目は、PHP からソケットを開けて直接メールサーバーに接続してメールを送る方法です。 有名なフレームワークやメールライブラリなどは、だいたいこちらの方法でメールを送信しているのではないでしょうか。 こちらの場合は接続先のホストとポート番号を MailHog コンテナの SMTP サーバーに変更するだけなので特に問題はないと思います。

mhsendmail コマンドを使用する

PHP のメール送信関数 mail() もしくは mb_send_mail() を使用している場合は、 mhsendmail コマンドを使用して MailHog コンテナにメールを送信するように変更しましょう。

mhsendmail コマンドをインストールする

mhsendmail コマンドをインストールするには、Dockerfile を下記のように変更します。 なお、これを行うのは PHP が入ってるコンテナであって、MailHog コンテナではないので注意してください。

Dockerfile
FROM php:8.2-apache

# apt を最新化
RUN apt update

# Go 言語 と Git をインストール
# - mhsendmail を go get でインストールするために必要
RUN apt install -y golang-go
RUN apt install -y git

# mhsendmail をインストール
RUN go get github.com/mailhog/mhsendmail \
 && mv /root/go/bin/mhsendmail /usr/local/bin

php.ini の sendmail_path を変更する

mhsendmail コマンドがインストールできたら、次は PHP の設定ファイル php.ini を変更します。

php.ini の sendmail_path の値に、インストールした mhsendmail コマンドを指定します。 --smtp-addr オプションで、MailHog コンテナの SMTP サーバーのホストとポート番号を指定します。

php.ini
[mail function]
sendmail_path="/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"

参考サイト

関連記事

Docker の PHP コンテナで開発する際に、テスト用のメールサーバーを使用すると便利です。メールを外部に送信せずに、メールの動作確認を行うことができます。Mailpit とは?Mailpit はテスト用に開発されたメールサーバーです。Go 言語で実装されています。本物のメールサーバーのように振舞いながらも、メール ...
Docker で開発環境を作るのって結構大変です。構成を気軽に組み替えたりできるため自由度が高いですが、その分必要になる知識も多いですし、必要な作業も多いです。まずは、XAMPP でおなじみの Apache と PHP を組み合わせた Web サーバーを作るところから始めてみましょう。Docker で Apache + ...
Docker は、構成を気軽に組み替えたりできるので、とても便利ですよね。Windows で Docker を使って開発している方も多いと思うのですが、個人的にはどうしても気が乗らない理由がありました。それは処理速度です。遅い。遅すぎる。めちゃくちゃ遅い。つらい。耐えられない。。。ということで調査しました。いろいろと調 ...
最近では、アプリケーションの実行環境の構築に Docker を使うことも珍しくなくなりました。Docker は便利ではあるのかもしれませんが、難しく感じて敬遠されている人もいるのではないでしょうか。その感覚はおそらく間違っていません。実際、知れば知るほど奥が深い技術だと感じてしまいます。もはや沼というか深淵を覗いている ...
XAMPP で開発する際に、PHP のメール送信関数 mail() もしくは mb_send_mail() を使うと、エラーが出てしまい困ることがあります。ちゃんとメールサーバーの設定をすれば良いじゃないかと思うかもですが、メールサーバーを用意するのは面倒ですし、実際にメールが外部に送信されてしまってもそれはそれで困り ...

記事検索

最新記事

人気記事

RSSフィード

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(旧 Twitter) もしくは、お問い合わせより、お願いします。

  • フィードバックの送信が完了しました。