🐧

Dev Container の sshd フィーチャー:Linux 使い(略)Advent Calendar 2024

2024/12/11に公開

はじめに

これは「Linux 使いになりたい人のための Advent Calendar 2024」の記事です。

筆者は、Web エンジニアを志望する人には、セルフホスト Git サービスを稼働させて利用することをオススメしています。もし Git を使ったことがないなら、Git を学ぶときに、セルフホスト Git サービスを稼働させることも視野に含めながら学習するのが効率的だと考えています。

Dev Container の sshd フィーチャー

前回はセルフホスト Git サービスを使うにあたり、OpenSSH を使うことが多いといった説明の流れから、VS Code Remote - SSH 拡張機能について紹介し、これを試用するための OpenSSH サーバーを Docker コンテナーで用意する方法を説明しました。

その際、用意した Docker イメージを作成するにはユーザーを追加するなどの処理が必要で少し大変でした。同じような sshd の環境を Dev Container で用意することができます。こちらは、sshd フィーチャーというものを使えば良いだけなので、簡単です。

開発コンテナーを使うには次のものが必要です。

  • Docker Engine + Docker Compose (Docker Desktop に含まれる)
  • Visual Studio Code
  • Visual Studio Code 拡張機能
    • Docker(ms-azuretools.vscode-docker)
    • Remote Development(ms-vscode-remote.vscode-remote-extensionpack)

devcontainer-sshd の利用

OpenSSH サーバーが稼働する開発コンテナーを sshd フィーチャーを使って用意してみましょう。ここでは次のファイルを用意するとします。

devcontainer-sshd/
├── .devcontainer/
│   └── devcontainer.json
└── sample/ ... 前回、前々回のものを参考にしてください
    └── dot.ssh/
        ├── authorized_keys
        ├── id_ed25519
        └── id_ed25519.pub

sshd フィーチャーについては devcontainers/features/src/sshd に説明があります。

devcontainer.json の作成

開発コンテナーを用意するには、devcontainer.json の作成をします。devcontainer.json についての詳細は https://aka.ms/devcontainer.json を参照してください。

devcontainer.json の内容は次のとおりです。エディタで作成してもよいですし、VS Code のアクティビティバーにあるリモートエクスプローラを開いて「開発コンテナー」のプルダウンの下にマウスをポイントすると表示される「+」(マウスオーバーで「新しい開発コンテナー」とラベルが表示される)をクリックして作成しても良いです。

{
    "name": "Node.js & TypeScript",
    // https://github.com/devcontainers/templates/tree/main/src/typescript-node
    "image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
    "features": {
        "ghcr.io/devcontainers/features/git:1": {},
        "ghcr.io/devcontainers/features/git-lfs:1": {},
        "ghcr.io/devcontainers/features/github-cli:1": {},
        "ghcr.io/devcontainers/features/sshd:1": {}
    }
}

ベースには Node.js で TypeScript が使える mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm イメージを使用します。mcr.microsoft.com/devcontainers/typescript-node イメージによる開発コンテナーを使うと次のようなメリットがあります。

  • 開発でよく使うツールがインストールされている
  • sudo 権限を持つユーザーがあらかじめ用意されている
  • Git リモートリポジトリを利用するための機能があらかじめ用意されている
  • Docker ホストの ssh-agent と連携する

フィーチャーについては、Git も使うことが多いので関連するものを追加してあります。今回、目的としている sshd も当然指定します。

  • git
  • git-lfs
  • github-cli
  • sshd

開発コンテナー内で ssh 動作確認

devcontainer-sshd ディレクトリーを /devcontainer-sshd に置いたとしたら、このディレクトリーを VS Code で次の手順で開きます。

code /devcontainer-sshd/

VS Code が開くと、右下に「コンテナーで再度開く」というボタンを含む通知が表示されます。このボタンをクリックすると、開発コンテナーが起動し、このコンテナーをアタッチした VS Code の画面が開きます。

開発コンテナーをアタッチした VS Code が開いたら、ターミナルを表示して、ユーザーのパスワードを指定します。ここで用意したコンテナーのユーザーは node なので、次のコマンドで node ユーザーのパスワードが指定できます。

sudo passwd $(whoami)

パスワードを指定したら、node@localhost へ SSH ログインします。sshd フィーチャーのポート番号は 2222 なので、-p オプションで指定します。他のオプションはホストのフィンガープリントをチェックしない(StrictHostKeyChecking=no)、known_hosts ファイルを無効化(UserKnownHostsFile=/dev/nullGlobalKnownHostsFile=/dev/null)するものです。

ssh -p 2222 \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o GlobalKnownHostsFile=/dev/null \
    node@localhost

