0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

テスト用のダミーSMTPサーバ smtp4dev をAmazon ECS/Fargateのサービスとして動かしてみた

Posted at

テスト用のダミーSMTPサーバ「smtp4dev」をAWSのマネージドコンテナ環境、ECS/Fargateを使ってサーバーレスで動かします。
サーバーレスで動かすことで、EC2の管理が不要となり、コストも抑えることができます。
メール送信アプリケーションをAWSで開発するときの開発・テストが便利になると思います。

はじめに

本記事はAWSやコンテナについて知識があり、使用経験があるかたを読者として想定しています。
個々のサービスや用語についての説明は割愛しますので、必要に応じてAWSの公式ドキュメントなどを参考に調べていただけるとありがたいです。

実現すること

AWSのプライベートネットワークでsmtp4devをECS/Fargateのサーバーレス環境で動かしテストメールを送信できるようにし、さらにデータの永続化を実現します。

AWSでダミーのSMTPサーバを動かす

SMTPでのメール送信アプリケーションを開発・テストする際に、安全かつ効率的にテストメールを送信するためのダミーの送信先SMTPサーバーとして使用できるsmtp4devというアプリケーションがあります。

Windows、Linux、コンテナなどで動かすことができます。
メールアプリケーションの稼働確認として実際にどのようなメールが送られるのか確認できます。

ECS/Fargateで動かす

smtp4devはEC2で起動するのは容易ですが、さりとてこのためだけにEC2の管理はしたくありません。
コンテナ版smtp4devをECSの単体タスクとして起動することもできますが、SMTPサーバとしてアプリケーションからの通信を受けることになるので、IPアドレスがタスク再起動のたびに変更されるのも使いづらいです。
ですのでコンテナ版をECS/Fargateの「サービス」として動かします。

Amazon ECSについてはこちら

Fargateについてはこちら

インターネット疎通のない「プライベートネットワーク」で動かす

smtp4devのコンテナはDocker Hubにホストされているので、一般的にはインターネットを通じたコンテナイメージの取得が必要です。
しかし今回はセキュリティ関連の要件が厳しくインターネットへの直接疎通が制限された環境を想定し、直接のインターネット疎通のないプライベートネットワークで動かします。

smtp4devのデータをAWSのストレージサービスで永続化する

コンテナのデータは揮発性です。コンテナ内にデータを持つと、smtp4devの設定やメールも再起動で消えてしまいます。
今回はECSで使用できるAWSのストレージサービスを使用して、smtp4devのデータを永続化します。

事前準備

必要なAWS環境を準備します。
使用リージョンはアイルランド(eu-west-1)リージョンです。
※サービス展開が早い傾向があるのでアイルランドを使用しています。別のリージョンでも手順は同じですので、ご自分の環境に合わせて適切なリージョンを選択ください。

VPC/Subnetの作成

まずVPCを作成します。
今回はPublic3つ(-pub)、Private3つ(-prv)の6サブネットを作成しました。

publicサブネットには踏み台サーバを配置します。

image.png

AWSのネットワークについてはこちら

またコンテナに付与するセキュリティグループも作成しておきます。

VPC Endpointの作成

プライベートネットワークでECSタスクを動かすためには、コンテナのPullに使用するECRとS3のエンドポイント、コンテナのログをCloudwatch Logsに送るためのエンドポイントが必要です。

以下のVPC Endpointを作成します。

  • com.amazonaws.eu-west-1.ecr.dkr(Interface)
  • com.amazonaws.eu-west-1.ecr.api(Interface)
  • com.amazonaws.eu-west-1.logs(Interface)
  • com.amazonaws.eu-west-1.s3(Gateway)
    を作成します。

image.png

必要なVPC Endpointについてはこちら

ECSクラスターの作成

ECSのクラスターを作成しておきます。
クラスター名はtstclstr01としました。

image.png

Docker HUBへのECR Pull Through Cacheの設定

Docker Hubからのsmtp4devのコンテナImageの取得をプライベートサブネットで可能にするため、ECRでDocker HubへのPull Through Cacheを設定します。

