LoginSignup
23
21

More than 5 years have passed since last update.

Dockerで別ネットワークにあるコンテナをセキュアにリンクする

Last updated at Posted at 2016-05-10

概要

あるホストで動作している Docker コンテナから別のネットワークにある別ホスト上で動作しているコンテナをリンクしたい.しかし,ネットワーク間の通信は信頼できないためセキュアな通信を張る必要がある.本来ならば,VPNを用意してオーバーレイネットワークを構築すべきかもしれないが,小規模な実験的プロジェクトのため,SSHトンネルとAmbassadorパターンで解決する.

コンテナ間のセキュアなリンク.png

AmbassadorS

AmbassadorS は Ambassador パターンを SSH トンネル上で実行するための Docker イメージである.

現在,Alpine Linux ベースのイメージと Raspberry Pi 用に Raspbian ベースのイメージの二種類を公開している.以下では,Alpine Linux ベースの jkawamoto/ambassadors を使う場合を考える.(Raspberry Pi から利用する場合は jkawamoto/rpi-ambassadors を使う.)

AmbassadorS には,サーバ,クライアントそしてトンネルの三つのモードがある.それぞれ次のように接続して使用する.

各モードの振る舞い.png

つまり,リンク先のコンテナが走っているホスト上にサーバモードの AmbassadorS コンテナを走らせ,リンク元のコンテナが走っているホスト上でクライアントモードとトンネルモードの AmbassadorS コンテナを走らせる.

リンク先のコンテナが複数ある場合でも,各ホストにサーバモードのコンテナは一つあれば良い.トンネルモードのコンテナは,接続先のホスト一台に付き一つ必要になる.クライアントモードのコンテナは,元々の Ambassadorパターンと同じくリンク先のコンテナ数分必要になる.

AmbassadorS の実行は,基本的に

$ docker run -dt jkawamoto/ambassadors (server|client|tunnel) [-v]

Options:
  -v           Verbose mode for debugging.

の形で,第一引数としてモードを指定 (server, client, tunnel のいずれか) する.第二引数に -v を渡すとデバッグ用に詳細なログを出力するようになる.

なお,各モードとも上記に Docker へのオプション指定,マウントやリンクの設定が必要になる.具体的な設定方法は次の接続例で説明する.

接続例

ホスト A で MySQL と MongoDB のコンテナが走っていて,ホスト B からこれらのコンテナを利用する場合を考える.なお,MySQL と MongoDB のコンテナはそれぞれ mysql, mongo という名前とする.

サーバモードコンテナの用意

まず始めに,ホスト A で MySQL と MongoDB のコンテナにリンクするサーバモードの AmbassadorS コンテナを用意する.

$ docker run -d --name ambassadors_server \
             -v ~/.ssh/authorized_keys:/data/authorized_keys -p 10022:22 \
             --link mysql:mysql --link mongo:mongo \
             jkawamoto/ambassadors server

サーバモードの AmbassadorS コンテナ はホスト B からの SSH 接続を認証するためにホスト B の公開鍵が必要で,この公開鍵は /data/authorized_keys に置く必要がある.上の例では,ホスト A の ~/.ssh/authorized_keys にホスト B の公開鍵が含まれているものとして,-v ~/.ssh/authorized_keys:/data/authorized_keys によってマウントしている.

サーバモードの AmbassadorS コンテナは,ホスト B からの SSH 接続用に 22番ポートを公開している.-p 10022:22 では,22番の代わりに 10022番を AmbassadorS 用に指定している.

--link mongo:mongo --link mysql:mysql では,AmbassadorS コンテナを MySQL と MongoDB のコンテナにリンクさせている.

トンネルモードコンテナの用意

ホスト B では,まずホスト A へトンネルを張るトンネルモードの AmbassadorS コンテナを用意する.

$ docker run -dt --name ambassadors_tunnel \
            -v ~/.ssh/id_rsa:/root/.ssh/id_rsa -e PORT=10022 -e HOST=<ホスト A のアドレス> \
            jkawamoto/ambassadors tunnel

トンネルモードでは,サーバモードのコンテナに接続するための情報が必要になる.環境変数 HOST 及び PORT は,それぞれサーバモード AmbassadorS コンテナが走っているホスト A のアドレスと公開しているポート番号を指定する.そして,ホスト A で設定した公開鍵に対応する秘密鍵を /root/.ssh/id_rsa に置く.ここでは,ホスト A の ~/.ssh/id_rsa が秘密鍵だとして -v ~/.ssh/id_rsa:/root/.ssh/id_rsa によってマウントしている.

クライアントモードコンテナの用意

最後に,ホスト B でクライアントモードのコンテナを用意する.これは,リンク先のコンテナ数分,この例では2個用意する.

$ docker run -d --name mysql_ambassadors \
             --link ambassadors_tunnel:tunnel --expose 3306 -e PORT=3306 \
             jkawamoto/ambassadors client
$ docker run -d --name mongo_ambassadors \
             --link ambassadors_tunnel:tunnel --expose 27017 -e PORT=27017 \
             jkawamoto/ambassadors client

クライアントモードのコンテナは,トンネルモードのコンテナを tunnel という名前でリンクしなければならない.また,リンク先のコンテナが公開しているポート番号を,--expose と環境変数 PORT の両方に指定しなければならない.MySQL コンテナの場合,3306番を公開しているため --expose 3306 -e PORT=3306 を指定している.

サービスコンテナの利用

最後に,MySQL と MongoDB を利用するコンテナをクライアントモードのコンテナに接続する.

$ docker run -d --link mysql_ambassadors:mysql --link mongo_ambassadors:mongo some-app

docker-compose

上記の例を docker-compose で行う場合,各ホストの設定ファイルは次の通り.

ホスト A 用

docker-compose.yml
mysql:
  image: mysql
mongo:
  image: mongo
ambassadors:
  image: jkawamoto/ambassadors
  command: server
  volumes:
    - ~/.ssh/authorized_keys:/data/authorized_keys
  ports:
    - "10022:22"
  links:
    - mysql
    - mongo

ホスト B 用

docker-compose.yml
tunnel:
  image: jkawamoto/ambassadors
  command: tunnel
  volumes:
    - ~/.ssh/id_rsa:/root/.ssh/id_rsa
  environment:
    HOST: xxx.xxx.xxx.xxx
    PORT: 10022
mysql_ambassadors:
  image: jkawamoto/ambassadors
  command: client
  expose: 3306
  environment:
    PORT: 3306
  links:
    - tunnel
mongo_ambassadors:
  image: jkawamoto/ambassadors
  command: client
  expose: 27017
  environment:
    PORT: 27017
  links:
    - tunnel
app:
  image: some-app-image
  links:
    - mysql_ambassadors:mysql
    - mongo_ambassadors:mongo

コンテナ間のリンクが多数必要になるので,上記のように docker-compose の利用を検討したい.

まとめ

SSH トンネリングと Ambassador パターンを提供する AmbassadorS コンテナを用いると,別のネットワークにある docker コンテナをセキュアにリンクすることができる.SSH トンエリングが切断した場合,トンネルモードのコンテナが終了するので,長期的に運用する場合には再接続する設定が必要である.

23
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
21