Dockerを利用したメールサーバ構築


# 目的と本ドキュメントの位置づけ
- Dockerを使ってメールサーバを構築する
- メールボックスやログなどをコンテナに置くと大変なので、そのあたりにも配慮する。
- 今回はまずテストドメインで構築を行い、その後現在運用しているサーバを移設する。

# 構成
- 構成は下記のようになるものとする。
![mail.jpg](https://qiita-image-store.s3.amazonaws.com/0/99704/3fe1f14a-da6b-b57b-1f22-922df65d40c2.jpeg "構成イメージ")

- メールサーバはSMTP, IMAP同居でDockerコンテナ上に実装。
- Dockerコンテナにメールボックスを置くわけにはいかなかったので、NFSサーバを用意した。
- 本来NFSは別サーバにしたかったが、予算の都合上、Dockerが稼働するUbuntu上で立ち上げた。
	- Elastic File Systemも試してみたかったけど、米国しかないので断念。
	- 本当はS3をマウントしてメールボックスにしたかったが、うまくいかなかったので、今回は断念した。
- Dockerコンテナにログを置くわけにもいかなかったので、fluentdを経由してS3に投げ込む構成とした。
- ちなみにDocker Containerで動いているのはUbuntu 14.04, Dockerが動いているのもUbuntu 14.04。

# 実装
## 本ドキュメントの範囲

本ドキュメントで記載する範囲は下記の通りとする。

- 本構成におけるDocker上にメールサーバを構築する場合の注意点
	- NFSマウントの仕方、とか
- fluentdの設定
	- あまりやったことがなかったので

## 本ドキュメントの範囲外

下記については詳しいサイトがたくさんあるので、ここでは言及しないものとする。

- AWSの構成の仕方
- メールサーバのコンフィグ例
- NFSサーバのコンフィグ例

## Docker ContainerからNFSのマウント
- 何も考えずにdocker runしてしまうとpermission deniedになる。
- 下記のようにprivilegedオプションを追記して起動する。

```bash
docker run --privileged=true -p 25:25 -p 143:143 -it ContainerImage bash
```

- 通常のdocker runではデバイスファイルなど、ホスト側へのアクセスを制限している。
- privilegedオプションを利用すると、ホスト側へのアクセスも行えるようになり、Operation Not Permitted問題が出なくなる。
- ただし、これによりセキュリティ上のリスクが発生するので、よく考えて使うこと。
- 実際にはもっと少ない範囲の権限に狭めることも可能そうだが、いまのところその解答はわかっていないので、調査でき次第追記する。

## fluentdを使ってpostfix/dovecotのログをS3に貯めこむ
### td-agentのインストール
- インストールは下記公式ドキュメントを読めばよくわかるので、そちらを参照のこと。
- http://docs.fluentd.org/articles/install-by-deb

### S3 pluginの導入
- 導入も設定も下記を読めばよくわかるが念のため書いておく
- http://docs.fluentd.org/articles/out_s3

- インストールは下記

```bash
fluent-gem install fluent-plugin-s3
```

- td-agent.confの設定。
- sourceの部分は下記サイオステクノロジー様のサイト丸コピーでいけます。
- http://sstd-bigdata.blogspot.jp/2014/08/postfixfluentdtreasuredata.html

- 残りのmatch以下は下記のとおりに設定。
- source部分は上述のコピー。

```td-agent.conf
<source>
  @type tail
  format multi_format
  path /var/log/mail.log
  pos_file /var/log/td-agent/mail.pos
  read_from_head true # if you need to read file from head
  tag td.log.mail

  <pattern>
    format /^(?<time>[^ ]* [^ ]* [^ ]*) (?<host>[^ ]+) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: (?<key>[^:]+): ?((to|from)=(<(?<address>[^>]+)>)?)?,( ?(orig_to=<(?<orig_to>[^>]+)>),)? ?(relay=(?<relay>[^ ]+)), ?(delay=(?<delay>[^ ]+)), ?(delays=(?<delays>[^ ]+)), ?(dsn=(?<dsn>[^ ]+)), ?(status=(?<status>[^,]+))/
    time_format %b %d %H:%M:%S
  </pattern>
  <pattern>
    format /^(?<time>[^ ]* [^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/
    time_format %b %d %H:%M:%S
  </pattern>
  <pattern>
    format none
  </pattern>
</source>

<match td.log.mail>
  @type s3
  aws_key_id AWS_KEY
  aws_sec_key AWS_SECRET_KEY
  s3_bucket LOG_BUCKET
  s3_region ap-northeast-1
  path maillog/
  buffer_path /var/log/td-agent/s3
  time_slice_format %Y%m%d%H
#  flush_interval 60s
  time_slice_wait 10m
  utc
  buffer_chunk_limit 256m
</match>
```

- flush_intervalはテスト時のみ設定することで、1時間待たずに1分単位でファイルをアップロードしてもらう。

# 今後の流れ

最終的には現行システムのメールサーバ移行が目標だが、それまでにまださらに下記が課題として残っている。

- S3内の古いログ(1週間以降？)を自動削除するポリシーを入れる
	- やり方がちゃんとわかってないので調べる。
- Elastic IPの逆引き設定の仕方

上記は今後調べてまとめる。

# 最後に(感想)
- NFSのところは、結構苦労した割に、書いてみるとすごくあっさりとなってしまい悲しかった。