🐙

コンテナに ssh で接続する際ちょっと便利になる .ssh/config の書き方

に公開

ときには、コンテナに ssh で接続したいというときがあると思います。私の場合は devcontainer で作った開発環境へ ssh で入っているので毎日使っています。

https://zenn.dev/goropikari/articles/nvim_devcontainer

一つのコンテナに対して 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 で接続待ちしている)

~/.ssh/config
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
~/.ssh/config
Host devc-*
    ProxyCommand /usr/bin/nc $(docker inspect %h --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') %p
    Port 2222
    User vscode

この状態で ssh devc-test1ssh devc-test2 とするとそれぞれのコンテナに接続することができます。

config に何を書いているのか

~/.ssh/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 できるようになりました。

GitHubで編集を提案

Discussion