こんにちは。日々是発見が楽しみな西山です。
最近ようやく自宅サーバーでDockerを活用できるようになり(知識を覚え)、性能がいらないDHCPや監視系をDockerに移行して、構成の簡易化やリソース活用を図っています。
が、CIFS(Windows共有)のファイルサーバーをボリュームマウントしようとして思いっきりハマったので、今回はその教訓を共有して皆様のお役に立てたいと思います。
docker-compose が刺さる
docker-composeで下記のように指定すれば、CIFSストレージ(Windows共有)をボリュームとしてDockerコンテナに公開できます。
volumes:
FileServer:
driver_opts:
type: cifs
o: "username=hogehoge,password=asdf1234"
device: "//192.168.100.30/share"
検索したりAIに聞けばすぐ出てくる、オーソドックスなやり方ですね。
が、弊宅では何度やってもこれがエラーを起こし、docker-composeのスタック自体が起動しませんでした。ファイルサーバーのユーザー名、パスワード、接続先、どれを何回確認しても間違ってないのに……。
途方に暮れてエラーまみれのコンソールを眺めていた時、ふとあることに気が付きました。
「"Error: YAML parse error" って……構文チェックで落ちてる?」
「エラーメッセージに出てるの、もしかしてパスワード? の一部?」
含まれていた「@」
その時使っていたCIFSパスワードはmkpasswdコマンドで生成したもので、文字列中に「@」が含まれていました。
そして上記の例の通り、docker-composeがCIFSボリュームをマウントする際は接続ユーザー名とパスワードを「コマンドオプション」文字列として無加工で渡します。
YAMLの構文チェックで、コマンドオプション文字列に入っていた「@」がエスケープされていない特殊文字として引っかかり、弾かれていたのでした!
「じゃあ特殊文字をエスケープしなよ」
そうですね。しましたとも。
o: "username=hogehoge,password=asdf@1234"
を、
o: "username=hogehoge,password=asdf\@1234"
みたいに。
するとどうでしょう。"YAML parse error" は起こらなくなりましたが、今度はCIFS接続が「Permission Denied」で弾かれるようになりました。
そう、「コマンドオプション文字列として無加工で渡す」ため、今度は「asdf\@1234」がパスワードとしてファイルサーバーに渡され、もちろん不一致なので弾かれるようになったのです!
そして解決へ
「@」を含むパスワードを何とかしてdocker-composeからSambaに渡そうと四苦八苦しました。
「@」を変数で定義して「asdf{{at}}1234」みたいに書いてみました。外出しの環境変数ファイル(.env)に切り出してdocker-composeに渡してみました。
しかし何をどうやっても、「@」を含む文字列を正しく渡すことはできませんでした……。
渡せない場合の解決策が2つあります。
1つ目:CIFS(Windows共有)パスワードを「@」を含まないものに変更する
今回はこの方法で解決しました。私一人用のファイルサーバーなので、私が覚悟さえ決めれば特に問題はありません。
とはいえ、いざ変更すると自分でも覚えていなかったデバイスがファイルサーバーに接続していて、そいつらが続々エラーを吐いて落ちるので大変でした……。
企業や学校など、複数人で利用しているファイルサーバーだと、うかつにパスワードを変更できないかも知れません。
何十人にも影響を及ぼして業務に支障が出る、情報システム部の方針で自由に変更ができない等々、事情は色々あるでしょう。
そういう場合はもう一つの解決策が使えます。
2つ目:dockerから直接CIFS接続せず、ホストマシン経由でマウントする。
dockerでなければ、mountコマンドにユーザー・パスワードを渡して難なくCIFSボリュームに接続できます。もちろんパスワードに「@」みたいな特殊文字が入っていても問題ありません。
dockerホストの任意のディレクトリにCIFS共有をマウントし、コンテナからはそのディレクトリをローカルストレージマウントする、といった構成が考えられます。
dockerコンテナは環境の再現性や可搬性がメリットなので、ホストマシンに依存した構成になるのは少々気持ち悪いところです。
が、ファイルサーバーは長年使用されてることが多く、既に使用されているパスワードを変更するとどこに影響が出るか、なかなか追い切れません。
複数人で利用しているファイルサーバーでこれにハマってしまった場合は、安全を取ってホストマウントで解決するのがベターだと思います。