[アップデート]AWS SAM CLIのローカル実行時に環境上のhostsファイルに設定を追加できるようになりました
初めに
本日AWS SAM CLIのv1.108.0がリリースされました。
今回のアップデートでlocal invoke
に--add-host
オプションが追加されました。
こちらのオプションは値としてホスト名:IP
を指定することでコンテナ内のhostsファイルに対してその値を引き渡すことができます。
説明や実装を見る限りstart-lambda
やstart-api
にも実装されていそうですが(オプションを受け付ける)、実際に実行して見る限りinvoke
ではhostsファイルに書き込まれるもののそれ以外のサブコマンドでは確認できていません(バグかも?)。
これまでAWS SAM CLIでローカル実行する際に特定のホスト名への通信を一時的に別の通信先に向けたい場合や、ネームサーバを利用しない場合で実行環境内へのhostsファイルの書き直しが必要な場合、引き渡すための手段がないためそれだけのためにコンテナイメージを別途ビルドするなりアプリ側に差し替えるような処理を差し込むような必要がありました。
また開発環境のみでそれを適用したい場合当然フロー次第では誤ったデプロイをさせないように注意する必要があります。
今後はそういった必要はなく一時的であれば実行時のオプション、継続的であればsamconfigに書き込むことで実行環境や処理とは独立して設定をすることができます。
機能としてはdocker run
の同名のオプション相当の機能ですので普段かからこちらをご利用いただいている方には説明不要かもしれません。
確認
実際にプログラム側に特定のホスト名にHTTPリクエストをかけてもいいのですが、直接環境に入ったほうがhostsファイルも見れてわかりやすいと思いますのでそちらで確認します。
未指定時
まずは比較として通常時(未指定時)の確認を行います。
sam init
でPython3.12のHelloWorldをlocal start-api
で起動します。
% sam local start-api Initializing the lambda functions containers. Local image is out of date and will be updated to the latest runtime. To skip this, pass in the parameter --skip-pull-image Building image.......................................................................................................................................................................... Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64. ... * Running on http://127.0.0.1:3000 2024-01-24 12:26:57 Press CTRL+C to quit
SAMの実際の実行環境はコンテナ上で動いているためdocker ps
で実行中のコンテナを確認すると対象のコンテナが確認できます。
% docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 769b3f8e0f99 public.ecr.aws/lambda/python:3.12-rapid-x86_64 "/var/rapid/aws-lamb…" 3 seconds ago Up 2 seconds 127.0.0.1:5513->8080/tcp eager_blackburn
なお今回確認して初めて知ったのですがSAM側としては常に指定ポート(デフォルト3000)で受け付けるようですが立ち上がるコンテナ自体は別のランダムなポートで受け付けているようです。
あまりそこまで詳しく処理を見たことはないのですがSAM側のflaskが3000番台で受け付けて、オーソライザの処理等はSAM側で行い実際のLambdaコード処理のフェーズになったら別途処理コンテナに投げるような処理をしているのかもしれません(想像のため実態は不明)。
該当コンテナのhostsをdocker exec
経由で確認します。
% docker exec 769b3f8e0f99 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 769b3f8e0f99
add-host指定時
--add-host
の指定はdocker run
同様にホスト名:IP
の組で引き渡します。複数指定が必要な場合はその分だけ--add-host
オプションを列挙します。
前述の通りlocal invoke
以外では動作を確認できなかったためtime.sleep()
でコンテナをできる限り起動状態で保持するようにした上でlocal invoke
を実行し先ほど同様に立ち上がってるコンテナで/etc/hosts
をdocker exec
経由で表示します。
$ sam local invoke --add-host foo:127.0.0.1 --add-host bar:127.0.0.1 ... % docker exec 06787ba36889 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 127.0.0.1 bar 127.0.0.1 foo 172.17.0.2 06787ba36889
samconfigで指定し引き渡す場合は配列で定義を行います。
[default.local_invoke.parameters] add_host = ["foo:127.0.0.1", "bar:127.0.0.1"]
一応start-api
でもdebugのログを見る限り値自体は引渡されていそうではあるのですが現バージョンではhostsファイルに乗っていることを確認できませんでした。
% sam local start-api --add-host foo:127.0.0.1 --add-host bar:127.0.0.1 --debug ... 2024-01-24 19:43:34,299 | --template_file=/Users/xxx/git/sam-app/.aws-sam/build/template.yaml --add_host={'foo': '127.0.0.1', 'bar': '127.0.0.1'} --host=127.0.0.1 --port=3000 ... % docker exec f0364ca01517 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 f0364ca01517
終わりに
ハードコードされたURLがありアプリを書き換えたくない場合、公開したくないホスト名ではあるがプライベートのDNSサーバを作る感じでもなくhostsファイルを利用している場合、といった形でローカル環境だと結構利用するケースはあるかと思いますのでこれがぱっとできるのは嬉しいのではないでしょうか。
SAM環境からSAM環境にはなりますが直近SAMでHTTPS通信が利用できるアップデートがありましたので信頼される正規の認証機関から発行された証明書をローカルに持ち込み、そのSAM環境にアクセスする際にhostsファイルでそのドメインを割り当てると証明書の検証を正規に通しつつ確認ということもできそうです。
今回動作を確認する限りはまだlocal invoke
以外では利用できなさそうなのでこの辺りが対応(もしくは修正?)されてくれれば一気に利用ケースが膨らみそうです。