ECS FargateでPostfixコンテナを動作させてAmazon SESのSMTPインターフェイスへSMTPリレーをしてみた

ECS FargateでPostfixコンテナを動作させてAmazon SESのSMTPインターフェイスへSMTPリレーをしてみた

ECS FargateとPostfixで高信頼なSMTPサーバーを動作させる場合は工夫が必要
2026.03.15

SMTPサーバーの運用負荷を下げたい

こんにちは、のんピ(@non____97)です。

皆さんはSMTPサーバーの運用負荷を下げたいと思ったことはありますか? 私はあります。

AWSで大量のメール配信を行う場合はAmazon SESを使うことが多いでしょう。

Amazon SESではメール送信をする際にSMTPとAPIの2つの方法があります。認証情報の管理やスループットなどの理由から後者が推奨されています。

https://dev.classmethod.jp/articles/amazon-ses-send-v1-v2/

一方、パッケージソフトを導入しているなど、メール配送の仕組みの改修が難しい場合はSMTPインターフェイスの出番です。

このとき、メール配送をしたいクライアント個別にAmazon SESのSMTPユーザーの認証情報を渡すのは運用効率的に難しいことがほとんどです。このような時は別途SMTPサーバー(MTA)を用意する形が取られるでしょう。

そもそもメールクライアントでSMTP-Authをサポートしていないがために、SMTPサーバーを用意することもあるでしょう。

私の体感ではこのSMTPサーバーとしてPostfixを使うことが多いように感じます。冗長化のためにPostfixをインストールしたEC2インスタンスを複数台用意し、NLBで負荷分散するような形です。Amazon SESではないのですが、以下記事のようなイメージです。

https://dev.classmethod.jp/articles/nlb-smtp-gmail/

ただし、EC2インスタンスのOS管理をしたくない方も多くはないでしょうか。可能であれば、コンテナ化してECS Fargateで動かしたい方も多くいると想像します。

ということで実際にECS Fargate上でPostfixを動作させ、Amazon SESのSMTPインターフェイスへSMTPリレーをしてみます。

やってみた

検証環境

検証環境は以下のとおりです。

検証環境.png

Postfixをコンテナ化して、ECS Fargateで動作させています。PostfixコンテナにはNLBを用いて負荷分散しています。

AWS Samplesとして公開されている SES SMTP Relay using AWS Fargate と方向性は同じです。

https://github.com/aws-samples/fargate-ses-relay/tree/main

ただし、今回の構成ではこのAWS Samplesに存在していないEFSがキモです。理由は後述します。Auto ScalingしないEC2インスタンスにPostfixをインストールして動作させるのであれば不要です。

Amazon SES、Secrets Manager、メールクライアントのEC2インスタンス以外のリソースはAWS CDKで構築しています。使用したコードは以下GitHubリポジトリに置いています。

https://github.com/non-97/ecs-fargate-postfix

Amazon SESのIDはwww.non-97.netです。

2.SES ID.png

EFSを配置した理由

EFSを配置した理由はメールのロストを回避するためです。

EFSはdeferedやincomingなど各種メールキューと配信状況レポートの置き場所として使用しています。各キューおよび配信状況レポートの種類は以下のとおりです。

キュー デフォルトのディレクトリ 役割
maildrop /var/spool/postfix/maildrop sendmail コマンド経由で投入されたメールの受付キュー
hold /var/spool/postfix/hold 管理者が意図的に保留したメール
incoming /var/spool/postfix/incoming cleanup デーモンが処理済みのメールを配置
active /var/spool/postfix/active qmgrが現在配送処理中のメール
deferred /var/spool/postfix/deferred 配送に一時的に失敗したメール
corrupt /var/spool/postfix/corrupt 破損して処理できないキューファイル
bounce /var/spool/postfix/bounce バウンスメールのレポート
defer /var/spool/postfix/defer deferred キュー内の各メールに対応する配送失敗理由
trace /var/spool/postfix/trace sendmail -bvETRN による配送経路追跡の結果

参考 : Postfix manual - qmgr(8)

メール配送や一部キューの関係性を簡単に図示すると以下のようになります。

参考 : Postfix Architecture Overview

データプレーンにFargateを使用する場合は、永続化データをどこに置くのかを注意する必要があります。

仮にエフェメラルストレージのみしか使用していない場合、タスクの入れ替えやスケールインなどタスクが削除された際にキュー内のメールがロストしてしまいます。

メール配送の基盤として中々気になります。不安なのであれば大人しくEC2インスタンス上でPostfixを立てた方が良いと思います。

詳細な実装は後述します。

Postfixの起動処理

Postfixを起動させるときの処理について説明をします。

メールをロストしないように以下のような処理を行っています。

