Fish Shell環境でのDockerコマンド実行エラーを修正
KamalのDockerコマンド生成において、フィルタ名をシングルクォートで囲むことでFish Shell環境での実行エラーを解消しました。これにより、Bash以外のシェルを使用する環境でも正常に動作するようになります。
背景
Fish Shell環境で kamal details コマンドを実行すると、以下のエラーが発生していました:
fish: Expected a variable name after this $.
docker ps --filter name=^kamal-proxy$
この問題は #1691 で報告されており、Fish Shellが $ 記号を変数展開の開始として解釈することに起因します。Kamalが生成するDockerコマンドの --filter name=^kamal-proxy$ という指定において、末尾の $ が正規表現の行末記号ではなく変数として認識されていました。
BashやZshではクォートなしでも問題なく動作しますが、Fish Shellの変数展開ルールはより厳格であり、この違いが互換性問題を引き起こしていました。
技術的な変更
lib/kamal/commands/base.rb と lib/kamal/commands/proxy.rb において、--filter オプションの値をシングルクォートで囲む変更が加えられました。
変更前:
def container_id_for(container_name:, only_running: false)
docker :container, :ls, *("--all" unless only_running), "--filter", "name=^#{container_name}$", "--quiet"
end
変更後:
def container_id_for(container_name:, only_running: false)
docker :container, :ls, *("--all" unless only_running), "--filter", "'name=^#{container_name}$'", "--quiet"
end
同様の修正が lib/kamal/commands/proxy.rb の info メソッドにも適用されています:
def info
docker :ps, "--filter", "'name=^#{container_name}$'"
end
生成されるコマンドは docker container ls --all --filter 'name=^app-web-latest$' --quiet のようになり、シングルクォートによって正規表現全体が1つの文字列として扱われます。
テストファイル群(test/cli/app_test.rb、test/cli/main_test.rb、test/cli/proxy_test.rb、test/commands/app_test.rb、test/commands/proxy_test.rb)でも、期待されるコマンド文字列がクォート付きに更新されています。
設計判断
シングルクォートによるエスケープ という最小限の変更が採用されました。
Dockerコマンド自体は引用符なしの形式とクォート付きの形式の両方を受け入れるため、この変更はBashやZshなどの既存環境との互換性を維持しながら、Fish Shell環境での動作を保証します。ダブルクォートではなくシングルクォートが選ばれているのは、変数展開を完全に防ぐためです。
フィルタ値全体をクォートで囲むことで、シェルの種類に依存しない一貫した動作を実現しています。この判断は、Kamalがサポートする環境の多様性を考慮した堅実な選択といえます。
まとめ
本PRは、Dockerコマンドのフィルタ名をシングルクォートで囲むことで、Fish Shell環境での実行エラーを解消しました。最小限のコード変更で複数のシェル環境での互換性を確保し、Kamalの環境依存性を低減させています。