Pull Through Cacheについてはこちら

ECRのコンソールから以下を選択して設定していきます。

image.png

Pull Through CacheのアップストリームとしてDocker Hubを選択します。

image.png

認証情報としてDocker HubのアカウントとAPIキーを入力します。

image.png

Pull Through Cacheの設定を行います。

image.png

これで、プライベートサブネットから、ECRのVPCエンドポイント経由でDockerHubのイメージが取得できるようになります。

取得する時のコマンドは以下のようになります。
ECRのリポジトリURIにPull Through Cacheで設定したPrefixがついたものになります。
docker pull xxxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/{UpstreamRepositoryName}:{ImageTag}

ロードバランサーとターゲットグループ

smtp4devの起動ガイドにあるように、smtp4devのコンテナのSMTP(25)とHTTP(80)のポートに通信を行うように構成します。

docker run --rm -it -p 5000:80 -p 2525:25 rnwood/smtp4dev

80ポートの通信はsmtp4devのWEB画面にアクセスして、smtp4devの設定やメールの確認のために使用します。

転送先が二つあるので、ターゲットグループも二つ必要なのですが、ECSのサービスはGUIで設定すると1つのサービスに一つのターゲットグループしか定義できません。
そこで、Cloudformationで一つのサービスに複数のターゲットグループを定義する方法をとります。

あらかじめロードバランサーやターゲットグループを定義しておく必要があります。

まずロードバランサーを作成します。
SMTPの通信を受けるためNLBで作成します。
image.png

ターゲットグループをPort 25とPort 80で二つ作成します。
ターゲットタイプはIPで作成し、ターゲットは登録しません。
image.png

Port 25とPort 80のリスナーを作成し、ターゲットグループを登録します。
image.png

設定や受信したメールの永続化

コンテナの場合、タスクが再起動するたびにコンテナのストレージは初期化されるので、受信したテストメールや設定は消えてしまいます。
smtp4devのInstallationガイドによると、/smtp4devというパスに設定等が保存されるとあります。

The folder /smtp4dev will be used for the database and auto-generated TLS certificate. You can mount a directory outside of the container here for peristent storage.

ECSの場合、外部ストレージとしてAWSのストレージサービスであるAmazon EFS(Elastic File system)が使用できます。

EFSについてはこちら

EFSを作成し、永続ストレージとしてコンテナの/smtp4devにマウントします。

EFSを作成します。
image.png

一旦別のEC2からマウントしsmtp4devのデータを保存するパス/smtpdataを作成しておきます。

$ sudo mount -t efs -o tls fs-08d8e02b6fd668856:/ /mnt/efs
$ sudo mkdir /mnt/efs/smtpdata

smtp4dev用タスク定義の作成

ECSのタスク定義を作成します。

タスク定義の名前はdummy-smtp4dev-1としました。
タスク定義では以下を設定します。

起動タイプ

タスクの起動タイプはFargateを指定します。

image.png

イメージURL

コンテナ名はsmtp4devとしました。
イメージURIは事前に作成したPull Through CacheのURLとsmtp4devのリポジトリを指定します。
image.png

コンテナのポート

tcp 25、80を指定します。
image.png

ボリューム

事前に作成したEFSの/smtpdataをコンテナsmtp4dev/smtp4devにマウントするように設定します。
ボリュームを定義します。
image.png

ボリュームをコンテナにマウントします。コンテナパスに/smtp4devを指定します。
image.png

ECSサービスのデプロイ

Cloudformationを使用してサービスを作成します。

Cloudformationコード

サービスの作成には以下のCloudformationテンプレートを使用します。
LoadBalancer以下にコンテナとターゲットグループの組み合わせを複数記載することで、一つのサービスに対して複数のターゲットグループを設定できます。