No ステップ 処理内容
1 EFSマウント確認 /mnt/efs/postfix の存在を検証
2 flockスロット取得 EFS上のロックファイルに flock -n で排他ロックを実施
メールが残留しているスロットを優先、なければ空きスロットを取得
3 キューディレクトリ初期化 postfix post-install create-missing/var/spool/postfix配下にキューディレクトリ群を作成し、incoming / active / deferredをEFS上のスロットディレクトリへシンボリックリンクで置換
4 リレー許可クライアント設定 S3から取得、またはデフォルト 127.0.0.0/8 を設定
5 Postfix設定 postconf で SMTPリレーやTLS、ログなどを設定
6 SASL認証設定 Secrets Managerに登録されているAmazon SESのSMTPユーザー認証情報から sasl_passwd を生成し postmap でDB化、平文は削除
7 シグナルハンドラ設定 SIGTERM/SIGINT でPostfix停止およびロック解放
8 Postfix起動 postfix start-fg & でバックグラウンド起動、起動完了を最大30秒待機
9 deferredキューフラッシュ postqueue -f で滞留メールをリトライ
10 バックグラウンド監視開始 ヘルスチェック(30秒間隔) + 終了したECSタスクがマウントしていたスロットに残されたメールを回収する処理(300秒間隔)を並行起動し、メインプロセスの終了を wait で待機

各Postfixコンテナのメールキュー用ディレクトリでEFSを単純にマウントするだけでは対策として不十分です。

そもそも、複数のPostfixインスタンスでキューを同時に共有してはいけません。

For the Postfix mail queue, it does not matter how well NFS file locking works. The reason is that you cannot share Postfix queues among multiple running Postfix instances. You can use NFS to switch a Postfix mail queue from one NFS client to another one, but only one NFS client can access a Postfix mail queue at any particular point in time.

For mailbox file sharing with NFS, your options are to use fcntl (kernel locks), dotlock (username.lock files), to use both locking methods simultaneously, or to switch to maildir format. The maildir format uses one file per message and needs no file locking support in Postfix or in other mail software.

Postfix and NFS

こちらの対応として、ECSタスクの最大実行数分、EFS上にメールキュー用のディレクトリを用意し、各ECSタスクからマウントする方式が考えられます。

同じディレクトリをマウントしないようにflockで排他ロックを掛けています。flockは以下記事が参考になりました。

https://qiita.com/ko1nksm/items/f86537f8b533e1ef55c1

NFS上のflockは内部的にfcntlにエミュレートしてくれるためflockのままで問題ありません。

NFS details

Up to Linux 2.6.11, flock() does not lock files over NFS (i.e., the scope of locks was limited to the local system). Instead, one could use fcntl(2) byte-range locking, which does work over NFS, given a sufficiently recent version of Linux and a server which supports locking.

Since Linux 2.6.12, NFS clients support flock() locks by emulating them as fcntl(2) byte-range locks on the entire file. This means that fcntl(2) and flock() locks do interact with one another over NFS. It also means that in order to place an exclusive lock, the file must be opened for writing.

Since Linux 2.6.37, the kernel supports a compatibility mode that allows flock() locks (and also fcntl(2) byte region locks) to be treated as local; see the discussion of the local_lock option in nfs(5).

flock(2) - Linux manual page

これだけの対応で良いかというと、そうではありません。

ここまでの対応だけではメールがロストしないだけでEFS内で漂い続けます。

例を挙げます。Auto Scalingやローリングアップデート、Blue/Green DeploymentなどでECSタスクが最大4つまで同時稼働する可能性があるのであれば、EFS上に以下のようにディレクトリを用意する形になります。

  • /postfix/slot_1
  • /postfix/slot_2
  • /postfix/slot_3
  • /postfix/slot_4

しかし、平常時のタスク起動数が1や2なのであれば、/postfix/slot_3/postfix/slot_4に残っているメールは拾われず配送されません。

そのため、No.10のステップとして終了したECSタスクがマウントしていたスロットに残されたメールを回収する処理を行っています。

また、No.10で行っているヘルスチェックではPostfixのステータスとNFSのマウントポイントにアクセスできるかを確認しています。障害などでEFSが停止している場合にメールをルーティングされ続けないようにするためです。ヘルスチェックに失敗したらSIGTERMでコンテナを停止させます。

なお、Postfix 3.10.8のソースコードを確認したところ、incomingキューにキューファイルを書き込むまでクライアントにACKは返さないような実装にはなっています。そのため、EFSのマウントに失敗しているECSタスクのPostfixコンテナにメールが配送されても、クライアントは気づくことができます。

