Accessoryの新規コンテナ実行時にoption_argsを適用
Kamalでアクセサリ(データベースなど)に対してコマンドを実行する際、新規コンテナで実行する場合と既存コンテナで実行する場合でオプション設定が異なる不整合が修正されました。
背景
kamal accessory execコマンドは、--reuseオプションの有無で動作が異なります。--reuseを指定すると既存のコンテナでコマンドを実行し、指定しない場合は新規の一時的なコンテナを起動してコマンドを実行します。
しかし、この新規コンテナ起動時にconfig/deploy.ymlのoptionsで指定したDockerオプション(ulimit、CPU制限、メモリ制限など)が適用されていませんでした。これにより、既存コンテナと新規コンテナで実行環境が異なるという問題が発生していました。
例えば、以下のような設定でulimitを指定していても:
accessories:
my-accessory:
image: my-image
options:
ulimit: nofile=8192:8192
新規コンテナでの実行時にはデフォルト値(1024)が使われていました。
技術的な変更
#1739では、execute_in_new_containerメソッドに*option_argsを追加することで、この不整合を解消しています。
変更前:
def execute_in_new_container(*command, interactive: false)
docker :run,
"-it", (interactive ? "--rm" : "--rm"),
*network_args,
*env_args,
*volume_args,
image,
*command
end
変更後:
def execute_in_new_container(*command, interactive: false)
docker :run,
"-it", (interactive ? "--rm" : "--rm"),
*network_args,
*env_args,
*volume_args,
*option_args, # 追加
image,
*command
end
これにより、実際に生成されるDockerコマンドは以下のように変わります:
変更前:
docker run --rm --network kamal --env MYSQL_ROOT_HOST="%" --env-file .kamal/apps/app/env/accessories/mysql.env private.registry/mysql:8.0 mysql -u root
変更後:
docker run --rm --network kamal --env MYSQL_ROOT_HOST="%" --env-file .kamal/apps/app/env/accessories/mysql.env --cpus "4" --memory "2GB" private.registry/mysql:8.0 mysql -u root
設計判断
この修正は、kamal app execの実装に倣ったものです。アプリケーションコンテナでは既に同様の実装がなされており、新規コンテナ実行時にも設定されたオプションが適用されていました。
アクセサリについても同じ挙動にすることで、一貫性のある実行環境を提供できるようになりました。これは特に、リソース制限やセキュリティ設定など、環境依存の設定が必要な場合に重要です。
テストコードでは、cpusとmemoryオプションを持つ設定を追加し、runメソッドとexecute_in_new_containerメソッドの両方で正しくオプションが適用されることを検証しています。