docker-mailserverをbash4.4未満で生き抜く
はじめに
このドキュメントは、docker-mailserverをbash4.4未満で使うためのメモです。
docker-mailserverのsetup.shでは、「shopt -s inherit_errexit」を使用しています。このコマンドはbash4.4以上でないと使用できません。
set -euEo pipefail
shopt -s inherit_errexit
trap '__err "${BASH_SOURCE}" "${FUNCNAME[0]:-?}" "${BASH_COMMAND:-?}" "${LINENO:-?}" "${?:-?}"' ERR
bash4.4未満の環境ではsetup.shをそのまま実行することはできません。例えば、CentOS7のbashは4.2系です。サポートの関係でCentOS8へ移行せず、CentOS7でいけるところまで引っ張る場合、問題となります。
$ bash --version
GNU bash, バージョン 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
解決方法1:bash4.4以上をローカルにインストールする
setup.sh実行用にbash4.4以上をインストールする方法です。
CentOS7上でbash5.1.6をインストールする方法を以下に示します。configure実行時のprefixは必要であれば変更してください。
# env LANG=C yum -y groupinstall "Development Tools"
# curl -LO https://ftpmirror.gnu.org/bash/bash-5.1.16.tar.gz
# tar zxvf bash-5.1.16.tar.gz
# cd bash-5.1.16
# ./configure --prefix=${HOME}/bash
# make && make install
setup.shを上記でインストールしたbashを使用するよう変更します。
#! /home/user1/bash/bin/bash
# version v1.0.0
# executed manually / via Make
# task wrapper for various setup scripts
CONFIG_PATH=
CONTAINER_NAME=
解決方法2:docker runでsetupを実行する
setup.shの本体はコンテナの中に入っています。setup.shはコンテナ内のsetupを呼び出すためのラッパーです。なので、setup.shが叩けないなら直接コンテナ内のsetupを呼び出す、という方法があります。
公式のStarting for the first timeにも本手順が記載されています。docker run実行時configディレクトリをdocker-compose.ymlと同じようにマウントしてあげる必要があります。
$ docker run --rm -v "${PWD}/docker-data/dms/config/:/tmp/docker-mailserver/" docker.io/mailserver/docker-mailserver setup email add user1@example.com password
この方法でsetupを実行する場合、ユーザ追加はパスワードを省略することはできません(setup.shだと、パスワードを省略して実行すると、パスワードを聞いてきます)。
また、本方法では一部表示されない情報があります。例えば、コンテナ動作時「/setup.sh email list」を実行すると、クォータ情報も表示されます。
$ ./setup.sh email list
* user1@example.com ( 0 / ~ ) [0%]
dockerコマンドでsetupを実行した場合、クォータ情報は表示されません。
$ docker run --rm -v "${PWD}/docker-data/dms/config/:/tmp/docker-mailserver/" docker.io/mailserver/docker-mails
erver setup email list
* user1@example.com
稼働中のコンテナでsetupを実行すると、上記情報も表示されます。
$ docker exec mailserver setup email list
* user1@example.com ( 0 / ~ ) [0%]
コンテナが動いているときはdocker exec、動いていないときはdocker runと判断する必要があるので、通常の使用では何も考えずdocker runを使うのが楽ちんだと思います。
解決方法3:docker-composeでsetupを実行する(お勧めしない)
docker runだとボリュームのマウントを指定する必要があるので面倒です。なので、docker-compose runで同じことできるんじゃないか、と考えました。結果、できるんだけどやめておいたほうがいい・・・ようです。
例えば「setup email list」を実行すると、以下のようにエラーが出ます。
$ docker-compose run mailserver setup email list
doveadm(user1@example.com)<37><>: Error: auth-master: userdb lookup(user1@example.com): connect(/run/dovecot/auth-userdb) failed: No such file or directory
doveadm(user1@example.com): Error: User lookup failed: Internal error occurred. Refer to server log for more information.
/usr/local/bin/listmailuser: line 19: notify: command not found
/usr/local/bin/listmailuser: line 19: notify: command not found
* user1@example.com ( / ) [%]
これはmailserver.env定義の有無で挙動を変える、という実装があるためです。docker-compose runの場合、コンテナにはmailserver.envの内容が反映されます。mailserver.env定義が存在する場合、各種サービス(postfixとか)が動いている前提でsetupは動きます。
しかし、docker-compose runの場合、postfixなど各種サービスは停止した状態です。そのため、上記のようなエラーが出ます。
mailserver.env定義の有無で挙動を変えるため、docker-compose runで破壊的な問題が出ないという可能性が0ではないです。そのため、docker-composeでのsetup実行は令和4年2月時点ではやめておいたほうが良い、という結論になりました。
Discussion