順序 処理内容 ファイル:行
1 SMTPクライアントからの接続を受け付ける src/smtpd/smtpd.c:5765
2 DATAコマンドを受信し、メール本文の受信を開始する src/smtpd/smtpd.c:3614
3 メール本文を保存するため、incoming キューにファイルを作成する(パーミッション 0600) src/global/mail_stream.c:433
4 ヘッダー整形やアドレス正規化のため、cleanup にメッセージを転送する src/smtpd/smtpd.c:3698
5 メールヘッダーの正規化やアクセス制御のため、cleanup がメッセージを処理する src/cleanup/cleanup_message.c
6 処理済みのメッセージを永続化するため、cleanup がキューファイルに書き込む src/cleanup/cleanup_out.c
7 qmgr が正しくメッセージを扱えるよう、メッセージサイズを確定して書き込む src/cleanup/cleanup_api.c:262
8 ディスク同期に備えて、バッファの内容をカーネルに書き出す src/global/mail_stream.c:296
9 qmgr がこのファイルを処理可能と認識できるよう、パーミッションを 0700 に変更する src/global/mail_stream.c:302
10 障害時のデータ消失を防ぐため、fsyncでカーネルバッファをディスクに同期する src/global/mail_stream.c:304
11 ファイルディスクリプタを解放するため、ファイルを閉じる src/global/mail_stream.c:347
12 配送処理を開始させるため、qmgr に新着メールを通知する src/global/mail_stream.c:368
13 smtpd が応答を返せるよう、cleanup が処理完了を通知する src/cleanup/cleanup.c:628
14 キューへの永続化が完了したことを確認するため、cleanup からの応答を受信する src/global/mail_stream.c:386
15 メールの受領を通知するため、クライアントに "250 OK" を返す src/smtpd/smtpd.c:3869

ちなみに、Postfixコンテナの/var/spool/postfixは以下のようになっています。

$ ls -l /var/spool/postfix
total 28
lrwxrwxrwx    1 postfix  postfix         31 Mar 15 05:55 active -> /mnt/efs/postfix/spool-1/active
lrwxrwxrwx    1 postfix  postfix         31 Mar 15 05:55 bounce -> /mnt/efs/postfix/spool-1/bounce
lrwxrwxrwx    1 postfix  postfix         32 Mar 15 05:55 corrupt -> /mnt/efs/postfix/spool-1/corrupt
lrwxrwxrwx    1 postfix  postfix         30 Mar 15 05:55 defer -> /mnt/efs/postfix/spool-1/defer
lrwxrwxrwx    1 postfix  postfix         33 Mar 15 05:55 deferred -> /mnt/efs/postfix/spool-1/deferred
drwx------    2 postfix  root          4096 Mar  5 00:39 flush
lrwxrwxrwx    1 postfix  postfix         29 Mar 15 05:55 hold -> /mnt/efs/postfix/spool-1/hold
lrwxrwxrwx    1 postfix  postfix         33 Mar 15 05:55 incoming -> /mnt/efs/postfix/spool-1/incoming
lrwxrwxrwx    1 postfix  postdrop        33 Mar 15 05:55 maildrop -> /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    1 root     postfix       4096 Mar 15 05:55 pid
drwx------    1 postfix  root          4096 Mar 15 05:55 private
drwx--x---    1 postfix  postdrop      4096 Mar 15 05:55 public
lrwxrwxrwx    1 postfix  postfix         30 Mar 15 05:55 saved -> /mnt/efs/postfix/spool-1/saved
lrwxrwxrwx    1 postfix  postfix         30 Mar 15 05:55 trace -> /mnt/efs/postfix/spool-1/trace

Postfixのログの整形

記事執筆時点のPostfix 3.10では残念ながら構造化ログを出力することはできません。

構造化ログではない場合、CloudWatch Logsのフィールドインデックスが効かず、トラブル時にメッセージIDやキューIDで検索しようにもクエリ時間もコストもかかります。

今回はAWS FireLens (AWS for Fluent Bit) で整形しました。

Postfixのログの構造は以下のように統一はされていません。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/raw-postfix-log.log

正規表現での表現は限界があったので、Luaスクリプトで処理をしました。

以下のようなプロセスで行っています。

  1. JSON パースをする
    • 成功なら log_type に JSON 内の source フィールドの値を設定
    • source フィールドがない場合は log_type は未設定
  2. syslog パターンにマッチ
    • タイムスタンプを ISO 8601 に変換
    • log_type = "postfix" と判定
    • デーモン固有のパーサーで詳細フィールドを抽出
  3. 1と2のいずれも false なのであれば、log_type = "raw" としてそのまま出力

また、そのままログを流すとNLBのヘルスチェックのログが大量に流れてきます

具体的には以下のようなログが繰り返し流れてきます。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/nlb-healthcheck-postfix-container-log.log

このうち、以下ログは判定しやすいという理由で除外しています。

対象ログ 説明
NOQUEUE lost connection after CONNECT TCP 接続後、サーバーが 220 バナーを送信した後、クライアントが SMTP コマンドを一切送信せずに切断したログ
実質的にヘルスチェックかポートスキャンのみ
disconnect commands=0/0 SMTP コマンドの交換がゼロのまま切断した時のログ

