Edited at

dockerコンテナでPHPからのメール送信とhttpsに対応する

Docker を使ってローカル環境をサクッと手元に用意しようとして、

不便(?)だった箇所をどうにかしようと色々試行錯誤したメモです。


環境構成

コンテナはDocker Hubの公式リポジトリから持ってきたPHPとMySQLを使い、

こんな構成にしてみました。


  • Debian 9.5

  • PHP 7.2.11

  • Apache 2.4

  • MySQL 5.7.24


対応したいことがいくつか

公式リポジトリから持ってきたままだと、いくつか不便なところがあったのですが、

今回対応したいのはこれら2つです。


  • PHPからメールが送れない

  • httpsに対応したい(自己署名証明書で良い)


PHPからメール送信

PHP の mail 関数でメールを送ろうとしたら、エラーになってどこにも届かず。。

まぁそりゃそうですよねー。

仕方ないのでSMTPサーバーを立てようかと思いましたが、MailHog が便利そうだったので導入してみました。


導入

こちらの記事を参考にさせてもらいました。

MailHogを利用してメール送信テスト環境をdockerコンテナ上に作る

こちらに書いてあるとおり、docker-compose.yml にコンテナを追加して、build し直すだけで完了します。

簡単ですね。


docker-compose.yml

mailhog:

image: mailhog/mailhog
ports:
- "8025:8025"
- "1025:1025"

しかし、このままでは SMTPサーバーの設定をしてあげないと送信できません。

単純に mail 関数で送りたかったので、もうちょっと調べてみると、sendmail を置き換えるものとして mhsendmail というものが用意されていました。

こちらはビルドされたバイナリがあるので、落とせばそのまま使えそうです。

Dockerfile に下記を追記して、build し直します。


Dockerfile

RUN curl -sSLO https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 \

&& chmod +x mhsendmail_linux_amd64 \
&& mv mhsendmail_linux_amd64 /usr/local/bin/mhsendmail \
&& echo 'sendmail_path = "/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"' > /usr/local/etc/php/conf.d/sendmail.ini

オプションの --smtp-addr= でSMTPサーバーとポートを指定してます。

mailhogdocker-compose.yml で設定しているサービス名です。

では、mail 関数から送ってみます。

mail('test@example.com', 'テストだよ', '届いてるかな?', 'From: from@example.com');

ブラウザで http://localhost:8025/ にアクセスして確認すると、無事に届いていました。

バッチリです。

MailHog.png


メールデータが消えないようにしたい

MailHog は、デフォルトではメールデータをメモリに保存するため、コンテナを停止したり、削除するとデータが消えてしまいます。

そこで、保存先をファイルに変更することで消えないようにします。

環境変数の MH_STORAGEmaildir を指定することでファイルに保存するようにし、

MH_MAILDIR_PATH に保存するディレクトリを設定します。

さらに、volumes の設定で、ローカルの mailhog ディレクトリにファイルを保存するようにしてあげればOKです。


docker-compose.yml

mailhog:

image: mailhog/mailhog
ports:
- "8025:8025"
- "1025:1025"
environment:
MH_STORAGE: maildir
MH_MAILDIR_PATH: /tmp
volumes:
- "./mailhog:/tmp"


httpsへの対応

本番環境は、https であることがデフォルトになりつつあるので、

ローカルで開発する時も https に対応しておきたいなと。

Let's Encrypt なども考えましたが、ローカルですし自己署名で良いかなと。

色々と調べてみましたが、単純に自己署名証明書を作ってあげれば良さそうです。

Dockerfile に下記を追記して、build し直します。


Dockerfile

RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/ssl-cert-snakeoil.key -out /etc/ssl/certs/ssl-cert-snakeoil.pem -subj "/C=AT/ST=Vienna/L=Vienna/O=Security/OU=Development/CN=localhost"

RUN a2enmod rewrite \
&& a2enmod headers \
&& a2ensite default-ssl \
&& a2enmod ssl

自己署名なのでブラウザのエラーは出てしまいますが、無事 https に対応できました!

https.png

さぁ、ここまで出来れば、あとはもう開発するだけです!