先に結論だけ
DevContainer内から1Password SSH Agentを使うには、以下の3つの設定をdevcontainer.jsonに追加します。
{
"name": "Node.js DevContainer",
"image": "mcr.microsoft.com/devcontainers/typescript-node:latest",
"runArgs": [
"-v",
"${localEnv:HOME}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock:/tmp/1password-agent.sock"
],
"remoteEnv": {
"SSH_AUTH_SOCK": "/tmp/1password-agent.sock"
},
"postStartCommand": "sudo chown node:node /tmp/1password-agent.sock && sudo chmod 600 /tmp/1password-agent.sock"
}
ポイント
-
runArgsで1PasswordのUnixソケットをコンテナー内にマウント -
remoteEnvで環境変数SSH_AUTH_SOCKを設定 -
postStartCommandで権限を調整(所有者をnodeユーザーに、パーミッションを600に)
はじめに
DevContainer内でGitリポジトリにSSH接続する際、秘密鍵の管理が課題になります。秘密鍵をコンテナー内にコピーするのはセキュリティ上好ましくありません。
1Password SSH Agentを使えば、秘密鍵をコンテナー外(ホストOS上の1Password)で安全に管理しながら、DevContainer内からSSH認証を行うことができます。
この記事では、macOS + VS Code Dev Containersの環境で1Password SSH Agentを使う方法を、実際にハマったポイントも含めて紹介します。
対象読者
- Docker/DevContainerを使い始めた方
- DevContainer内でGit署名付きコミットやSSH接続を行いたい方
- 1Passwordで秘密鍵を安全に管理したい方
対象環境
この記事は以下の環境で動作確認しています:
- macOS 15.7.2
- VS Code 1.106.0
- Docker Desktop for Mac 4.51.0
- 1Password for Mac 8.11.18(SSH Agent機能有効化済み)
この記事ではmacOS固有のSSH Agentパス(~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock)を使用しています。LinuxやWindowsなど他のプラットフォームを利用する場合は、お使いのOSに応じたパスに読み替えてください。
前提条件
以下の環境が整っていることを前提とします。
- 1Password(SSH Agent機能が有効: 有効化手順)
- Visual Studio Code(Dev Containers拡張機能)
- Docker Desktop
セットアップ手順
ステップ1: devcontainer.jsonの作成/編集
プロジェクトルートの.devcontainer/devcontainer.jsonを編集します(まだ存在しない場合は作成)。
ステップ2: 3つの設定項目を追加
2-1. runArgs: Unixソケットのマウント
"runArgs": [
"-v",
"${localEnv:HOME}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock:/tmp/1password-agent.sock"
]
解説
- Dockerの
-vオプションを使って、ホストの1Password SSH Agentソケットをコンテナーにマウントします - macOSでは1Passwordのソケットは
~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sockに配置されています - コンテナー内では
/tmp/1password-agent.sockとしてアクセスできるようになります
Unixソケットとは
Unixソケット(UNIXドメインソケット)は、同一マシン上のプロセス間通信に使われる仕組みです。ファイルシステム上のパスで識別され、ネットワーク通信と同じソケットAPIを使いながら、ローカル通信を実現します。
1Password SSH Agentは、このUnixソケットを通じてSSH鍵へのアクセスを提供しています。
参考: 付録 A UNIX ドメインソケット - Oracle Solaris 10ドキュメント
なぜrunArgsを使うのか
後述の「ハマったポイント」で詳しく説明しますが、UnixソケットファイルのマウントにはmountsプロパティではなくrunArgsの-vオプションを使う必要があります。
2-2. remoteEnv: 環境変数の設定
"remoteEnv": {
"SSH_AUTH_SOCK": "/tmp/1password-agent.sock"
}
解説
- コンテナー内の
SSH_AUTH_SOCK環境変数に、マウントしたソケットファイルのパスを指定します - この環境変数により、gitやsshコマンドがSSH Agentの場所を認識できます
2-3. postStartCommand: 権限の調整
"postStartCommand": "sudo chown node:node /tmp/1password-agent.sock && sudo chmod 600 /tmp/1password-agent.sock"
解説
- コンテナー起動時、マウントされたソケットファイルの所有者は
root:root、パーミッションは660になっています -
nodeユーザー(このDevContainerのデフォルトユーザー)がアクセスできるように、所有者を変更します - パーミッションを
600(所有者のみ読み書き可能)に設定することで、セキュリティを強化します
ステップ3: DevContainerのリビルド
VS Codeのコマンドパレット(Cmd+Shift+P)から「Dev Containers: Rebuild Container」を実行し、コンテナーをリビルドします。
動作確認
DevContainer内のターミナルで以下のコマンドを実行し、正しく動作しているか確認します。
ssh-add -l
期待される出力
1Passwordに保存されているSSH鍵の一覧が表示されれば成功です。
256 SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (ED25519)
SSH Agentを共有すると何ができるか
SSH Agentが正しく動作することで、以下のような用途にSSH鍵を利用できるようになります:
- Gitコミットの署名:SSH鍵を使った署名付きコミットが可能になります
- GitHubへのSSHアクセス:SSH認証を設定している場合、
git cloneやgit pushなどのGit操作が可能になります - その他のSSH接続:リモートサーバーへの接続など、SSH鍵を必要とする操作が可能になります
1Password SSH Agentを使う利点
- 秘密鍵のコピー不要:秘密鍵はコンテナー内に存在せず、1Passwordで安全に管理されます
- ユーザーによる認証と使用許可:SSH鍵を使う操作を実行すると、ホストOS上で1Passwordの認証プロンプトが表示されます(TouchID、Face IDやパスワード認証など)。ここで署名を拒否すると処理が中断され、コマンドが失敗します。これにより、マルウェアなどが鍵データを悪用しようとしても、ユーザーが処理を中断できます
- 一時的なアクセス:コンテナー停止時は自動的にアクセスが切断されます
ハマったポイント
DevContainer内で1Password SSH Agentを使う際、mountsプロパティを使ったアプローチも試しましたが、Unixソケットのマウントでは問題が発生しました。
実験1: mountsでtype=bindを使った場合
"mounts": [
"source=${localEnv:HOME}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock,target=/tmp/1password-agent.sock,type=bind"
]
結果: ❌ 失敗
ソケットファイルではなく、ディレクトリが作られてしまう問題が発生しました。
$ ls -la /tmp/1password-agent.sock
drwxr-xr-x 2 root root 40 Nov 16 10:00 1password-agent.sock/
実験2: mountsでtype=volumeを使った場合
"mounts": [
"source=${localEnv:HOME}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock,target=/tmp/1password-agent.sock,type=volume"
]
結果: ❌ 失敗
コンテナーのビルド自体が失敗しました。volumeタイプはホストファイルシステムのパスをサポートしていません。
結論: runArgs+-vが正解
Unixソケットファイルのマウントには、runArgsでdocker runの-vオプションを直接指定する方法が正しく動作します。
"runArgs": [
"-v",
"${localEnv:HOME}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock:/tmp/1password-agent.sock"
]
補足: Docker Desktop公式方式との比較
Docker Desktop for Mac 2.2.0.0以降には、SSH Agent転送の公式機能があります(公式ドキュメント)。
Docker Desktop公式方式
{
"mounts": [
"source=/run/host-services/ssh-auth.sock,target=/run/host-services/ssh-auth.sock,type=bind"
],
"containerEnv": {
"SSH_AUTH_SOCK": "/run/host-services/ssh-auth.sock"
}
}
この方式では、Docker Desktopがホストの$SSH_AUTH_SOCK環境変数が指すソケットをコンテナーに転送します。
どちらを選ぶべきか
一般的には、Docker Desktop公式方式($SSH_AUTH_SOCKを使う方式)を推奨します。
この方式では、ホスト側で以下の設定を行います:
## .zshrcなどに追加
export SSH_AUTH_SOCK="$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
これでホスト側の環境変数$SSH_AUTH_SOCKが、1Password SSH Agentのソケットを指すようになります。
参考: 1Password SSH Agent - SSH_AUTH_SOCK
Docker Desktop公式方式の利点
- プラットフォーム非依存(macOS/Linux対応)
- 複数のSSH Agent実装を切り替えやすい
-
postStartCommandでの権限設定が不要 - チームで共有しやすい
なぜこの記事では直接マウント方式を使うのか
この記事では、実験的に直接マウント方式を採用しています。その理由は:
- macOSのデフォルト
$SSH_AUTH_SOCK(システムキーチェーン)との違いを明確にするため - 1Passwordソケットの場所を明示的に指定することで、設定内容がより理解しやすくなるため
トラブルシューティング
Error connecting to agent: Permission denied
原因
ソケットファイルの権限が正しく設定されていない
対処法
-
postStartCommandが正しく実行されているか確認 - ソケットファイルのパーミッションを確認:
ls -la /tmp/1password-agent.sock - コンテナーをリビルド: "Dev Containers: Rebuild Container"
The agent has no identities
原因
ホスト上の1Passwordが起動していない、またはSSH Agent機能が無効
対処法
- ホストOS上で1Passwordアプリが起動しているか確認
- 1PasswordのSSH Agent機能が有効になっているか確認(Settings → Developer → SSH Agent)
- ホストで1Passwordソケットをテスト:
SSH_AUTH_SOCK="$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" ssh-add -l
Gitコミット時にCouldn't find key in agent?
原因
環境変数が正しく設定されていない、または鍵が1Passwordに登録されていない
対処法
- コンテナー内の
SSH_AUTH_SOCK環境変数が正しく設定されているか確認:echo $SSH_AUTH_SOCK/tmp/1password-agent.sockと表示されるはず - 1Passwordに署名用のSSH鍵が登録されているか確認
-
.gitconfigのuser.signingkeyが1Passwordの鍵と一致しているか確認
ソケットがマウントされない
原因
ソケットパスが間違っている、またはDocker Desktopの問題
対処法
- ホストOSのソケットパスが正しいか確認
ls -la ~/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock - Docker Desktopを再起動
- コンテナーをリビルド
まとめ
DevContainer内から1Password SSH Agentを使うには、以下の3つの設定が必要です:
-
runArgs: Unixソケットを
-vオプションでマウント(mountsではなくrunArgsを使う) -
remoteEnv:
SSH_AUTH_SOCK環境変数を設定 - postStartCommand: ソケットファイルの権限を調整
この設定により、秘密鍵をコンテナー内に置くことなく、安全にSSH認証を行えます。