connectのログも除外しようとする場合はNLBのENIのIPアドレスをPostfix側が知っている必要があります。NLBのIPアドレスはALBと異なり、動的に変動しないものとはいえ、管理が手間だと感じたので除外していません。

実際のコードは以下をご覧ください。

なお、本当はFireLensコンテナを自前でビルドせず、initプロセスでLuaスクリプトを渡したかったのですが、initプロセスで指定したものは全てconfigとしてIncludeしてしまうようで、Luaスクリプトを使用する場合は扱えないようでした。残念。

https://github.com/aws/aws-for-fluent-bit/blob/mainline/init/fluent_bit_init_process.go#L246-L262

https://github.com/aws/aws-for-fluent-bit/blob/mainline/init/fluent_bit_init_process.go#L380-L391

initプロセスの説明は以下に記載されています。

How init process works?

  1. The init process will request ECS Task Metadata. Get valuable parts from the responses and set them using export as environment variables.
  2. After you set the ARN or Path of the config files as environment variables in the ECS Task Definition, the init process will collect all config files which you specified (download files which come from S3 if needed).
  3. The init process will create the main config file and use @INCLUDE keyword to add the config file FireLens generated into it.
  4. The init process will process these config files one by one, use @INCLUDE keyword to add config files to the main config file. And the init process will check if each config file is a parser config. If it is a parser config, change the original Fluent Bit command, add -R to specify that parser. For more details, please see the example below.
  5. The init process will finally invoke Fluent Bit with the modified main configuration file.

aws-for-fluent-bit/use_cases/init-process-for-fluent-bit at mainline · aws/aws-for-fluent-bit

Dockerfile

Dockerfileは以下のとおりです。

FROM public.ecr.aws/docker/library/bash:5.2.37-alpine3.22

RUN apk add --no-cache \
      postfix \
      util-linux \
      aws-cli \
      cyrus-sasl \
      cyrus-sasl-login

COPY docker-entrypoint.sh /docker-entrypoint.sh

EXPOSE 25

ENTRYPOINT ["/docker-entrypoint.sh"]

Bashでシェルスクリプトを書いているので、Bashのイメージを使用しています。私がAlpineの標準シェルであるashに慣れ親しんでいないというのもあります。

ちなみにrootユーザー以外で動作できないかも検討したのですが無理でした。Postfixのmain関数UIDが0以外の場合は弾く処理がありました。

src/postfix/postfix.c
/*
  * The mail system must be run by the superuser so it can revoke
  * privileges for selected operations. That's right - it takes privileges
  * to toss privileges.
  */
if (getuid() != 0) {
msg_error("to submit mail, use the Postfix sendmail command");
msg_fatal("the postfix command is reserved for the superuser");
}

メールの配送

実際にメールの配送をしましょう。

EC2インスタンスにmailxをインストールします。

その後、~/.mailrcにNLBのDNS名を指定して、SMTPリレーをさせます。

$ hostname -i
10.0.2.220

$ sudo dnf install mailx
.
.
(中略)
.
.
Installed:
  mailx-12.5-43.amzn2023.0.1.x86_64

Complete!

$ vi ~/.mailrc
$ cat ~/.mailrc
set smtp=smtp://EcsFar-EcsCo-TDpxMt8JmRX7-db95221b13f236ae.elb.us-east-1.amazonaws.com

この状態でメールを配送します。

$ echo "test mail body" \
  | mail \
    -s "test mail subject 1" \
    -r noreply@www.non-97.net <送信先メールアドレ>

メールボックスを確認すると、確かにメール配送されていました。

4.test mail subject 1の詳細.png

3.test mail subject 1.png

このときのCloudWatch Logsに出力されたPostfixのログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/send-mail-postfix-container-log.log

送信元メールアドレスのドメインが許可されたドメイン以外のものを指定した場合

送信元メールアドレスのドメインが許可されたドメイン以外のものを指定した場合の挙動を確認します。

Amazon SESのSMTPインターフェイスへセルフマネージドのSMTPサーバーからSMTPリレーしている環境において、送信元ドメインがAmazon SESに存在しないIDのドメインおよびサブドメインの場合は、以下記事で紹介されているようにSMTPサーバー上でリレー失敗のログは記録されても、メールクライアントはそれを知ることができません。

https://dev.classmethod.jp/articles/amazon-ses-smtp-relay-from-mta-bounce-invalid-id-log/

SMTPサーバーのキューに溜まりっぱなしになるのもよろしくないので、Postfixのcheck_sender_accessでそもそもリレーしないように制御しています。

今回は送信元ドメインをnon-97.netにしました。こちらでメールを送信しようとします。

