DockerコンテナにSSHで接続する方法について詳しく説明しました。このチュートリアルでは、Dockerへのリモートアクセスを有効にすることで、同じ概念を別のレベルに引き上げます。
dockerリモートアクセスを使用すると、ローカルホストでdockerコマンドを実行するたびに、リモートサーバーで効果が発生します。
詳細に説明させてください。
Dockerリモートアクセスとは何ですか?
セットアップに飛び込む前に、dockerがどのように機能するかを思い出させてください。
Dockerは、クライアントサーバーアーキテクチャと呼ばれるもので動作します。すべてのコンテナ、ボリューム、ネットワークなどを処理する主要なコンポーネントは、バックグラウンドで実行されるdockerデーモンです。
docker
コマンドはクライアントアプリケーションに他なりません。クライアントとデーモンは、/run/docker.sock
にある従来のUnixソケットを介してdockerAPIを介して通信します。 または/var/run/docker.sock
。クライアントはデーモンに何かをするか、情報を取得するように要求し、デーモンはまさにそれを行います。
これはどのようにあなたに興味を持っていますか? Dockerクライアントとサーバー間で使用される通信プロトコルはプレーンHTTPであるため、ローカルUNIXソケットではなくポートでデーモンにHTTP要求をリッスンさせることができれば、サーバーにリモートで要求を送信できるはずです。
>結局のところ、あなたは完全にそれを行うことができます。デーモンは実際、UNIXソケットだけでなくTCPポートでもリッスンできます。 Dockerバージョン18.09以降では、それだけでは不十分であるかのように、通信プロトコルにSSHを使用することもできます。
このチュートリアルでは、docker
を使用できるように、ホストとリモートサーバーを構成する方法のプロセス全体を説明します。 リモートサーバーにSSHで接続しなくても、あるホストからコマンドを実行し、別のホストで実行できます。
このアプローチの利点についてまだ疑問に思っていますか?それらのいくつかを次に示します。
- サービスを開始または停止するためにサーバーにログインする必要はありません。すべてリモートで実行できます。
- Portainerなどの多くの監視ツールは、ネットワークや実行中のコンテナーなどの詳細を監視するためにDocker APIエンドポイントにアクセスする必要があります。通常、サーバーをエンドポイントリストに追加するには、サーバーにPortainerエージェントをデプロイする必要があります。まず、コンテナからホストにポートをバインドします。代わりに、Dockerデーモンに直接アクセスさせることができます。これにより、多くのリソースを節約できます。
- ローカルコンピューターでさまざまな自動化スクリプトを記述して、1つ以上のリモートDockerサーバーを制御/管理できます。リモートサーバーにSSHで接続する必要がないため、安定した接続を維持する必要はありません。これは、インターネット接続が不安定または遅い場合に適したオプションです。
- ローカルシステムがコンテナを実行するのに十分な能力を備えていない場合、または十分なストレージがない場合は、Dockerホストにリモートサーバーを使用し、TCPポートまたはSSHを介してリモートで制御できます。
- 前のポイントを拡張して、クラウド上のサーバーは現在非常にスケーラブルです。コストに問題がない限り、新しいSSDまたはHDDを購入することを心配することなく(まだ使用している場合)、必要に応じてDockerホストを拡張できます。
利点自体は、問題の人が本当にこれを必要としているかどうかに応じて、スケールアップまたはスケールダウンすることができます。そうでなければ、それで結構です。しかし、あなたがそうするなら、あなたは正しい場所にいます。
Dockerリモートアクセスは安全ですか?
dockerの友達はすでにこれを検討しています。中間プロトコルにSSHを使用すると、SSHセッションと同じくらい安全です。これについては、このチュートリアルの後のセクションで詳しく説明します。
SSHの使用に熱心でない場合は、認証の形式を使用せずにパブリックポートを介してAPIを公開することは、現時点では必ずしも最善のアイデアではありませんか?
そのため、TLS認証を使用しています。他の誰かが(CA証明書とともに)あなたのCAによって署名された証明書を持っていない限り、その人はあなたに害を及ぼすことはできません。
次の図はこれを説明しています:

まず、SSHを使用して、このセットアップ用にローカルサーバーとリモートサーバーを構成する方法について説明します。他の方法が少し難しいと思われる場合は、このルートを使用することをお勧めします。
この設定には何が必要ですか?
先に進む前に、いくつかのことが必要です。いくつかは必須で、いくつかはオプションです。
- これはすでにかなり明確なので、クラウド上にサーバーが必要になります。個人的にはLinodeをお勧めします。
- Dockerはこのリモートサーバーにインストールする必要があります。 UbuntuとCentOSへのDockerのインストールに関するガイドを参照してください。
- オプションで、
openssl
に関する知識> TCPポート方式の使用を計画している場合は、有益な場合があります。 - SSH公開鍵認証を介したサーバーへのアクセス。
方法1:SSHを使用してリモートDockerアクセスを設定する
ここでSSHを使用することの最も良い点の1つは、他の方法よりもはるかに少ない作業で済むことです。すでにSSHキーを設定している場合は、文字通り1ステップのプロセスです。
先に進む前に、このSSH方式がどのように機能するのか、そしてなぜそれが構成されているように構成されているのかを理解するために、この心構えを理解してもらいたいと思います。
リモートDockerアクセスにSSHプロトコルを使用すると、Dockerクライアントが実際にローカルホストでsshコマンドを実行し、リモートホストで非表示のDockerコマンド(docker system dial-stdio)を実行して、リモートのほとんどの場合/var/run/docker.sockであるdockerdエンドポイント、およびコマンドstdioへの接続を転送します。
上記のステートメントを確認するには、任意のdocker
を実行します -l debug
を使用して、このセクションの最後にあるコマンド(テスト中) 国旗。これにより、ローカルマシンで実行されている正確なコマンドが出力されます。
この構成の前提条件は次のとおりです。
1。 SSH公開鍵認証
参加しているマシン間でSSH公開鍵認証を有効にする必要があります。これがあなたがそうすることができる方法の簡単な要約です、
- コマンド
ssh-keygen
を使用します 公開鍵と秘密鍵のペアを生成します。 -
ssh-copy-id [email protected]
を使用します 公開鍵をリモートサーバーにコピーするコマンド。 -
PubKeyAuthentication
を確認してくださいyes
に設定されています リモートSSHD構成ファイル内。さらに、パスワード認証をオフにすることをお勧めします(PasswordAuthentication
を設定します)no
。


