新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

WindowsのDockerで複数のDocker Serverを運用する方法

WindowsのデクストップPCにDockerを入れて、ちょっとした定例作業をするためのサーバーを動かしています。

ただ、開発も同じPCでやっているので、開発での作業の影響を本番に与えたくないため、開発と本番でDocker Serverを動かすマシンを分けています。

その、Docker Serverを複数立ち上げる方法に関する手順メモです。また、Docker ServerへのアクセスはPowerShellではなく、WSLを通じて行っているので、その設定も合わせてメモしておきます。

手順

「Docker Machine」を使うと、Dockerが動く仮想マシンを手軽に追加することができきるのでそれを使います。

PowerShellを管理者権限で起動します

PowerShellのコンソールの文字コードをUTF-8にします

chcp 65001

docker-machineで新しいDocker Serverの仮想端末を作成します

docker-machine create `
    —driver hyperv `
    —hyperv-memory 2048 `
    —hyperv-virtual-switch "既定のスイッチ" `
    devVM

これで新しく「devVM」というDocker Serverが追加されます。

WindowsのDockerで複数のDocker Serverを運用する方法

WindowsのDockerで複数のDocker Serverを運用する方法

「MobyLinuxVM」というのは後述しますが、Docker Desktopをインストールした時に作成される、デフォルトのDocker Serverです。

WindowsのDockerに関して簡単に解説

上記の作業内容について簡単に説明します。

Dockerはクライアント・サーバーモデルで動いています。WindowsのDockerは、Hyper-VでLinuxの仮想端末を作成し、その仮想端末上でDocker Serverを動かしてDockerの実行を行なっています。

つまり、WindowsネイティブにDockerが動いているのではなく、Windows上で作成されたLinux上でDockerが動いていて、PowerShellやコマンドプロンプト、WSLなどのクライアントから、そのLinuxにアクセスしているに過ぎません。(Windowsネイティブに動くWindowsコンテナというものもあるのですが、今回は説明から省きます)

Hyper-Vの仮想端末がインターネットにアクセスできるようにするには、仮想端末が使うスイッチを「既定のスイッチ」にする必要があり、「—hyperv-virtual-switch」オプションで指定します。ただし、「既定のスイッチ」は日本語で、そのままではコマンド引数に渡せないため、「chcp 65001」でPowerShellの端末の文字コードをUTF-8に変更しています。

WSLからDockerにアクセスする

デフォルトのDocker ServerにWSLからアクセスする