AWSTemplateFormatVersion: '2010-09-09'
Description: ecs multi tgt svc
Resources:
  service:
    Type: AWS::ECS::Service
    Properties:
      #ECSクラスター名の指定
      Cluster: tstclstr01
      #タスク数は1
      DesiredCount: 1
      #Fargate起動タイプを指定
      LaunchType: FARGATE
      #事前に作成したタスク定義を指定
      TaskDefinition: dummy-smtp4dev-1:1
      #作成するサービス名
      ServiceName: testsvc
      #スケジューラはレプリカを指定
      SchedulingStrategy: REPLICA
      LoadBalancers:
        #事前作成した80ポートと25ポートのターゲットグループのARNを指定
        - ContainerName: smtp4dev
          ContainerPort: 80
          TargetGroupArn: arn:aws:elasticloadbalancing:eu-west-1:xxxxxxxxxxxx:targetgroup/tgt-ecssvc-http/2b53f6a0ff81f3d4
        - ContainerName: smtp4dev
          ContainerPort: 25
          TargetGroupArn: arn:aws:elasticloadbalancing:eu-west-1:xxxxxxxxxxxx:targetgroup/tgt-ecssvc-smtp/139f95508c75ec76
      NetworkConfiguration:
        AwsvpcConfiguration:
          #プライベートネットワークなのでパブリックIPは付与しない。
          AssignPublicIp: DISABLED
          #事前作成したセキュリティグループとサブネットを指定
          SecurityGroups:
            - sg-01bb32c5719e2fbfd
          Subnets:
            - subnet-0b6129430274e59ed
            - subnet-0afecdc596823b4fa
            - subnet-043482be4aaa20168

Cloudformation スタックの作成

マネジメントコンソールからCloudformation テンプレートをデプロイし、サービスを作成します。

以下のように複数ターゲットグループへの割り振りを行うNLBを持ったサービスが作成できました。

image.png

動作確認

WEB設定画面へのアクセス

踏み台EC2のブラウザからNLBのアドレスにアクセスします。
以下のようなsmtp4devのUIが表示されます。
image.png

テストメールの送信

PowerShellのSend-MailMessageを使ってからnlbのDNS名にあててテストメールを送信します。

PS C:\Users\Administrator> $ToADDR   = "to@example.com"
>> $FromADDR = "from@example.com"
>> $SMTPHost   = "testnlb-a8b32e9c0524cf93.elb.eu-west-1.amazonaws.com"
>> $PortNum  = "25"
>> $Subject  = "smtp4dev test"
>> $MailBody  = "test mail"
>>
>> Send-MailMessage -To $ToADDR -From $FromADDR -SmtpServer $SMTPHost -Port $PortNum -Subject "$Subject" -Body $MailBody  -Encoding UTF8

テストメールが送信されました。
image.png

EFSによるデータ永続化の確認

ECSのコンソールからタスクを強制的に終了します。

image.png

ECSのサービスによって別IDのタスクが起動します。
image.png

image.png

テストメールが残っていることが確認できます。
image.png

EFSにはこのようなファイルが作成されていました。

$ ls -l /mnt/efs/smtpdata/
total 4200
-rw-r--r--. 1 root root    1296 Mar 26 05:35 appsettings.json
-rw-r--r--. 1 root root  106496 Mar 28 04:58 database.db
-rw-r--r--. 1 root root   32768 Mar 28 05:08 database.db-shm
-rw-r--r--. 1 root root 4148872 Mar 28 05:08 database.db-wal
-rw-r--r--. 1 root root     748 Mar 26 05:11 selfsigned-certificate.cer
-rw-r--r--. 1 root root    2343 Mar 26 05:11 selfsigned-certificate.pfx
$ 

まとめ

テスト用のダミーSMTPサーバ「smtp4dev」をAWSのマネージドコンテナ環境、ECS/Fargateを使ってサーバーレスで動かすことができました。

動かすために

  • Cloudformationを使った複数ターゲットグループを持つECSサービスの作成
  • プライベートサブネットでのDocker HUBのコンテナの起動
  • EFSを使ったデータの永続化
    を使用しました。

すべての手順が役立つとは限りませんが、この記事の一部でも参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?