Docker イメージを PC (Mac) から Azure に展開する


こんにちは。

Azure 上の Docker Container (on Linux) を使って、PC や Mac から、クライアント側をほとんど汚すことなく (Git と軽量な Docker Client のみで) イメージ展開できます。今回は、Node.js アプリの展開を例に、この手順を紹介します。

なぜ、思いついたようにこの投稿を書くかというと、今年も 11/07 に Node.js の Annual イベント「東京 Node 学園祭 2015」が開催されるためです ! (まだスポンサー情報に出ておりませんが、日本マイクロソフトも協賛させていただきます。) Cloud を活用して、PC や Mac から Rapid で Immutable な Node.js 環境が利用できますので、当日のハンズオンなどでも是非ご活用ください。

 

クライアント環境の作成と証明書の準備

クライアント環境を準備しましょう。 なお、今回は Windows を使用しますが、Mac でも同様の概念でセットアップできます。(使用するコンポーネントやコマンド オプション等は異なりますが、概念は同じです。)

まず、Git for Windows のインストールをおこなってください。

{install dir of git}\git-bash.exe を実行して Bash を起動し、下記のコマンドを実行して、Docker Client をインストールします。 今回は、C:\bin のフォルダーを作成し、ここに docker.exe と docker-machine.exe を作成します。

curl -L https://get.docker.com/builds/Windows/x86_64/docker-latest.exe > /C/bin/docker.exe
curl -L -k https://github.com/docker/machine/releases/download/v0.4.1/docker-machine_windows-amd64.exe > /C/bin/docker-machine.exe

補足 : 今回 (2015 Oct 時点) は 0.4.1 をインストールしていますが、https://github.com/docker/machine/releases で Docker Machine の Release 情報を確認しておいてください。

このあと、この exe をバリバリ使用しますので、Windows の環境変数を設定するなどして、上記の docker.exe, docker-machine.exe のインストールされたディレクトリに Path を通しておいてください。

つぎに、後述する Azure への Staging の際に使用する証明書を作成します。 下記のコマンドを実行して、Private key を含んだクライアント側の証明書 (mycert.pem) を作成します。(有効期限は 1 年にしています。)

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem

上記の mycert.pem を使って、Azure 側に配置する public key を持った証明書 (mycert.cer) を作成します。

openssl x509 -inform pem -in mycert.pem -outform der -out mycert.cer