$ echo "test mail body" \
  | mail \
    -s "test mail subject noreply@non-97.net" \
    -r noreply@non-97.net <送信先メールアドレ>

smtp-server: 554 5.7.1 <noreply@non-97.net>: Sender address rejected: Access denied
"/home/ssm-user/dead.letter" 11/350
. . . message not sent.

拒否されたことが分かります。

このときのCloudWatch Logsに出力されたPostfixのログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/send-not-allowed-domain-mail-postfix-container-log.log

送信元メールアドレスのドメインがFQDN形式ではないものを指定した場合

送信元メールアドレスのドメインがFQDN形式ではないものを指定した場合の挙動も確認します。

Postfixのreject_non_fqdn_senderで制御しています。

$ echo "test mail body" \
  | mail \
    -s "test mail subject noreply@non-97net" \
    -r noreply@non-97net <送信先メールアドレ>

smtp-server: 504 5.5.2 <noreply@non-97net>: Sender address rejected: need fully-qualified address
"/home/ssm-user/dead.letter" 11/347
. . . message not sent.

分かりやすいエラーになりましたね。

このときのCloudWatch Logsに出力されたPostfixのログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/send-reject-non-fqdn-mail-postfix-container-log.log

mynetwork外からメール送信

続いて、mynetwork外からメールを送信する場合です。

mynetwork外のEC2インスタンスからメールを送信しようとします。

$ hostname -i
10.0.3.19

$ echo "test mail body" \
  | mail \
    -s "test mail subject from outside mynetworks" \
    -r noreply@www.non-97.net <送信先メールアドレ>

smtp-server: 554 5.7.1 <<送信先メールアドレス>>: Relay access denied
"/home/ssm-user/dead.letter" 11/363
. . . message not sent.

アクセス拒否されましたね。

このときのログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/send-outside-mynetwork-mail-postfix-container-log.log

ECSタスクの入れ替えが発生した場合もキュー内のメールを再送できるかの確認

まず、Amazon SESのSMTPインターフェイスのVPCエンドポイントのセキュリティグループを変更し、ECSタスクからTCP/587でSMTPリレーできないようにします。

5.SMTPインターフェイスVPCエンドポイントのセキュリティグループルールを変更.png

現在、Postfixのコンテナはそれぞれ1と2のスロットを使用しています。

{
    "ecs_cluster": "EcsFargatePostfixStack-EcsConstructCluster14AE103B-ZkzhWed6B4ZR",
    "ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsFargatePostfixStack-EcsConstructCluster14AE103B-ZkzhWed6B4ZR/72dc511278ea45afa779a82f984646b8",
    "ecs_task_definition": "EcsFargatePostfixStackEcsConstructTaskDef7C428F37:7",
    "log_type": "entrypoint",
    "source": "entrypoint",
    "log_timestamp": "2026-03-14T11:00:29Z",
    "level": "info",
    "slot": "2",
    "container_id": "72dc511278ea45afa779a82f984646b8-3282321826",
    "log": "Acquired slot",
    "container_name": "postfix"
}

{
    "level": "info",
    "container_name": "postfix",
    "container_id": "e3cf6875680342e780ee8421344990d9-3282321826",
    "ecs_cluster": "EcsFargatePostfixStack-EcsConstructCluster14AE103B-ZkzhWed6B4ZR",
    "ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsFargatePostfixStack-EcsConstructCluster14AE103B-ZkzhWed6B4ZR/e3cf6875680342e780ee8421344990d9",
    "ecs_task_definition": "EcsFargatePostfixStackEcsConstructTaskDef7C428F37:7",
    "slot": "1",
    "log": "Acquired slot",
    "log_type": "entrypoint",
    "source": "entrypoint",
    "log_timestamp": "2026-03-14T10:59:56Z"
}

コンテナにECS Execで接続をして現在のメールキューを確認します。

$ ls -l /proc/1/fd/
total 0
lrwx------    1 root     root            64 Mar 14 11:14 0 -> /dev/null
l-wx------    1 root     root            64 Mar 14 11:14 1 -> pipe:[22062]
l-wx------    1 root     root            64 Mar 14 11:14 10 -> /mnt/efs/postfix/.lock-2
l-wx------    1 root     root            64 Mar 14 11:14 2 -> pipe:[22063]
lr-x------    1 root     root            64 Mar 14 11:14 255 -> /docker-entrypoint.sh

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-4
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:12 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:12 /mnt/efs/postfix/spool-2/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-8
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-6
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-2
drwxr-xr-x   12 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/spool-4
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 08:01 /mnt/efs/postfix/spool-4/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 08:01 /mnt/efs/postfix/spool-4/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-5
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-1
drwxr-xr-x   12 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/spool-3
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 10:45 /mnt/efs/postfix/spool-3/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 10:45 /mnt/efs/postfix/spool-3/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/trace
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-3

