Mac OS XでDocker Machine(デフォルトのboot2dockerマシンを使用)でDockerを使用しており、docker-composeを使用して開発環境をセットアップしています。
コンテナの1つが「stack
」と呼ばれるとしましょう。今私がしたいのは電話です:
docker-composer run stack ssh [email protected]
私の公開鍵(stackoverflow.com
および私を認証するために使用されます)は、ホストマシンにあります。このキーをDocker Machineコンテナーで使用できるようにして、コンテナー内からそのキーを使用してstackoverflow
に対して自分自身を認証できるようにします。できれば、物理的にキーをDocker Machineにコピーせずに。
これを行う方法はありますか?また、キーがパスワードで保護されている場合、一度ロックを解除する方法はありますか?
これをdocker-compose.ymlに追加できます(コンテナ内のユーザーがrootであると仮定):
volumes:
- ~/.ssh:/root/.ssh
また、 sshエージェントを使用したより高度なソリューション (自分で試していませんでした)を確認することもできます
Dockerにはsecretsという機能があります。これはここで役立ちます。それを使用するには、次のコードをdocker-compose.yml
に追加できます。
---
version: '3.1' # Note the minimum file version for this feature to work
services:
stack:
...
secrets:
- Host_ssh_key
secrets:
Host_ssh_key:
file: ~/.ssh/id_rsa
次に、次のようにDockerfile
で新しいシークレットファイルにアクセスできます。
RUN mkdir ~/.ssh && ln -s /run/secrets/Host_ssh_key ~/.ssh/id_rsa
秘密ファイルはコンテナにコピーされません:
新しく作成されたサービスまたは実行中のサービスにシークレットへのアクセスを許可すると、復号化されたシークレットはインメモリファイルシステムのコンテナにマウントされます
詳細については、以下を参照してください。
OS Xと暗号化されたキーを使用している場合、これはPITAになります。 手順は次のとおりです 私はこれを理解しました。
問題ないと思うかもしれません。 sshフォルダーをマウントするだけです:
...
volumes:
- ~/.ssh:/root/.ssh:ro
...
これでうまくいくはずですよね?
次に気付くのは、間違ったユーザーIDを使用していることです。 sshキーの所有者をコピーして変更するスクリプトを作成します。また、sshサーバーがだれが接続しているかを知るために、設定でsshユーザーを設定します。
...
volumes:
- ~/.ssh:/root/.ssh-keys:ro
command: sh -c ‘./.ssh-keys.sh && ...’
environment:
SSH_USER: $USER
...
# ssh-keys.sh
mkdir -p ~/.ssh
cp -r /root/.ssh-keys/* ~/.ssh/
chown -R $(id -u):$(id -g) ~/.ssh
cat <<EOF >> ~/.ssh/config
User $SSH_USER
EOF
当社では、パスフレーズを使用してSSHキーを保護しています。コンテナを起動するたびにパスフレーズを入力することは実用的ではないため、Dockerでは機能しません。パスフレーズを削除することもできます(以下の例を参照)が、セキュリティ上の懸念があります。
openssl rsa -in id_rsa -out id_rsa2
# enter passphrase
# replace passphrase-encrypted key with plaintext key:
mv id_rsa2 id_rsa
ローカルでsshアクセスが必要になるたびにパスフレーズを入力する必要がないことに気づいたかもしれません。何故ですか?それがSSHエージェントの目的です。 SSHエージェントは基本的に、「ssh auth sock」と呼ばれる特別なファイル、unixソケットをリッスンするサーバーです。システム上の場所を確認できます。
echo $SSH_AUTH_SOCK
# /run/user/1000/keyring-AvTfL3/ssh
SSHクライアントはこのファイルを介してSSHエージェントと通信するため、パスフレーズは1回だけ入力します。暗号化されていない場合、SSHエージェントはそれをメモリに保存し、リクエストに応じてSSHクライアントに送信します。これをDockerで使用できますか?もちろん、その特殊ファイルをマウントして、対応する環境変数を指定するだけです。
environment:
SSH_AUTH_SOCK: $SSH_AUTH_SOCK
...
volumes:
- $SSH_AUTH_SOCK:$SSH_AUTH_SOCK
この場合、キーをコピーする必要さえありません。キーが利用可能であることを確認するために、ssh-addユーティリティを使用できます。
if [ -z "$SSH_AUTH_SOCK" ]; then
echo "No ssh agent detected"
else
echo $SSH_AUTH_SOCK
ssh-add -l
fi
OS Xユーザーにとって残念なことに、Docker for Macにはいくつかの欠点があります。その1つは、MacとLinuxの間でUnixソケットを共有できないことです。 D4M Githubの未解決の問題 があります。 2019年2月の時点ではまだ開いています。
それで、それは行き止まりですか?いいえ、ハッキーな回避策があります。
幸いなことに、この問題は新しいものではありません。 Dockerよりもずっと前に、リモートsshセッション内でローカルsshキーを使用する方法がありました。これは、sshエージェント転送と呼ばれます。アイデアは簡単です。sshを介してリモートサーバーに接続し、そこにあるすべての同じリモートサーバーを使用して、キーを共有できます。
Docker for Macでは、TCP ssh接続を使用してsshエージェントをdocker仮想マシンと共有し、そのファイルを仮想マシンからそのSSH接続が必要な別のコンテナにマウントします。ソリューションを示すための写真を次に示します。
まず、linux VM through a TCP port。ここで実際のssh auth sockを使用します。)内のコンテナー内のsshサーバーへのsshセッションを作成します。
次に、sshサーバーはsshキーをそのコンテナのsshエージェントに転送します。 SSHエージェントには、Linux VMにマウントされた場所を使用するUnixソケットがあります。つまりUnixソケットはLinuxで動作します。 Macで動作しないUnixソケットファイルは効果がありません。
その後、SSHクライアントを使用して便利なコンテナを作成します。ローカルSSHセッションが使用するUnixソケットファイルを共有します。
そのプロセスを簡素化するスクリプトがたくさんあります: https://github.com/avsm/docker-ssh-agent-forward
DockerでSSHを機能させるのは簡単だったでしょう。しかし、それはできます。そして、今後改善される可能性があります。少なくともDocker開発者はこの問題を認識しています。そして ビルド時の秘密を持つDockerfilesのためにそれを解決した 。そして 提案があります Unixドメインソケットをサポートする方法。
SSHエージェントを転送できます:
something:
container_name: something
volumes:
- $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
environment:
SSH_AUTH_SOCK: /ssh-agent