WIndowsのDocker Desktopをインストールした際にインストールされる、デフォルトのDocker ServerにWSLからアクセスするには、Docker Desktopの設定で

  • [General]-[Expose daemon on tcp://localhost:2375 without TLS]にチェック

WindowsのDockerで複数のDocker Serverを運用する方法

で行えます。

追加したDocker ServerにWSLからアクセスする

追加したDocker Serverにアクセスするには一手間必要です。

先述のとおり、Dockerはクライアント・サーバーモデルなので、WSL(Dockerクライアント)の向き先を、デフォルトのDocker Serverから、作成したDocker Serverに変えることにより行います。

向き先の設定は「DOCKER_HOST」「DOCKER_CERT_PATH」「DOCKER_TLS_VERIFY」の環境変数により行います。

  • 「DOCKER_CERT_PATH」が示すDocker Serverの認証に関するファイルは、Docker Machine作成時に生成され、「/mnt/c/Users/<Windowsユーザー名>/.docker/machine/machines/<Docker_Server名>」ディレクトリに保存されます。
  • Docker ServerのIPアドレスは、Hyper-Vマネージャの作成した仮想端末の「ネットワーク」から調べます。

WindowsのDockerで複数のDocker Serverを運用する方法

これらの情報を元に、下記のように環境変数を設定すると、以後、Dockerコマンドは追加したDocker Serverに対して発行され、アクセスできるようになります。

export DOCKER_HOST=tcp://<ip_address>:2376
export DOCKER_CERT_PATH=/mnt/c/Users/<user_name>/.docker/machine/machines/<docker_server_name>
export DOCKER_TLS_VERIFY=1

デフォルトのDocker Serverにアクセスを戻す

下記のように、設定した環境変数を削除すれば、以後、デフォルトのDocker Serverにアクセスできるようになります。

export DOCKER_HOST=tcp://0.0.0.0:2375
unset DOCKER_CERT_PATH
unset DOCKER_TLS_VERIFY

Docker Composeを使う際の注意

Docker Composeは、デフォルトではTLSのバージョン1.0を使うため、追加したDocker Serverに対して、WSLでDocker Composeを使うと、セキュリティー上の問題により下記のようなエラーがでます。

ERROR: SSL error: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version

そんな時は、下記のように、環境変数でDocker ComposeのTLSのバージョンを1.2にセットするとエラーが出なくなります。

export COMPOSE_TLS_VERSION=TLSv1_2

ちなみに、デフォルトのDocker Serverは、WSLからのアクセス設定で「without TLS」としているので、TLSのバージョンに関わらずエラーは出ません。

Docker ServerのIPアドレスを固定する

「既定のスイッチ」を使うと、追加したDocker ServerはDHCPで適当なIPアドレスが割りあてられます。

そのままでは、PCを起動する度にIPが変わってしまい不便ですので、IPアドレスを固定します。

情報収集

IPアドレス固定に必要な情報は下記です。

  • IPアドレス
  • ネットマスク
  • ゲートウェイ
  • DNS

ネットマスク・ゲートウェイ・DNS

[コントロールパネル]-[ネットワークと共有センター]-[アダプターの設定の変更]で「vEthernet(既定のスイッチ)」があるので、 [右クリック]-[状態の表示]-[詳細]を開きます。

WindowsのDockerで複数のDocker Serverを運用する方法

  • 「IPv4 アドレス」が「ゲートウェイ」と「DNS」になります。
  • 「IPv4 サブネット マスク」が「ネットマスク」になります。
  • 「IPアドレス」は、「IPv4 アドレス」と「IPv4 サブネット マスク」から求まる、任意の「ホスト部」で設定できます。(前述で設定したIPアドレスのままでも構いません)

情報をDocker Serverに設定

「Hyper-Vマネージャー」から、追加したDocker Serverをダブルクリクしてログインします。

Docker Server起動時に「/var/lib/boot2docker/bootlocal.sh」が呼ばれるので、「bootlocal.sh」ファイルを作成して下記を記載します。

bootlocal.sh

ifconfig eth0 <IPアドレス> netmask <ネットマスク> up
echo nameserver <DNS>  >>  /etc/resolv.conf
route add default gw <ゲートウェイ>

シャットダウンして、再度Docker Serverを起動します

するとDocker Serverが新しい指定したIPアドレスになり、PCを立ち上げなおしても指定したIPアドレス固定になります。

認証の再構築

認証はIPアドレスと紐付いているため、IPアドレスが変わるとDocker Machine構築時に作成された認証が使えなくなるので、管理者権限で実行したPowerShellから下記コマンドで再構築します。

docker-machine regenerate-certs <マシン名>

Docker Serverの切り替え

「.bashrc」などに下記のようなエイリアスを作っておくと、切り替えが楽になるかと思います。

alias machine_default='export DOCKER_HOST=tcp://0.0.0.0:2375 && unset DOCKER_CERT_PATH && unset DOCKER_TLS_VERIFY' 
alias machine_dev='export DOCKER_HOST=tcp//<ip_address>:2376 && export DOCKER_CERT_PATH="/mnt/c/Users/<user_name>/.docker/machine/machines/<machine_name>" && export DOCKER_TLS_VERIFY=1'

感想

Hyper-V周りはややこしくてハマりました…。常に仮想端末が動いているのは精神衛生上よろしくなく、WSLだけでDockerが動いてくれたらこんな苦労しなくて済むんですが…。