ドッカーを使用してリモートのドッカーホストにデプロイする方法

Compose

docker-composeツールは、ローカル開発環境でドッキングされたアプリケーションを実行するために非常に人気があります。必要なのは、アプリケーションのサービスの構成を含むComposeファイルを作成し、デプロイ用に実行中のDockerエンジンを用意することだけです。 ここから、単一の 「docker-compose up」 コマンドで数秒でアプリケーションをローカルで実行できます。 

これは最初の範囲でしたが...

開発者は、CIパイプライン/本番環境での開発環境と同じデプロイの容易さを求めているため、今日、docker-composeはさまざまな方法で、当初の範囲を超えて使用されていることがわかります。 このような場合の課題は、docker-compose が DOCKER_HOST 環境変数-H, –host コマンドラインオプションを使用して、リモートの Docker エンジンでの実行のサポートを提供していたことです。 これはあまりユーザーフレンドリーではなく、複数の環境にまたがるComposeアプリケーションの展開を管理することは負担になります。

この問題に対処するために、 Docker Contexts を使用して、さまざまな環境にComposeアプリケーションを安全にデプロイし、ローカルホストから簡単に管理します。 この投稿の目的は、コンテキストを使用してさまざまな環境をデプロイの対象とし、それらを簡単に切り替える方法を示すことです。

この演習全体で使用するサンプル アプリケーションの定義を開始し、それを localhost にデプロイする方法を示します。 さらに、Dockerコンテキストと、リモートのDockerエンジンに安全に接続できるように保持する情報について説明します。 最後に、docker-compose で Docker コンテキストを使用して、リモート エンジンにデプロイします。

続行する前に、ドッカーとドッカー作成をローカルホストにインストールする必要があります。 Docker Engine と Compose は、 Docker Desktop for Windows および macOS に含まれています。 Linuxの場合は、Docker Engineとdocker-composeを入手する必要があります。コンテキストサポート機能を使用してdocker-composeを取得するようにしてください。 これは、docker-compose のリリース 1.26.0-rc2 以降で使用できます。

サンプル作成アプリケーション

フロントエンドとバックエンドの2つのサービスで構成されるアプリケーションを記述するComposeファイルを定義しましょう。 フロントエンドサービスは、HTTPリクエストを単純なGoアプリサーバーに転送するnginxプロキシを実行します。 

この演習に必要なすべてのファイルを含むサンプルを ここから ダウンロードするか、代わりに Compose samples リポジトリの他のサンプルを使用できます。

プロジェクト構造と作成ファイルは以下にあります。

$ tree hello-docker
hello-docker
├── backend
│ ├── Dockerfile
│ └── main.go
├── docker-compose.yml
└── frontend
├── Dockerfile
└── nginx.conf

docker-compose.yml

version: "3.6"
services:
  frontend:
    build: frontend   
    ports:
    - 8080:80
    depends_on:
    - backend
  backend:
    build: backend

ローカルホストでの実行

前に定義したアプリケーションをデプロイするには、プロジェクト ディレクトリに移動し、docker-compose を実行します。

$ cd hello-docker/
$ docker-compose up -d
Creating network "hello-docker_default" with the default driver
Creating hello-docker_backend_1 ... done
Creating hello-docker_frontend_1     ... done

docker-compose.yml で説明されているように、すべてのコンテナーが実行されており、フロントエンド サービス コンテナーのポート 80 がローカルホストのポート 8080 にマップされていることを確認します。

$ docker ps
CONTAINER ID  IMAGE                  COMMAND                 CREATED        STATUS
  PORTS                   NAMES
07b55d101e74  nginx:latest           "nginx -g 'daemon of..."  6 seconds ago  Up 5 seconds
  0.0.0.0:8080->80/tcp    hello-docker_frontend_1
48cdf1b8417c  hello-docker_backend   "/usr/local/bin/back..."  6 seconds ago  Up 5 seconds                           hello-docker_backend_1

ポート 8080 で Web サービスを照会して、go バックエンドから hello メッセージを取得します。

$ curl localhost:8080
          ##         .
    ## ## ##        ==