キュー内にメールは存在していないことが分かります。

それではこの状態でメール送信を2件ほどします。

$ echo "test mail body" \
  | mail \
    -s "relocate mail 1" \
    -r noreply@www.non-97.net <送信先メールアドレ>

$ echo "test mail body" \
  | mail \
    -s "relocate mail 2" \
    -r noreply@www.non-97.net <送信先メールアドレ>

現在のメールキューを確認します。

$ date
Sat Mar 14 11:21:53 UTC 2026

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-4
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/active
-rwx------    1 root     root          1474 Mar 14 11:21 /mnt/efs/postfix/spool-2/active/0833CCDF9EDB97C23F128
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
.
.
(中略)
.
.
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/active
-rwx------    1 root     root          1474 Mar 14 11:21 /mnt/efs/postfix/spool-1/active/8DE35ADBE8D24D3EFFF0C
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-3

$ date
Sat Mar 14 11:22:02 UTC 2026

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-4
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/active
-rwx------    1 root     root          1474 Mar 14 11:21 /mnt/efs/postfix/spool-2/active/0833CCDF9EDB97C23F128
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
.
.
(中略)
.
.drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/active
-rwx------    1 root     root          1474 Mar 14 11:21 /mnt/efs/postfix/spool-1/active/8DE35ADBE8D24D3EFFF0C
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-3

$ date
Sat Mar 14 11:22:09 UTC 2026

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-4
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer/0
-rw-------    1 root     root           338 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer/0/0833CCDF9EDB97C23F128
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/deferred
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/deferred/0
-rwx------    1 root     root          1474 Mar 14 11:27 /mnt/efs/postfix/spool-2/deferred/0/0833CCDF9EDB97C23F128
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
.
.
(中略)
.
.
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/active
-rwx------    1 root     root          1474 Mar 14 11:21 /mnt/efs/postfix/spool-1/active/8DE35ADBE8D24D3EFFF0C
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-3

$ date
Sat Mar 14 11:22:20 UTC 2026

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-4
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer/0
-rw-------    1 root     root           338 Mar 14 11:22 /mnt/efs/postfix/spool-2/defer/0/0833CCDF9EDB97C23F128
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/deferred
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-2/deferred/0
-rwx------    1 root     root          1474 Mar 14 11:27 /mnt/efs/postfix/spool-2/deferred/0/0833CCDF9EDB97C23F128
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
.
.
(中略)
.
.
drwxr-xr-x   12 root     root          6144 Mar 14 06:36 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/defer
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-1/defer/8
-rw-------    1 root     root           338 Mar 14 11:22 /mnt/efs/postfix/spool-1/defer/8/8DE35ADBE8D24D3EFFF0C
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/deferred
drwx------    2 root     postfix       6144 Mar 14 11:22 /mnt/efs/postfix/spool-1/deferred/8
-rwx------    1 root     root          1474 Mar 14 11:27 /mnt/efs/postfix/spool-1/deferred/8/8DE35ADBE8D24D3EFFF0C
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:00 /mnt/efs/postfix/.lock-3

メールがactiveキューからdefferedキューに遷移していくことが分かります。

キューに溜まっているメールを確認します。

/ # postqueue -p
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
0833CCDF9EDB97C23F128     589 Sat Mar 14 11:21:36  noreply@www.non-97.net
(connect to email-smtp.us-east-1.amazonaws.com[10.0.0.229]:587: Operation timed out)
                                         <送信先メールアドレス>

-- 0 Kbytes in 1 Request.

この時、キューID0833CCDF9EDB97C23F128に関するログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/0833CCDF9EDB97C23F128-postfix-container-log.log

それではこのままECSタスクを停止させます。停止はマネジメントコンソールから行いました。

6.タスク停止.png

停止リクエストをして、しばらくすると以下のようにPostfixの停止およびロックの解除が行われていました。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/stop-postfix-container-log.log

新しく起動してきたECSタスクを確認します。

$ ls -l /proc/1/fd/
total 0
lrwx------    1 root     root            64 Mar 14 11:35 0 -> /dev/null
l-wx------    1 root     root            64 Mar 14 11:35 1 -> pipe:[22614]
l-wx------    1 root     root            64 Mar 14 11:35 10 -> /mnt/efs/postfix/.lock-3
l-wx------    1 root     root            64 Mar 14 11:35 2 -> pipe:[22615]
lr-x------    1 root     root            64 Mar 14 11:35 255 -> /docker-entrypoint.sh