2。ログインユーザーはdockerグループに属している必要があります
事実上、ユーザーとしてログインし、docker
をリクエストしているためです。 サーバーに情報を提供したり、何かを行うには、リモートユーザー(ログインしているユーザー)が、リモートの「ローカルDOCKER_HOST」(前述のとおり、ほとんどの場合/var/run/docker.sock
)。そのリモートユーザーをdocker
に追加することで、その権限を取得できます グループ。
「リモートローカルDOCKER_HOST」とは、リモートサーバーのローカルDOCKER_HOSTを意味します。
私は個人的にdocker
を使用するのが好きではないので、これは私のような多くの人にとってはオフになる可能性があります sudo
のグループ -実行が少ない。
usermodコマンドを使用して、既存のユーザーをdocker
に追加できます。 グループ。
sudo usermod -aG docker [username]
Dockerサーバーを制御する場所からローカルの個人用システムを微調整する必要があるものは次のとおりです。
1。ローカルシステムでDOCKER_HOSTを変更します
信じられないかもしれませんが、ここで行うことは1つだけです。環境変数DOCKER_HOST
を設定します リモートユーザー名、サーバーIP、およびsshdが実行されているポートの正しい組み合わせに。このように:
DOCKER_HOST=ssh://[email protected]:22
または、-H
を使用することもできます docker
でここで行ったようなフラグ コマンド
docker -H ssh://[email protected] info
代わりに、次のようにLinuxにエイリアスを追加できます。
alias docker="docker -H ssh://[email protected]:22"
どちらの方法(環境変数またはエイリアス)を選択したかは関係ありません。これをテストするには、docker info
のような単純なdockerコマンドを実行するだけです。 。
また、docker -l debug info
を実行してみてください コマンドが実行されていることに注意してください。
方法2:TLS認証でパブリックTCPポートを使用する
この方法は前の方法よりも複雑ですが、docker
を使用する必要がないなどの利点があります。 グループ全体。
ここでの考え方は単純です。独自の証明書と秘密鍵を作成し、TCPポートを使用してdocker
にアクセスします。 プレーンHTTPではなく、安全なHTTPSチャネルを介したデーモン。
それはウェブサイトに似ています。 Webサイトの場合、さまざまなキーと証明書を使用するようにWebサーバーで構成します。これらのキーと証明書は、後でブラウザーによって有効であり、信頼できる組織(Let's EncryptやDigiCertなど)によって検証されます。その検証が完了すると、暗号化されたHTTPリクエストがWebサーバーに送信され、必要なデータが取得されます。
同様に、ここでは、従来のWebサーバーの代わりに、docker
を構成します。 特定の証明書と秘密鍵を使用するデーモンのサーバー。したがって、誰かがデーモンサーバーに要求を送信しようとするときはいつでも、ステップ1は、クライアントが同じCA証明書を持ち、証明書がそのCAによって署名されている限り、参加者が信頼できることを確認することです。接続が確立されます。クライアントは[暗号化された]リクエストをサーバーに送信できるようになります。
次の手順では、サーバーとクライアントの証明書と秘密鍵を生成します。
認証局
トランザクションを簡単にするために、クライアントマシンを使用してすべてのファイルを生成します。必要に応じて、そのために別のマシンを使用できます。 CA証明書は、自己署名証明書に他なりません。
ただし、最初に、CAの秘密鍵を生成する必要があります。これを行うには、次のコマンドを使用します
openssl genrsa -aes256 -out ca-key.pem 4096
コマンドを分解してみましょう:
- genrsa :このオプションは、
openssl
に通知します RSAアルゴリズムに基づいて秘密鍵を生成します。 - -aes256 :これは、256ビットのAESを使用して、ユーザーが指定したパスフレーズで秘密鍵を暗号化します。 AESは、単なる暗号化技術(Advanced Encryption Standard)です。
- -アウト :出力ファイル名を指定します。
- 最後に、キーの長さ(ビット単位)を入力します。
キーを保護するためのパスフレーズを提供します。次に、CAの証明書を作成します。この証明書は、作成したばかりのキーで署名されます。次のコマンドを使用して作成します:
openssl req -x509 -new -key ca-key.pem -days 365 -subj '/CN=CertificateAuthority' -out ca-cert.pem
多くの人にとって、これは謎のように見えるかもしれません。さて、あなたのためにそれを分解させてください:
- req :このオプションは、主にCSRを作成するために使用されます。ここでは、これを使用して自己署名証明書を作成しています。
- -x509 :これは
openssl
に通知します CSRの代わりに署名付き証明書を生成します。 - 新しい :これにより、新しい証明書リクエストが作成され、関連するフィールド値をユーザーに尋ねられます。
- -キー :使用するキー。
- -日 :証明書の有効期間(日数)。
- -subj :すべての詳細の入力を求められる代わりに、このオプションを使用して関連するフィールド値を直接割り当てます。ここでのみ共通名を設定しました。このフラグは省略でき、すべての詳細の入力を求められます。
- -アウト :出力ファイル名。
プロンプトが表示されたら、キーのパスフレーズを入力します。
Dockerサーバー
次に、サーバーの証明書と秘密鍵を生成する必要があります。
このためには、最初にCSR、証明書署名要求を作成し、次にCAによって署名されます。最初に秘密鍵を生成します:
openssl genrsa -out server-key.pem 2048
構文は、例外を除いて、前に使用したものと同じです。 1つは、今回はキーを暗号化しないことです。他のプログラムはこのファイルを無人で読み取る必要があるため、暗号化すると、いくつかのエラーが発生します。 2つ目は、ここでのキーの長さは256バイトです。 CAのキーを長くすることを選択しました。これにも同じ長さを使用できます。これは、自由に使用できるさまざまなオプションを示すためです。
次にCSRを生成します:
openssl req -new -key server-key.pem -subj '/CN=docker-host' -out server.csr
/etc/hosts
を編集します ファイルを作成し、DockerホストのIPを一定のホスト名で追加します。このホストにアクセスしたいすべてのクライアントにこれを追加する必要があります。このホストのIPにFQDNが割り当てられている場合は、代わりにそれを使用できます。 FQDN、完全修飾ドメイン名は、DNSサーバーのIPに関連付けられているドメイン名です。これはローカルホスト名ではありません。 FQDNは、パブリックDNSレコードの一部であり、リゾルバーがそのDNSサーバーを使用している限り、LANだけでなく世界中のどこでもIPに解決されます。
フラグは、CA証明書を生成するときに使用したものと同じです。ここには-x509
がありません これは自己署名証明書ではないため、CAがこれに署名します。したがって、署名してください
openssl x509 -req -days 365 -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile <(echo "extendedKeyUsage = serverAuth") -out server-cert.pem
- x509 :このオプションは、CSRに署名するために使用されます。
- -req :このオプションは
openssl
にあります CSRを期待する。 - -in :CSRファイルを渡します。
- オプション-CA 、 -CAkey CA証明書とCAキーをそれぞれ引数として取ります。
- -CAcreateserial :このオプションを使用すると、
openssl
CAシリアル番号ファイルがまだ存在しない場合は作成します。 - -extfile :使用する証明書拡張子を含むファイルを渡します。ここでは、
extendedKeyUsage
を使用しました 拡張機能。
これで、CA署名付きサーバー証明書server-cert.pem
が必要になります。 およびサーバーの秘密鍵server-key.pem
。
Dockerクライアント
次に、Dockerクライアントをセットアップする必要があります。プロセスは以前と多少同じです。秘密鍵を作成し、CSRを生成し、CAでそのCSRに署名します。
わかりやすくするために、これらについてはここで説明します。秘密鍵を生成します:
openssl genrsa -out client-key.pem 2048
次に、CSRを生成します:
openssl req -new -key client-key.pem -subj '/CN=docker-client' -out client.csr
ここで、CNの値としてクライアントのホスト名を入力します。最後に、CSRに署名します:
openssl x509 -req -days 365 -in client.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile <(echo "extendedKeyUsage = clientAuth") -out client-cert.pem
ここでの唯一の違いは、「拡張キー使用法」拡張値です。 clientAuth
があります serverAuth
の代わりに 。プロンプトが表示されたらパスフレーズを入力します。
証明書と秘密鍵の準備ができたら、Dockerエンジンとクライアントにそれらについて通知する必要があります。また、エンジンAPIをパブリックTCPポートに公開し、クライアントがローカルマシンにないDockerエンジンを使用できるようにする必要があります。
次の手順はまさにそれを実行します。
Dockerホスト
まず、管理者のマシンであるCA証明書(ca-cert.pem
)から3つのファイルをコピーします。 )、このホストの秘密鍵(server-key.pem
)およびCA署名付き証明書(server-cert.pem
)。ディレクトリを作成します/etc/docker/certs
これらのファイルを保持します。
sudo mkdir /etc/docker/certs
次に、デーモン構成ファイルを開き、以下を追加します(構成は/etc/docker/daemon.json
にあります) ):
{
"tlsverify": true,
"tlscacert": "/etc/docker/certs/ca-cert.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"host": "tcp://0.0.0.0:2376"
}
最後のオプションは、デーモンにTCPポート2376をリッスンするように指示します。ファイルを保存してdockerを再起動します。
sudo systemctl restart docker
チームがdocker
の背後にいる間 これにはポート2376を使用することをお勧めします。理論的には、他の未使用/予約されていないポートを使用できます。
クライアント
クライアント側は、間違いなくセットアップが簡単です。ディレクトリ~/.docker
を作成します :
mkdir ~/.docker
そのディレクトリ内に、以下のように正しい名前で3つのファイルを配置します(この記事で以前に使用した名前は、これらの括弧内に配置されています)
- ca.pem :CA証明書(
ca-cert.pem
。 - key.pem :クライアントの秘密鍵(
client-key.pem
。 - cert.pem :クライアントの証明書(
client-cert.pem
。
次に、2つの環境変数を設定します
- DOCKER_HOST この変数の値を
tcp://docker-host:2376
に設定します 。/etc/hosts
で設定したホスト名を使用します 対応するhost/ipのファイル。 - DOCKER_TLS_VERIFY これを1に設定します。
~/.bashrc
を使用できます これらを自動的に構成します。 exportコマンドを使用して、次の変数を設定します。
export DOCKER_HOST=tcp://docker-host:2376
export DOCKER_TLS_VERIFY=1
ここでも、ホスト名には、/etc/hosts
の適切な値を使用します。 。このIPのFQDNがある場合は、代わりにそれを使用してください。
すべてが完了したので、docker info
を実行してテストできます。 、または任意のランダムコンテナを実行します。 curl
を使用することもできます それをテストします(覚えていますか?これらは単純なHTTPリクエストです)。 docker info
の代わりに以下を使用してください
curl https://docker-host:2376/info --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem
これにより、jq
などを使用して解析できるJSONオブジェクトが出力されます。 。 Dockerを使用してNginxサーバーを実行してみて、どのシステムで実行されているかを確認することもできます。視覚的には、Dockerがローカルシステムで実行されているように見えるため、これは実行できる主要な例/テストです。実行するだけです
docker run -d --rm --name remote_nginx -p 8080:80 nginx:latest
ここで、curl
を使用します ローカルホストとリモートIPの両方をチェックします。最初のローカルホスト、
curl http://localhost:8080
このような出力が表示されるはずです
curl: (7) Failed to connect to localhost port 8080: Connection refused
次に、リモートIPでも同じことを試してください。
curl http://docker-host:8080
そこにnginxのテンプレートサイトが表示されます。ブラウザを使用して、これらの場所、ローカルホスト、およびリモートホストをサーフィンすることもできます。
どのメソッドを使用しますか? TCPまたはSSH?
どちらの方法にもメリットがあります。多くのフープを通過したくない場合は、SSH方式の方が簡単です。ただし、Portainerなどの一部のアプリケーションは、リモートデーモンアクセス用のSSH方式では機能しません。 TCP方式を使用すると、デフォルトで「Dockerグループを使用するかどうか」の問題も解消されます。目的に合った方法を選択してください。
このチュートリアルがお役に立てば幸いです。ご不明な点がございましたら、下のコメント欄でお知らせください。