自宅のプロキシ/DNS/メールサーバをPacemakerによる冗長構成から、ロードバランサ (ZEVENET) + Dockerコンテナ構成への移行を進めている。
ロードバランサは導入済みなので、最終形として、プロキシ、DNS、メールのそれぞれの機能をDockerのコンテナ化を行うことを計画しており、今回はその第一弾として、メール機能であるPostfixのコンテナ化を行う。
最終形として、プロキシ、DNS、メールのそれぞれの機能をDockerのコンテナ化を行うことを計画しており、今回はその第一弾として、メール機能であるPostfixのコンテナ化を行う。
- DockerでPostfixをコンテナ化してメールサーバを構築する ★本記事
- DockerでUnboundをコンテナ化してDNSサーバを構築する
- DockerでSquidをコンテナ化してプロキシサーバを構築する
- Docker Composeを作って複数のコンテナの作成・起動・停止・削除を制御する
環境
今回のDocker環境構築時のソフトウエアバージョンを以下に記載する。
- DockerホストOS : CentOS 8.2
- Docer : 19.03.14
- コンテナ用OSイメージ : centos:latest
Dockerホストとコンテナ間では、サービス提供に必要なポートの紐づけと、ログファイルを出力させるディレクトリの紐づけを行う。以下に簡単に図示しておく。
Postfixコンテナ化手順
1. Dockerのインストール
Dockerのインストールは別記事を参照。CentOS 7にDockerをインストールする内容となっているが、CentOS 8も同様の手順でインストールできる。
Dockerインストール後、Dockerfile等を配置するディレクトリを作成し、以後はそのディレクトリ内にすべてのファイルを配置する。
2. Postfix用の設定ファイルを準備
通常の家庭用のインターネットプロバイダを使っている場合、SMTP (TCP/25ポート) を使って外部へのメール送信はできないようになっている。この仕様をOP25B (Outbound Port 25 Blocking)と呼ぶが、PostfixでOP25Bに対応した設定をすることでメール送信が可能となる。OP25B環境におけるPostfixの設定は以下にて記事にしているで参照いただきたい。
コンテナにする場合も同様の設定を行えばよい。あらかじめ、以下の通り2つの設定ファイルを作成しておく。
main.cf
※★箇所は各環境に合わせて変更すること。
compatibility_level = 2
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost
unknown_local_recipient_reject_code = 550
mynetworks = 127.0.0.0/8, 192.168.0.0/16 #★
relayhost = [<メールサーバのFQDN>]:587 #★
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix/samples
readme_directory = /usr/share/doc/postfix/README_FILES
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem
smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
smtpd_tls_security_level = may
smtp_tls_CApath = /etc/pki/tls/certs
smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt
smtp_tls_security_level = may
meta_directory = /etc/postfix
shlib_directory = /usr/lib64/postfix
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/smtp_password
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain,login
smtp_password
※★箇所は各環境に合わせて変更すること。
[<メールサーバのFQDN>]:587 <ユーザ名>:<パスワード> #★
3. rsyslogとPostfix起動用のスクリプト (ラッパースクリプト) を作成
Postfixはログ出力にrsyslogの機能を使うため、rsyslogの起動とPostfixの起動という複数のプロセス起動を行う必要がある。複数のプロセス起動を行う場合の作法としては、ラッパースクリプトを作成して実行させるといった手法が定番のようだ。
今回は、以下の内容でstartup.sh
というスクリプトを作成した。メインとなるプロセス (今回はPostfix) の起動コマンドはexec
を付与してPID 1で動作させるようにしている。
#!/bin/bash
/usr/sbin/rsyslogd
exec /usr/sbin/postfix start-fg
4. Dockerホストにログ出力先を作成
今回はコンテナのPostfixが出力したmaillogをDockerホストのディレクトリ出力するよう構成するため、以下の通りあらかじめログ出力先のディレクトリを作成しておく。
mkdir -p /var/log/docker/centos-postfix
chmod 777 /var/log/docker/*
5. Dockerfile
を作成
コンテナの構成情報はDockerfile
に記述する。いくつか記述内容にポイントがあるので以下表にまとめる。
命令 | 記述内容 | 説明 |
---|---|---|
FROM | centos |
コンテナのベースとなるイメージはCentOSを使用する。 |
ENV | TZ |
タイムゾーンを日本標準時 (Asia/Tokyo) にする。 |
ENV | http_proxy , https_proxy |
プロキシ環境の場合は、プロキシサーバを指定する。 |
RUN | dnf |
必要なパッケージのインストールを行う。Postfixのログはsyslogを使用して出力されるため、rsyslogを追加インストールする点に注意。 |
RUN | sed , mkdir |
コンテナ環境であってもログを出力できるようにするため、/etc/rsyslog.conf の設定ファイルを修正する。maillog の出力先を/var/log/postfix/maillog に変更し、ログの出力をjournald経由ではなくシステムソケットに変更している。また、Dockerホストのボリュームのマウントポイントとなるため、ログ出力先ディレクトリの作成しておく。 |
COPY | - | 事前に作成したmain.cf とsmtp_password の設定ファイルを /etc/postfix/ にコピーする。 |
COPY | - | プロセス起動用のstartup.sh を/ にコピーする。 |
RUN | chmod , postmap , postalias |
各種設定ファイルの権限設定とPostfixで必要となるDBファイルの作成を行う。 |
EXPOSE | 25 | SMTPの25番ポートを記述する。 |
CMD | ["/startup.sh"] |
startup.sh を起動する。[] で囲まずに記述すると/bin/sh -c が付与されてプロセスが実行されてしまうので、通常は必ず[] にてコマンドを囲むこと。 |
実際のDockerfile
は以下の通りとなった。
FROM centos
ENV TZ=Asia/Tokyo \
http_proxy=http://192.168.33.23:8080 \
https_proxy=http://192.168.33.23:8080
RUN dnf install postfix cyrus-sasl cyrus-sasl-plain mailx rsyslog -y && \
sed -i -e 's#/var/log/maillog#/var/log/postfix/maillog#g' \
-e 's/SysSock.Use="off"/SysSock.Use="on"/g' \
-e 's/^\(module(load="imjournal"\)/#\1/g' \
-e 's/^\([ ]*StateFile="imjournal.state\)"/#\1/g' \
/etc/rsyslog.conf && \
mkdir /var/log/postfix
COPY main.cf smtp_password /etc/postfix/
COPY startup.sh /
RUN chmod 600 /etc/postfix/smtp_password && \
postmap /etc/postfix/smtp_password && \
postalias /etc/aliases && \
chmod +x /startup.sh
EXPOSE 25
CMD ["/startup.sh"]
6. コンテナイメージを作成
作成したDockerfile
を使って、docker build
コマンドにてコンテナイメージを作成する。
# docker build -t centos-postfix:1 .
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos-postfix 1 9e3991eb23a8 36 hours ago 296MB
7. コンテナを起動
コンテナ起動時には、以下オプションの設定を行う。
設定内容 | 説明 |
---|---|
--name |
コンテナの名称を設定。今回は「centos-postfix」という名前にする。 |
-p |
Dockerホストの通信ポートとコンテナの通信ポートを紐づけを行う。<ホストポート>:<コンテナポート> の書式で記載する。今回はSMTPのポート番号である25番ポートを紐づけるので、25:25 で指定する。 |
-v |
Dockerホストのディレクトリ/ファイルとコンテナのディレクトリ/ファイルの紐づけを行う。<ホストディレクトリ/ファイル>:<コンテナディレクトリ/ファイル> の書式で記載する。今回はホストの/var/log/docker/centos-postfix/ ディレクトリにコンテナの/var/log/postfix を紐づけることで、maillog ログを出力させる。 |
上記をふまえ、以下の通りdocker run
コマンドでコンテナの起動を行う。
# docker run -d -p 25:25 --name "centos-postfix" \
-v /var/log/docker/centos-postfix:/var/log/postfix \
centos-postfix:1
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6bb3910351a centos-postfix:1 "/startup.sh" 28 minutes ago Up 28 minutes 0.0.0.0:25->25/tcp centos-postfix
8. logrotate設定
ホストに出力させたログをローテーションさせるため、logrotateの設定を行う。logrotateは/etc/logrotate.d/
に設定ファイルを置けば自動で実行されるようになる。
logrotateの設定のポイントは2つ。
logrotateは元のファイルをリネームして、新規空ファイルを作成するという動作を行うが、この際にログ出力元となるプロセスのリロード等の処理が必要となる。しかし、ホスト側のログローテーション実行とコンテナ側のプロセスのリロードの同期ができないため、copytruncate
オプションを付与する。copytruncate
オプションを付与すると、元のファイルはリネームではなくコピーしたのち、ログファイルの内容を空にする方式でローテーションが実行される。
※本方式はタイミングによっては、ローテーション中に書き込まれたログがロストする可能性があるので注意。
また、logrotateの仕様により、ログ出力先のディレクトリの権限が777となっている場合、以下メッセージでローテーションが失敗する。このような場合でもログローテーションを実行できるようsu root root
を付与する。
error: skipping "/var/log/docker/centos-postfix/maillog" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.
上記をふまえ、以下のようにdocker-log
というファイル名で設定ファイルを作成し、/etc/logrotate.d/
に配置した。
# cat /etc/logrotate.d/docker-log
/var/log/docker/*/maillog
/var/log/docker/*/*.log
{
rotate 7
daily
copytruncate
dateext
su root root
}
1日経過すると以下の通りログがローテーションされることが確認できた。
# ls -lh /var/log/docker/centos-postfix/
/var/log/docker/centos-postfix/:
-rw-r--r--. 1 root root 263K 12月 20 07:06 maillog
-rw-r--r--. 1 root root 1.2M 12月 20 03:17 maillog-20201220
以上でPostfixのコンテナ化が完了となる。
0 件のコメント:
コメントを投稿