$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-4
drwxr-xr-x   10 root     root          6144 Mar 14 11:31 /mnt/efs/postfix/spool-2
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-2/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:31 /mnt/efs/postfix/spool-2/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-2/trace
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-8
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-6
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-2
drwxr-xr-x   12 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/spool-4
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 08:01 /mnt/efs/postfix/spool-4/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 08:01 /mnt/efs/postfix/spool-4/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/defer
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/deferred
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-4/trace
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-5
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-1
drwxr-xr-x   12 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/spool-3
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 11:32 /mnt/efs/postfix/spool-3/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:32 /mnt/efs/postfix/spool-3/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/bounce
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer
drwx------    2 root     postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E
-rw-------    1 root     root           338 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E/EE380F9BA9BBFD0C85874
-rw-------    1 root     root           338 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E/E05BA284CCE58B510C041
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/deferred
drwx------    2 root     postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/deferred/E
-rwx------    1 root     root          1610 Mar 14 11:38 /mnt/efs/postfix/spool-3/deferred/E/EE380F9BA9BBFD0C85874
-rwx------    1 root     root          1610 Mar 14 11:38 /mnt/efs/postfix/spool-3/deferred/E/E05BA284CCE58B510C041
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/trace
drwxr-xr-x   10 root     root          6144 Mar 14 11:31 /mnt/efs/postfix/spool-1
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:21 /mnt/efs/postfix/spool-1/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:30 /mnt/efs/postfix/spool-1/active
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/bounce
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:36 /mnt/efs/postfix/spool-1/trace
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-7
-rw-r--r--    1 root     root             0 Mar 14 11:29 /mnt/efs/postfix/.lock-3

/ # postqueue -p
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
EE380F9BA9BBFD0C85874     725 Sat Mar 14 11:21:36  noreply@www.non-97.net
(connect to email-smtp.us-east-1.amazonaws.com[10.0.0.229]:587: Operation timed out)
                                         <送信先メールアドレス>

E05BA284CCE58B510C041     725 Sat Mar 14 11:21:48  noreply@www.non-97.net
(connect to email-smtp.us-east-1.amazonaws.com[10.0.0.229]:587: Operation timed out)
                                         <送信先メールアドレス>

-- 1 Kbytes in 2 Requests.

先ほどはSlot 1と2にあったメールがSlot 3に移動していることが分かりますね。これはPostfixコンテナが60秒ごとにロックされていない = PostfixコンテナがマウントしていないSlotに残っているメールキューを回収する処理をしているためです。

この時のログは以下のとおりです。

https://github.com/non-97/ecs-fargate-postfix/blob/main/sample-log/orphan-scan-postfix-container-log.log

メールキューを回収して再度キューに投入したのち、pickup → cleanup → qmgr(active) → deffered と遷移していることが分かります。

先ほどはdefferdキューまで移動したものを回収しているような動きだったので、今度はactiveキューのメールを回収できることを確認します。

2つ目のメールを配送したタイミングでkill 1で停止をさせます。

$ echo "test mail body" \
  | mail \
    -s "relocate mail 3" \
    -r noreply@www.non-97.net <送信先メールアドレ>

$ echo "test mail body" \
  | mail \
    -s "relocate mail 4" \
    -r noreply@www.non-97.net <送信先メールアドレ>
$ find /mnt/efs/postfix/ -exec ls -ld {} \;
drwxr-xr-x    6 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/
.
.
(中略)
.
.
drwxr-xr-x   12 root     root          6144 Mar 14 06:51 /mnt/efs/postfix/spool-3
drwxr-xr-x    2 postfix  postdrop      6144 Mar 14 11:32 /mnt/efs/postfix/spool-3/maildrop
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:38 /mnt/efs/postfix/spool-3/incoming
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 11:38 /mnt/efs/postfix/spool-3/active
-rwx------    1 root     root          1473 Mar 14 11:38 /mnt/efs/postfix/spool-3/active/9D2504003182DCDC4FED6
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/bounce
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer
drwx------    2 root     postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E
-rw-------    1 root     root           338 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E/EE380F9BA9BBFD0C85874
-rw-------    1 root     root           338 Mar 14 11:33 /mnt/efs/postfix/spool-3/defer/E/E05BA284CCE58B510C041
drwxr-xr-x    3 postfix  postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/deferred
drwx------    2 root     postfix       6144 Mar 14 11:33 /mnt/efs/postfix/spool-3/deferred/E
-rwx------    1 root     root          1610 Mar 14 11:38 /mnt/efs/postfix/spool-3/deferred/E/EE380F9BA9BBFD0C85874
-rwx------    1 root     root          1610 Mar 14 11:38 /mnt/efs/postfix/spool-3/deferred/E/E05BA284CCE58B510C041
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/saved
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/hold
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/corrupt
drwxr-xr-x    2 postfix  postfix       6144 Mar 14 06:51 /mnt/efs/postfix/spool-3/trace
.
.
(以下略)
.
.

$ kill 1

また、このタイミングでSMTPインターフェイスVPCエンドポイントのセキュリティグループルールを戻し、TCP/587で通信できるようにします。