これを実行すると、パスワード入力のプロンプトが表示されるので、先程指定した node ユーザーのパスワードを入力すると、SSH ログインができます。

鍵ファイルを使った動作確認

次に鍵ファイルを作成して動作確認してみましょう。次のコマンドで ~/.ssh/id_ed25519~/.ssh/id_ed25519.pub が作成されます。

ssh-keygen -t ed25519 -C "node@devcontainer-sshd"

次に SSH サーバーへ公開鍵の登録します。ここでは ssh-copy-id コマンドを使います。これで ~/.ssh/id_ed25519.pub の内容が SSH サーバーの ~/.ssh/authorized_keys に登録されます。OpenSSH の初期設定では、sshd のパスワード認証を有効化しておいて、公開鍵の登録を済ませてから sshd のパスワード認証を無効化するといったことは、サーバー構築時によくある手順です。

ssh-copy-id -p 2222  \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o GlobalKnownHostsFile=/dev/null \
    node@localhost

このコマンド実行時のコンソールは次のような出力になります。

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 3 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.
node@localhost's password: ← パスワードを入力

Number of key(s) added: 3

Now try logging into the machine, with:   "ssh -p '2222' -o 'StrictHostKeyChecking=no' -o 'UserKnownHostsFile=/dev/null' -o 'GlobalKnownHostsFile=/dev/null' 'node@localhost'"
and check to make sure that only the key(s) you wanted were added.

これで、/home/node/.ssh/authorized_keys に、id_ed25519.pub の公開鍵が登録されます。その結果、公開鍵認証による SSH ログインができるようになります。

なお、Docker ホストから開発コンテナーの sshd へアクセスするには、Docker ホストのポート番号 2222 を開発コンテナーのポート番号 2222 へ転送する必要があります。devcontainer-sshd コンテナーをアタッチした VS Code の画面でターミナルを開くと、ターミナルの横にポートのタブが表示されます。そこでポートのタブを開くと「ポートの転送」ができるようになっています。この画面で Docker ホストの 2222 のポートをコンテナーの 2222 のポートへ転送します。

もちろん、devcontainer.jsoncompose.yaml ファイルでポート転送の指定をして使えるようにしておいても良いです。

開発コンテナー用イメージでの Git 認証について

開発コンテナー用イメージでの Git 認証については、VS Code の公式ドキュメントの Sharing git credentials を一度、詳しく読んでおくと良いはずです。

mcr.microsoft.com/devcontainers で提供されている開発コンテナー用イメージを使って起動した開発コンテナーは Docker ホスト側の ~/.gitconfig を自動でコピーします。そのため、自分で ~/.gitconfig をバインドマウントする必要はありません。なお、自動で追加される設定もあるので、開発コンテナー用の .gitconfig を用意するというのが逆に難しくなっています。

また、この開発コンテナーは、開発コンテナー用のワークスペースの Git リポジトリを自動で検出します。開発コンテナーを開くときに、その Git リポジトリを使うことを選択すると、/workspace の下に自動で Git リポジトリをバインドマウントします。

正直なところ、バインドマウントはいろいろと問題の原因となりやすいので、自動でバインドマウントされることについては、少し気になりますが、便利であるといえば便利です。

簡単な問題となる例を上げると、開発コンテナーを起動中に使用中の devcontainer.json の編集ができてしまうのですよね。使っている状態から乖離したものに編集してしまうと、使用中の開発コンテナーに影響が出てしまうので、あまり良くないというのが自分の考えです。さわらなければ良いといえば、そうなのですが、事故は常に起こり得るので、起きにくくするためにバインドマウントしない方を個人的には推奨しています。

また、開発コンテナーで ssh コマンドを使うときに、Docker ホストの ssh-agent と連携するため、~/.ssh を自分でバインドマウントする必要がありません。ただし、この機能が自分が使っている Linux (Ubunt Desktop) では、うまく働かなくなることがあります。このあたりは、気になっているのですが、きちんと調べきれていません。なんとなく ssh-agent を使った認証を1度しておいてから開発コンテナーを起動すると大丈夫なような気がしています。

おわりに

前々回に Docker コンテナーを使うと OpenSSH サーバーの試用が簡単にできることを紹介しました。

root ユーザーのみのシンプルなコンテナーで OpenSSH サーバーを動かしても良いのですが、開発コンテナーに使い慣れていると、OpenSSH サーバーを利用するスクリプトの開発などをするときには、こちらの sshd フィーチャーを使うのが楽そうだと感じるのではないでしょうか。

CI/CD 用のスクリプトを作成するときは ssh コマンド関連の自動化はよくするので、それの動作確認ができる環境は専用に用意しておきたいところです。そういったときに、開発コンテナー + sshd フィーチャーが役に立ちます。

Discussion