【Docker/supervisor/postfix】Dockerコンテナ起動時にpostfixを自動起動

Dockerコンテナの起動時に、postfixやらなんやらを自動起動させるのに手間取ったのでその方法についてまとめました。

先に結論を書くと、
**supervisorでpostfixを起動させるのがおそらくベター**
です。それについての記載となります。

後述する**創生滅亡輪廻 postfix**およびその類似の現象で悩む人をちょっとでも壊劫させることができれば幸いです。

なお、本記事では**alpine3.10**の想定です。

大枠の思想は他のディストリビューションでも変わらないので、
インストールやらプロセス起動部分だけ変換してください。

# supervisorをインストール＆CMDに指定
supervisorをインストールし、CMDで起動するプロセスに指定します。
前述の通り、彼が今回の肝です。

```Dockerfile:Dockerfile
# postfix関連とsupervisorのインストール
RUN apk add --no-cache supervisor && \
    postfix postfix-pcre && \
    mailx cyrus-sasl cyrus-sasl-crammd5 rsyslog

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
```

「なんやねんそれ」って人用にざっくり書くと**フォアグラウンドプロセスをデーモン化したり管理したりするやつ**です。これをCMDに設定することで任意のプロセスを自動起動していきます。

今回**フォアグラウンドプロセス**って部分、超大事だった。
上の例では起動させるpostfixも一緒に入れてます。

# supervisorの設定
次にデーモンとして起動させるプロセスとかの設定をします。
以下はpostfixを自動起動される例です。

```Dockerfile:Dockerfile
# supervisord設定
RUN echo '[supervisord]' >> /etc/supervisord.conf && \
    echo 'nodaemon=true' >> /etc/supervisord.conf && \
    echo '[program:postfix]' >> /etc/supervisord.conf && \
    echo 'command=postfix start-fg' >> /etc/supervisord.conf
```

- supervisorをnodeamonで起動し （**nodaemon=true**）
- postfixというプロセス名をつけて （**[program:postfix]**)
- postfixをフォアグランドで起動しています (**command=postfix start-fg**）

これでコンテナを起動させればOKです。以下の様にpostfixが起動され、コンテナの標準出力でもそれが確認できるはずです。

``` terminal:コンテナの中（外からexecでもいいよ）
# postfix status
postfix/postfix-script: the Postfix mail system is running: PID: 609
```

``` log:標準出力
$ docker logs {コンテナ名}
2020-01-08 18:06:49,102 INFO supervisord started with pid 1
2020-01-08 18:06:50,109 INFO spawned: 'postfix' with pid 540
2020-01-08 18:06:51,172 INFO success: postfix entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
```

### 動けばいいよ！って人はここまで見ればいいです。
お疲れ！ビール飲んでいいよ！

## supervisor設定のポイント
今回のポイントとしては以下の二点です。

- supervisorそのものは**nodeamon**で起動（nodaemon=true）
- postfixは**フォアグランドでの起動**を明示（command=postfix start-fg）

前者はそうしないと全部起動した後にdockerコンテナそのものが終了してしまうためです。
プロセスが全部終了するとコンテナも終了するので。

後者はsupervisorの特性に関連します。

わかりやすいのでDockerfileを以下の様に変更してみてください。

``` Dockerfile:Dockerfile
# echo 'command=postfix start-fg' >> /etc/supervisord.conf && \
echo 'command=postfix start' >> /etc/supervisord.conf && \
```

この状態でコンテナを起動して標準出力を確認すると、
以下の様にpostfixが**spawned（誕生）→exited（死亡）→spawned→exited**と延々と繰り返すはずです。


``` log:標準出力ログ
2020-01-08 18:06:09,698 INFO spawned: 'postfix' with pid 477
2020-01-08 18:06:10,702 INFO success: postfix entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2020-01-08 18:06:10,725 INFO exited: postfix (exit status 1; not expected)
2020-01-08 18:06:11,732 INFO spawned: 'postfix' with pid 484
2020-01-08 18:06:12,734 INFO success: postfix entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2020-01-08 18:06:12,756 INFO exited: postfix (exit status 1; not expected)
```

これが僕が割と長く悩んだ**創生滅亡輪廻postfix**です。

commandで指定したプロセスがバックグラウンドにまわると、supervisorがそのプロセスを補足できずに
**「起動したけど終了した」と判断して再起動をかけ続ける**みたいなんですね。

これを防ぐために、postfixをフォアグラウンド指定で起動しています。

## 余談
**postfix start-fg**はpostfixのバージョンが3.3以上でないと使えません。
そのため、もしそれ未満で同様のことがしたい場合は、以下の様にしてください。

``` Dockerfile:Dockerfile
# echo 'command=postfix start-fg' >> /etc/supervisord.conf && \
echo 'command=sh /usr/local/bin/postfix.sh' >> /etc/supervisord.conf && \　#postfix3.3未満の場合
```

``` sh:/usr/local/bin/postfix.sh
#!/bin/sh
postfix start
tail -F /var/log/mail.log
```

supervisorではシェルを起動し、起動されるシェルの方でpostfixの起動とFオプション月のtailコマンドでフォアグランド扱いとする方式です。
こっちのが応用も効くかな？知らんけど。