7.SMTPインターフェイスVPCエンドポイントのセキュリティグループルールを戻す.png

これでしばらく待つとメールが送られてきました。

8.メールが再送されたことを確認.png

ということで、キューに溜まっている未送信のメールも別ECSタスクが収集し送信することが分かりました。

Postfixがメールを受け取ったタイミングでEFSに通信できない場合の挙動の確認

Postfixがメールを受け取ったタイミングでEFSに通信できない場合の挙動の確認をします。

ECSタスクがEFSへ通信できないようにセキュリティグループのルールを変更します。

9.EFSのセキュリティグループ修正.png

その後、コンテナ内で行なっているヘルスチェックによってPostfixのプロセスを停止させる前にメールを送ります。

$ echo "test mail body" \
  | mail \
    -s "down efs mail 1" \
    -r noreply@www.non-97.net <送信先メールアドレ>
$ echo "test mail body" \
  | mail \
    -s "down efs mail 2" \
    -r noreply@www.non-97.net <送信先メールアドレ>
$ echo "test mail body" \
  | mail \
    -s "down efs mail 3" \
    -r noreply@www.non-97.net <送信先メールアドレ>

Unexpected EOF on SMTP connection
Unexpected EOF on SMTP connection
"/home/ssm-user/dead.letter" 11/337
. . . message not sent.
"/home/ssm-user/dead.letter" 11/337
. . . message not sent.
Unexpected EOF on SMTP connection
"/home/ssm-user/dead.letter" 11/337
. . . message not sent.

mailコマンド実行後数秒すると、Unexpected EOF on SMTP connectionとなりました。

デッドレターを確認します。

$ ls -l /home/ssm-user/dead.letter
-rw-------. 1 ssm-user ssm-user 2740 Mar 15 02:29 /home/ssm-user/dead.letter

$ cat /home/ssm-user/dead.letter
Date: Sat, 14 Mar 2026 08:12:17 +0000
From: noreply@non-97.net
To: <送信先メールアドレ>
Subject: test mail subject noreply@non-97.net
Message-ID: <69b51861.cb36E8tLLM583neD%noreply@non-97.net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sat, 14 Mar 2026 08:15:58 +0000
From: noreply@non-97net
To: <送信先メールアドレ>
Subject: test mail subject noreply@non-97net
Message-ID: <69b5193e.xx31YKlgwQs0qM51%noreply@non-97net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sat, 14 Mar 2026 10:43:49 +0000
From: noreply@non-97.net
To: <送信先メールアドレ>
Subject: test mail subject noreply@non-97.net
Message-ID: <69b53be5.GFTYJfWem3dvtMTe%noreply@non-97.net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sat, 14 Mar 2026 11:14:06 +0000
From: noreply@non-97net
To: <送信先メールアドレ>
Subject: test mail subject noreply@non-97net
Message-ID: <69b542fe.5VgfjycqZXZqEeTT%noreply@non-97net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sat, 14 Mar 2026 11:20:23 +0000
From: noreply@www.non-97net
To: <送信先メールアドレ>
Subject: relocate mail 1
Message-ID: <69b54477.1bZPoQONOYTHRk6Q%noreply@www.non-97net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sun, 15 Mar 2026 02:28:18 +0000
From: noreply@www.non-97.net
To: <送信先メールアドレ>
Subject: down efs mail 1
Message-ID: <69b61942.uUMYNMIkK5gjtKxW%noreply@www.non-97.net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sun, 15 Mar 2026 02:28:52 +0000
From: noreply@www.non-97.net
To: <送信先メールアドレ>
Subject: down efs mail 3
Message-ID: <69b61964.qRy/6EB9i/or9+Xw%noreply@www.non-97.net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body
Date: Sun, 15 Mar 2026 02:28:38 +0000
From: noreply@www.non-97.net
To: <送信先メールアドレ>
Subject: down efs mail 2
Message-ID: <69b61956.RJ5fY4aQkZoaDoIM%noreply@www.non-97.net>
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

test mail body

先ほど送信したもの含めて送信失敗したものを確認できました。

ということで、EFSがダウンしている場合はPostfixへのSMTPリレーが失敗し、ユーザー側でも気づくことができることが分かりました。

ECS FargateとPostfixで高信頼なSMTPサーバーを動作させる場合は工夫が必要

ECS FargateでPostfixコンテナを動作させてAmazon SESのSMTPインターフェイスへSMTPリレーをしてみました。

ECS FargateとPostfixで高信頼なSMTPサーバーを動作させる場合は工夫が必要です。正直EC2インスタンスよりも気にしなければならない要素が多いので、シンプルにEC2インスタンスを複数台用意し、NLBで負荷分散する方法が良いなと感じました。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!

この記事をシェアする

FacebookHatena blogX

関連記事