上記の証明書 (mycert.cer) は、Azure Classic Portal (https://manage.windowsazure.com) を開いて、[設定] (Settings) – [管理証明書] (Management Certificates) の中に upload しておいてください。(mycert.pem のほうは、そのままクライアント側に置いておきます。)

上記で Bash は閉じていただいて OK です。

 

Azure への Docker Machine の作成

以降は Windows の Command Prompt を使用します。(なお、Windows PowerShell を使用することもできます。)

まず、上記の docker.exe, docker-machine.exe に path が通っていることを確認してください。 また、作業ディレクトリーに、上記で作成した証明書 (mycert.pem) があることを確認してください。

さらに、Windows 版の openssl もインストールして path を通しておく必要がありますが、openssl は上記の git と共にインストールされていますので、{install dir of git}\usr\bin に path を通して openssl を使えるようにしておけば良いでしょう。

環境の確認が完了したら、下記の通り、docker-machine コマンドを使って Azure 上にホストを作成します。(ここは、少し時間がかかりますが、Docker Machine 構築時の一度だけですので辛抱してください。。。)

{MACHINE_NAME} には unique な名前を指定します。(Azure 上に作成されるマシンの DNS が {MACHINE_NAME}.cloudapp.net になります。) また、{AZURE_LOCATION} には Central US, East US などの region を指定します。(なお、指定可能な region が決まっていますので注意してください。)

docker-machine create -d azure --azure-location="{AZURE_LOCATION}" --azure-subscription-id="{SUBSCRIPTION_ID}" --azure-subscription-cert="mycert.pem" {MACHINE_NAME}

例えば、下記の通りです。

docker-machine create -d azure --azure-location="East Asia" --azure-subscription-id="b3ae1c15-4fef-4362-8c3a-5d804cdeb18d" --azure-subscription-cert="mycert.pem" tsmatsuz-node01

補足 : このように、Docker では、Driver Type オプション (-d オプション) に Azure を指定できます。 また、Windows 環境の場合、Docker Machine として Hyper-V を使用することも可能です。(この具体的な手順については、省略します。) この場合は、上記の Driver Type オプション (-d オプション) に「hyper-v」と指定します。 普段は Hyper-V を使ってローカルで検証し、必要に応じて Azure に展開 (Staging) するような使い方も可能です。

上記のコマンドを実行すると、Microsoft Azure 上に {MACHINE_NAME} (上記の場合 tsmatsuz-node01) の Virtual Machine (Ubuntu) が新規作成されます。 クライアント (Command Prompt) から以下のコマンドを実行すると、作成された Docker Machine の一覧が確認できます。

docker-machine ls

NAME              ACTIVE   DRIVER   STATE     URL   SWARM
tsmatsuz-node01            azure    Timeout

補足 : この Docker Machine の情報は、%userprofile%\.docker\machine に含まれています。 特に、%userprofile%\.docker\machine\certs には、Docker Machine 作成時に作成された証明書が格納されていますので、もし Docker Machine 作成時に証明書エラーになる場合などには、このフォルダーを削除してから実施しなおしてみてください。

補足 : Docker Machine を消す際は、docker-machine rm tsmatsuz-node01 と入力します。(Azure 上の Virtual Machine も削除されますが、上述のクライアント上の cert は残ったままになりますので注意してください。)

さいごに、今回、Node.js で作成するアプリを Port 80 で公開しますので、Azure Classic Portal (https://manage.windowsazure.com) を使って、作成された Virtual Machine の Endpoint を表示し、Public Port、Private Port 共に 80 の Endpoint を追加しておいてください。

 

Container の Build と Staging

まず、作業の前に、Docker Client が参照する Docker Machine 環境として、上記で作成した tsmatsuz-node01 (ここは、皆さんが作成した Docker Machine 名になります) を設定します。 以下のコマンド (docker-machine env) を実行すると、下記の通り実行すべき Windows コマンドが標準出力されるので、出力されたコマンドをコピーして Command Prompt で実行してください。(必ず、上記の mycert.pem の証明書のあるディレクトリーで実行してください。Azure 上の VM も見に行きます。)

docker-machine env tsmatsuz-node01 --shell cmd

set DOCKER_TLS_VERIFY=1
set DOCKER_HOST=tcp://tsmatsuz-node01.cloudapp.net:2376
set DOCKER_CERT_PATH=C:\Users\TusyoshiMatsuzaki\.docker\machine\machines\tsmatsuz-node01
set DOCKER_MACHINE_NAME=tsmatsuz-node01
# Run this command to configure your shell:
# copy and paste the above values into your command prompt

Container を実行するには、大きく以下の 3 つの手順を実施します。

  1. Dockerfile という名前のテキスト ファイルを作成し、ここに、Docker Registry からコピーするイメージや、その他のセットアップなどを記述します。
  2. Build をおこなって Container を作成します
  3. Run をおこなって Image を実行します

今回は、本家の「Docker : Dockerizing a Node.js web app」で紹介されている Express を使った簡単な Node.js のサンプルを配置してみましょう。

まず、作業フォルダーとして、今回は nodesample という名前のサブフォルダーを作成します。 このフォルダーに、下記の package.json ファイル (UTF-8) を作成します。ここでは、Express のインストールをおこなうように指定しています。

{
  "name": "docker-centos-hello",
  "private": true,
  "version": "0.0.1",
  "description": "Node.js Hello world using docker",
  "author": "Tsuyoshi Matsuzaki <tsmatsuz@microsoft.com>",
  "dependencies": {
    "express": "3.2.4"
  }
}

さらに、Express を使って動作する js ファイルとして、以下の index.js ファイル (UTF-8) を作成します。 今回は、Hello World と表示するだけの単純なサンプルです。(Express を使う意味のないサンプルですが。。。)

var express = require('express');

var PORT = 80;

var app = express();
app.get('/', function (req, res) {
  res.send('Hello world\n');
});

app.listen(PORT);

注意 : 「Docker : Dockerizing a Node.js web app」では、src のサブ フォルダーを作成し、そこに package.json, index.js を配置するよう記載されていますが、上記の通り、これらは元のディレクトリーに配置してください。(ドキュメントの不備と思われます。。。)

そして、ここに Dockerfile という名前のテキスト ファイルを作成し、以下の通り記述します。 下記では、Docker Hub の centos (tag が centos6) という名前の Repository にあるイメージを使用します。イメージ取得後は、rpm と yum を使って npm (Node Package Manager) をインストールし、カレント ディレクトリにあるファイル一式 (上記の package.json, index.js も含む) を src のサブ ディレクトリにコピーします。そして、このディレクトリーに移動 (cd) して、npm コマンドで express のインストールをおこないます。(この際、上記の package.json が参照されます。) 最後に node /src/index.js コマンドを実行して Node を起動しています。

なお、src という名前のサブ フォルダーも、あらかじめ作成しておいてください。

FROM    centos:centos6

RUN     rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

RUN     yum install -y npm

COPY . /src

RUN cd /src; npm install

EXPOSE  80

CMD ["node", "/src/index.js"]

以上で、必要なファイルの準備は完了です。

上記のフォルダー nodesample で、以下を実行して Container の Build をおこないます。(今回は Image の名前を「node-hello:0.1.0」としています。) このタイミングで、上記の Dockerfile に記述された内容が実行されます。

docker build -t node-hello:0.1.0 .

Build が完了したら、以下のコマンドでイメージを実行します。

docker run -p 80:80 -t -d --name=stage_node node-hello:0.1.0

下図の通り、docker ps で確認すると、1 つの Image が実行されているのが確認できます。 今回は単一の Image だけですが、Image は瞬時に実行されますので、多数のサービスどうしの連携や、負荷分散やテストための大量インスタンスの起動など、多くの場面でこの軽快さを実感することでしょう。

Web Browser を使って、前述で作成された Microsoft Azure のマシンの Port 80 番 (http://tsmatsuz-node01.cloudapp.net/) にアクセスすると、下図の通り、Express を使った Hello World が表示されます。

なお、下記のコマンドで、Image の停止と Clean up が可能です。

docker stop stage_node
docker rm stage_node

 

今回は PC 上の Docker Client から利用する例を述べましたが、Resource Template (Azure Resource Manager template) と呼ばれる Microsoft Azure 上の Resource 作成の定義ファイル (.json) を使うことで、Azure への Docker Conatiner (Linux) の展開時に Compose を使用することもできます。 さらに、次期 Windows Server 2016 では、OS にバンドルされた機能によって Windows Server 上で Container が利用でき、Windows イメージを扱えます。(Azure には、既にこの VM イメージが提供されています。) また今後、Microsoft Azure に Built-in された Docker コンテナー アプリケーション向けのオーケストレーション ソリューション (ツール、API 含む) として Azure Container Service も利用可能になる予定です。

今後、ますます多くのシナリオに対応した展開が可能になりますので、是非ご活用ください。

Comments (0)