コンテナに ssh で接続する際ちょっと便利になる .ssh/config の書き方
ときには、コンテナに ssh で接続したいというときがあると思います。私の場合は devcontainer で作った開発環境へ ssh で入っているので毎日使っています。
一つのコンテナに対して ssh をするくらいならよいですが、複数のコンテナに対して同時に ssh しようと思うと port が衝突しないように port forward のことを考えなければならず面倒です。
ならいっそ port forward なんてしなければいいわけですが、その時 .ssh/config を工夫すると運用が楽になるかもしれません。
サマリ
- 立ち上げたコンテナの名前を rename or name 指定で立ち上げる
- ProxyCommand でコンテナ名から IP を調べるようにしておく
-
ssh {container_name}で接続できるようになる
devc- prefix がついているコンテナに対して ssh できるようにする config 例。(SSH の devcontainer feature では 2222 port で接続待ちしている)
Host devc-*
ProxyCommand /usr/bin/nc $(docker inspect %h --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') %p
Port 2222
User vscode
詳細
動作確認環境
- OS: Ubuntu 24.10
- docker: version 27.4.1
- devcontainer cli: version 0.72.0
実際に動かしてみる
コンテナを2つ起動して実際に試してみます。
for d in devc-test1 devc-test2; do
devcontainer templates apply --template-id ghcr.io/devcontainers/templates/ubuntu:1.3.2 --features='[{"id":"ghcr.io/devcontainers/features/sshd:1", "options":{}}]' --workspace-folder=$d
res=$(devcontainer up --workspace-folder=$d)
id=$(echo $res | jq -r .containerId)
docker rename $id $d
# コンテナの中に公開鍵を配置
devcontainer exec --workspace-folder=$d mkdir -p /home/vscode/.ssh
docker cp ~/.ssh/id_ed25519.pub $d:/home/vscode/.ssh/authorized_keys
devcontainer exec --workspace-folder=$d bash -c 'chmod 644 /home/vscode/.ssh/authorized_keys'
devcontainer exec --workspace-folder=$d bash -c 'chmod 700 /home/vscode/.ssh'
done
Host devc-*
ProxyCommand /usr/bin/nc $(docker inspect %h --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') %p
Port 2222
User vscode
この状態で ssh devc-test1 や ssh devc-test2 とするとそれぞれのコンテナに接続することができます。
config に何を書いているのか
Host devc-*
ProxyCommand /usr/bin/nc $(docker inspect %h --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') %p
Port 2222
User vscode
hostname にはワイルドカードが使え、この書き方だと devc- prefix がつけられた hostname を指定するとこの設定が使われます。
%h, %p は ssh_config で使える TOKEN でそれぞれ hostname, port を表しています。
docker container name と hostname を合わせておけば docker inspect %h --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' によって指定したコンテナの ip address が取得できます。
ProxyCommand に書かれていることから想像できるように nc は Proxy の役割をしています。SSH server とは nc を介して通信し、client と nc 間は stdin/stdout で通信されます。
以上により localhost に port forward せずとも楽にコンテナに SSH できるようになりました。
Discussion