Dockerでsendmailが使える環境構築 [ Nginx-alphine + PHP-alphine (in Postfix)]

2022/06/19

テクノロジー

t f B! P L
eyecatch いつもメールサーバーの設定で時間を取られてしまう、ユゲタです。 WEBサービスを作る時に、メール送信処理は、ほぼほぼ発生します。 そんな時に、当然ですが、DockerでちゃんとセットしていないとPHPのメール機能などは使えません。 今回も3日ほどハマってしまったけど、無事に安定稼働できる構築が完成したので、その内容を備忘録を踏まえてブログに残しておきたいと思います。 ちなみに、webサービスでは、メール送信だけやって、メールの受け取りなどは不要なので、サービスで利用するだけのSMTPサーバーを立ち上げるという内容になります。

構築条件

Dockerで、Nginx + PHPの構成でかなり容量を削減した開発環境を構築していて、以前にブログでも書いた内容です。 Dockerを使って自分のPC内に必要最低限の便利な環境構築をした話(PHP編) この構築したPHP環境を便利に使っていたんですが、PHPのsendmailを機能させたくなりました。 単純にPHPのイメージにPostfixをインストールすればいいかと軽く考えていたんですが、結果的に3日もの時間を要することになるとは・・・ なかなかのトラップがたくさんあった事を事前にお伝えしておきます。 そして、今回の構築しているDockerイメージは全てalpineという容量がかなり軽いモノを使用しているので、他のサイトに書かれているDebianやUbuntuなどの書き方があまり参考にならなかったと言うことも大前提にしておきたいと思います。

main.cfで毎回悩みまくり

sendmailはpostfixでセットしているんですが、他の機能を使ったとしてもだいたいの場合、main.cfというファイルをセットしてメール送信だけするサーバーを構築する事になります。 自分の持っているメールサーバーや、gmailのsmtpにアクセスさせてもいいんですが、今回は、「Mailtrap」という面白いサービスを見つけたので、これを使って見たいと思います。 このMailtrapというサービスは、メール受け取りサービスで、有料版もしっかり用意されていますが、開発で使いやすいように、想定されるあらゆるプログラム言語や環境での設定が、便利に掲載してくれているとても開発よりなサービスなのです。 しかも、smtpのrelayに対応していて、relayされたメールは、送信されずにMailtrapのメールボックスに貯まるため、無駄に外部にメール送信せずに送ったことが確認できるという、 開発でよくある誤送信などが発生しない仕組みが作れる神サービスだったのです。 こりゃあ、WEB開発員なら、使わないといけませんよね。 詳しい使い方は、また別日のブログで解説したいと思うので、今回はDocker設定の説明を進めます。 ちなみに、mail.cfの設定もMailtrapのpostfixという項目に書かれている内容をほぼコピペするだけでいいという事で、アッサリ、サックリ完了してしまいました。

phpイメージのDockerファイル公開

先ほど記述した以前書いたブログの内容に追記した形になりますが、以下のようにDockerfileをセットしました。 FROM php:8.1-fpm-alpine RUN apk update && \ apk add --update --no-cache \ libjpeg-turbo-dev \ libwebp-dev \ libpng-dev RUN docker-php-ext-configure gd --with-jpeg RUN docker-php-ext-install -j$(nproc) gd RUN apk update && \ apk add -u busybox && \ apk add --update --no-cache \ syslog-ng \ cyrus-sasl \ postfix \ vim COPY main.cf /etc/postfix/ COPY sasl_passwd /etc/postfix/ RUN /usr/sbin/postmap /etc/postfix/sasl_passwd COPY entrypoint.sh / ENTRYPOINT ["sh", "/entrypoint.sh"] 下半分のpostfix周辺からそれ以下が今回の追記部分になります。 busyboxはなくても問題ないと思うんですが、syslog-ngは、postfixのmaillogをログ吐き出しするための機能でこれがないと、メールがちゃんと送信されない時に何が原因なのかが話からないため入れています。 軽さにこだわりたい人は、これも外しても問題がなければちゃんと動作します。 cyrus-saslは、smtpは、認証機能が必須なので、relaymする場合にこの機能をいれておかないと正常に動作しませんでした。 このsasl機能を使って、その下でRUNしているのは、Mailtrapからコピーしてきたsasl認証パスワードをdb形式(コンアイはlmdb形式)に変換しています。 毎回変わるものではないので、Dockerfile内で処理するようにしています。 そして、最後に、entrypoint.sh という、起動時に実行する処理を入れて最終的にこれで無事に動作することが確認できました。 他に必要なファイルを列挙しておきます。 #!/bin/ash postfix start # dockerのイメージが、entrypointによって上書きされたので、再実行する . /usr/local/bin/docker-php-entrypoint php-fpm compatibility_level = 3.7 queue_directory = /var/spool/postfix command_directory = /usr/sbin daemon_directory = /usr/libexec/postfix data_directory = /var/lib/postfix unknown_local_recipient_reject_code = 550 smtpd_banner = $myhostname ESMTP $mail_name (alphine) debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5 home_mailbox = Maildir/ mydestination = $myhostname, localhost.$mydomain, localhost sendmail_path = /usr/sbin/sendmail newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq setgid_group = postdrop html_directory = no manpage_directory = /usr/share/man sample_directory = /etc/postfix readme_directory = /usr/share/doc/postfix inet_protocols = ipv4 inet_interfaces = localhost mail_spool_directory = /var/mail debug_peer_level = 2 debug_peer_list = 127.0.0.1 maillog_file = /var/log/maillog.log # SMTPリレーの設定 # ※Mailtrapの設定をコピペ # ※smtp_sasl_password_maps = hash:***** と言う箇所をhash: -> lmdb:に変更 ... php/sasl_passwd ※Mailtrapからコピペ

困難な複数の峠越え

とりあえず、通常webサイトも2日ほどで作ってしまうユゲタがハマッてしまった3日間の軌跡を、ポイントを踏まえて書いておきます。

1日目

postfixインストールをして、main.cfでひたすら悩み、Mailtrapサービスと出会う。 この際、alphineイメージでログ出力がされない件や、各種インストールに必要なモジュールなどを調べ上げました。

2日目

Mailtrapへの繋ぎ込みをひたすら検証。 Dockerコンテナに入り込んで/var/log/maillog.logの確認をしながら、ひたすらmain.cfを更新する作業を続けて、ようやくメール送信ができる状態になる。

3日目

コンテナ立ち上げ時に、postfixがstartできる仕様を盛り込もうと思ってEntrypointを実行したら、nginxイメージで502エラーが出て困っていたら、 どうやら、entrypointを指定した場合、イメージ内で基本的にセットされている起動バッチが正常に動作しないという事が判明。 その為、entrypoint.shの最後に、基本起動する処理を追記して、なんとか正常に立ち上がる状態に持っていく事ができた。 これって、Dockerのバグのようにも感じたので、今後バージョンアップで正常になったら、この点でエラーになる可能性が高いと感じつつも、今の所この方法しかないので、エラーが出た時にまたこのブログを書き直そうと思う。 似たような事で困っている人がこのブログを読むだろうと想定しているが、何かのお役に立てれば幸いです。 他にも似たようなブログで解決しないモノもたくさんあったので、こうした事は自分で調査して認識しておかなければいけないポイントであることも併せて理解してもらうといいかも・・・

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