## ## ## ## ##     ===
/"""""""""""""""""\___/ ===
{                       / ===-
\______ O           __/
 \    \         __/
  \____\_______/
Hello from Docker!

リモートホストでの実行

リモートのDockerホストは、Dockerエンジンを実行し、エンジンAPIを照会するためにポートが公開されているローカルネットワークの内部または外部のマシンです。

サンプル・アプリケーションは、いくつかの方法でリモート・ホストにデプロイできます。 アプリケーションのデプロイ時にパスワードプロンプトが表示されないように、キーベースの認証を使用してリモートDockerホストにSSHアクセスできると仮定します。

リモートホストにデプロイするには、次の 3 つの方法があります。

1.プロジェクトファイルのコピーによる手動デプロイ、docker-composeをインストールして実行

Composeの一般的な使用法は、 docker-compose.ymlを使用してプロジェクトソースをコピーすることです。 作成アプリをデプロイするターゲットマシンにdocker-composeをインストールし、最後に実行します。

$ scp -r hello-docker user@remotehost:/path/to/src
$ ssh user@remotehost
$ pip install docker-compose
$ cd /path/to/src/hello-docker
$ docker-compose up -d

この場合の欠点は、アプリケーションソースまたはComposeファイルを変更すると、コピーしてリモートホストに接続し、再実行する必要があることです。

2. 環境変数を使用してDOCKER_HOSTターゲットエンジンを設定する

この演習では、 DOCKER_HOST 環境変数シナリオを使用して Docker ホストをターゲットにしますが 、-H, –host 引数を docker-compose に渡すことで同じことを実現できます。

$ cd hello-docker
$ DOCKER_HOST="ssh://user@remotehost" docker-compose up -d

これは、手動展開よりも優れた方法です。 しかし、アプリケーションの変更やホストの変更ごとにリモートホストエンドポイントを設定/エクスポートする必要があるため、非常に面倒です。

3.ドッカーコンテキストの使用 

$ ドッカーコンテキストls
名前 説明 DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
...
リモート ssh://user@remotemachine
$ cd hello-docker
$ docker-compose ‐‐context remote up -d

Docker コンテキストは、異なるデプロイメント・ターゲットを自動的に切り替える効率的な方法です。 次のセクションでは、Dockerコンテキストをcomposeとともに使用してデプロイを容易/高速化する方法を理解するために、コンテキストについて説明します。

ドッカーコンテキスト

Docker コンテキストは、Docker API エンドポイントに名前を提供し、後で使用するためにその情報を格納するメカニズムです。 ドッカー コンテキストは、 ドキュメントに示されているように、Docker CLI を使用して簡単に管理できます。 

リモートホストをターゲットとするコンテキストを作成して使用する

Dockerクライアントを使用してリモートホストに簡単にアクセスするには、まず、リモートホストへの接続パスを保持するコンテキストを作成します。

$ ドッカーコンテキスト作成リモート ‐‐ドッカー " host=ssh://user@remotemachine"
遠隔
コンテキスト「リモート」が正常に作成されました

$ ドッカーコンテキストls
名前 説明 DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
デフォルト * 現在のDOCKER_HOST...  unix:///var/run/docker.sock 群れ
リモート ssh://user@remotemachine

SSHingのキーベースの認証をリモートホストに設定していることを確認してください。 これが完了すると、コンテキスト名を引数として渡すことで、リモートホスト上のコンテナを一覧表示できます。

$ ドッカー ‐‐ コンテキスト リモート ps
コンテナIDイメージコマンド作成ステータス名

「リモート」コンテキストをDockerコマンドのデフォルトコンテキストとして設定することもできます。 これにより、各コマンドでコンテキスト引数を渡さずに、リモートホストですべてのdockerコマンドを直接実行できます。

$ Dockerコンテキストはリモートを使用します
遠隔
現在のコンテキストが「リモート」になりました
$ ドッカーコンテキストls
名前 説明 DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
デフォルト 現在のDOCKER_HOST ...  unix:///var/run/docker.sock 群れ
リモート * ssh://user@remotemachine

ドッカー作成コンテキストの使用

docker-compose の最新リリースでは、Docker API エンドポイントにアクセスするためのコンテキストの使用がサポートされるようになりました。 これは、docker-composeを実行し、コンテキスト「remote」を指定して、リモートホストを自動的にターゲットにできることを意味します。 コンテキストが指定されていない場合、docker-compose は Docker CLI と同様に現在のコンテキストを使用します。

$ docker-compose ‐‐context remote up -d
/tmp/_MEI4HXgSK/paramiko/client.py:837: ユーザー警告: 不明な ssh-ed25519 10.0.0.52 のホスト キー: b'047f5071513cab8c00d7944ef9d5d1fd'
デフォルトドライバを使用したネットワーク「hello-docker_default」の作成
こんにちはdocker_backend_1を作成する...完成です
こんにちはdocker_frontend_1を作成します...完成です

$ ドッカー ‐‐ コンテキスト リモート ps
コンテナー ID イメージ コマンドが作成されました
ステータス ポート名
ddbb380635aa こんにちはdocker_frontend "nginx -g 'デーモンの..." 24秒前
アップ 23 秒 0.0.0.0:8080->80/tcp hello-docker_web_1
872c6a55316f hello-docker_backend "/usr/local/bin/back..." 25秒前
アップ24秒こんにちはdocker_backend_1

複数のターゲットにまたがるデプロイを作成する

多くの開発者は、切り替える必要がある複数の開発/テスト環境を持っている場合があります。 これらすべてにわたるデプロイは、docker-composeでコンテキストを使用することで簡単になりました。

ここで、複数の Docker エンジン間でコンテキストの切り替えを実行しようとしています。 このために、3つのターゲットを定義します。

  • ローカルの Docker エンジンを実行しているローカルホスト 
  • ssh経由でアクセス可能なリモートホスト
  • 別のリモートホストとして機能する Docker-in-Docker コンテナ 

次の表は、コンテキストを Docker ターゲットにマッピングする方法を示しています。

ターゲット環境コンテキスト名API エンドポイント
ローカルホストデフォルトunix:///var/run/docker.sock
リモートホスト遠隔ssh://user@remotemachine
ドッカー・イン・ドッカー食事tcp://127.0.0.1:2375

ポート 2375 をローカルホストにマップして Docker-in-Docker コンテナーを実行するには、次のコマンドを実行します。

$ docker run -‐rm -d -p "2375: 2375 " ‐‐特権 -e " DOCKER_TLS_CERTDIR=" ‐‐名前ディンド ドッカー:19.03.3-ディンド
ed92bc991bade2d41cab08b8c070c70b788d8ecf9dffc89e8c6379187aed9cdc
$ ドッカー ps
コンテナー ID イメージ コマンドの作成状態
ポート名
ed92bc991bad docker:19.03.3-dind "dockerd-entrypoint...."17秒前 15秒上へ
0.0.0.0:2375->2375/TCP、2376/TCPディンド

新しいコンテキスト 'dind' を作成して、コンテナーを簡単にターゲットにします。

$ ドッカーコンテキスト ディンドを作成する ‐‐ドッカー " ホスト=TCP://127.0.0.1:2375" ‐‐デフォルトスタックオーケストレータスウォーム
食事
コンテキスト "dind" が正常に作成されました

$ ドッカーコンテキストls
名前 説明 DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
デフォルト * 現在のDOCKER_HOST ... unix:///var/run/docker.sock 群れ
リモート ssh://user@devmachine 群

これで、任意の環境をターゲットにして、ローカルホストからComposeアプリケーションをデプロイできるようになりました。

$ ドッカーコンテキスト使用ディンド
食事
現在のコンテキストは "dind" になりました

$ docker-compose up -d
デフォルトドライバを使用したネットワーク「hello-docker_default」の作成
こんにちはdocker_backend_1を作成する...完成です
こんにちはdocker_frontend_1を作成します...完成です

$ ドッカー ps
コンテナー ID イメージ コマンドが作成されました
ステータス ポート名
951784341a0d こんにちはdocker_frontend "nginx -g 'デーモンの..." 34秒前
アップ 33 秒 0.0.0.0:8080->80/tcp hello-docker_frontend_1
872c6a55316f hello-docker_backend "/usr/local/bin/back..." 35秒前
アップ 33 秒 こんにちは-docker_backend_1

$ ドッカー ‐‐ コンテキストのデフォルト ps
コンテナー ID イメージ コマンドが作成されました
ステータス ポート名
ed92bc991bad docker:19.03.3-dind "dockerd-entrypoint...."  28分前
アップ 28 分 0.0.0.0:2375->2375/tcp, 2376/tcp ディンド

$ docker-compose ‐‐context remote up -d
/tmp/_MEIb4sAgX/paramiko/client.py:837: ユーザー警告: 不明な ssh-ed25519 10.0.0.52 のホスト キー: b'047f5071513cab8c00d7944ef9d5d1fd'
デフォルトドライバを使用したネットワーク「hello-docker_default」の作成
こんにちはdocker_backend_1を作成する...完成です
こんにちはdocker_frontend_1を作成します...完成です

$ docker コンテキストはデフォルトを使用します
デフォルト
現在のコンテキストが「デフォルト」になりました

$ docker-compose up -d
デフォルトドライバを使用したネットワーク「hello-docker_default」の作成
こんにちはdocker_backend_1を作成する...完成です
こんにちはdocker_frontend_1を作成します...完成です

$ ドッカー ps
コンテナー ID イメージ コマンドが作成されました
ステータス ポート名
077b5e5b72e8 こんにちはdocker_frontend "nginx -g 'デーモンの..." 約1分前
アップ約分0.0.0.0:8080->80 / tcpこんにちはdocker_frontend_1
fc01878ad14e hello-docker_backend "/usr/local/bin/back..." 約1分前
1分ほどアップ こんにちは-docker_backend_1
ed92bc991bad docker:19.03.3-dind "dockerd-entrypoint...." 34分前
アップ 34 分 0.0.0.0:2375->2375/tcp, 2376/tcp ディンド

これで、サンプル アプリケーションが 3 つのホストすべてで実行されます。 以下に示すように、これらの各ホストでフロントエンドサービスを照会すると、同じメッセージが返されます。

$ カールローカルホスト:8080

$ docker exec -it dind sh -c " wget -O – localhost:8080"

$ カール 10.0.0.52:8080

アウトプット:

          ##         .
    ## ## ##        ==
## ## ## ## ##     ===
/"""""""""""""""""\___/ ===
{                       / ===-
\______ O __/
\    \         __/
\____\_______/
ドッカーからこんにちは!

概要

docker-composeを使用してリモートホストにデプロイすることは、かなり長い間一般的なユースケースでした。 

docker-compose の Docker コンテキストのサポートは、さまざまなリモートホストをターゲットにするための簡単でエレガントなアプローチを提供します。 異なる環境間の切り替えが管理しやすくなり、環境全体の展開リスクが軽減されます。 SSHおよびtcpプロトコルを介してリモートDockerホストにアクセスする方法の例を示し、これらが多数のユースケースをカバーすることを期待しています。