WindowsユーザーのためのDockerコンテナー入門【Azure活用編】(3)
Dockerコンテナーへのストレージのマッピングと、複数コンテナーのロード(単一ホスト)
――Dockerコンテナー実践活用(中編)――
実運用で必要となる「ストレージのマッピング」(Dockerホストのストレージを利用/Azure File Storageを利用)を解説。さらに、単一のホストに複数のCassandra DockerコンテナーをロードしてCassandraクラスターを構築する方法を説明する。
前回の手順で起動したCassandraコンテナーには、ストレージ(Dockerホストのストレージ/Azure Storage)をマッピングしていない。Dockerコンテナーでの修正は、ストレージ上のDockerイメージに保存される。そのため、もしストレージにマッピングせずにDockerコンテナーを削除すると、修正内容(ここまでの例ではキースペースの作成)が失われてしまうのだ。また、データが将来的に増大したときに備えて、コンテナーの外部リソースにデータを永続化(=保存)できるようにしておいた方がよい。
そこで今回はまず、ストレージをDockerコンテナーに割り当てて起動する方法として、
- Dockerホストのストレージをマッピングする方法
- Azure Storageをマッピングする方法
の2つを説明する。
「Dockerホストのストレージ」をDockerコンテナーにマップする
それでは、Dockerホストのストレージをマッピングして起動してみよう。
Cassandra Dockerコンテナーの停止と削除
まずは、マッピングして起動し直すために、すでに起動したCassandraコンテナーを停止させ、コンテナーを一度削除する。
# Cassandraコンテナーを停止する
SSH> docker stop some-cassandra
# Cassandraコンテナーが停止されたことを確認する
SSH> docker ps -a
# Cassandraコンテナーを削除する
SSH> docker rm some-cassandra
# Cassandraコンテナーが削除されたことを確認する
SSH> docker ps -a
|
Dockerコンテナーを停止させると、(2行になって少し見にくいが)[STATUS]が「Exited」になるが、Dockerコンテナー自体は残ったままである(赤枠部分)。この状態で、同じ名前のコンテナーを作成することはできない。
Dockerコンテナーを作成し直すためには、Dockerコンテナーを削除する必要がある。
再起動時に「Dockerホストのストレージ」へマッピング
次に、CassandraコンテナーからDockerホストのストレージを使用できるようにするためのオプションを付与して、再びCassandraコンテナーを起動する(リスト6)。
# Cassandraに割り当てるディレクトリ(=Dockerホストのストレージ)を用意する
SSH> cd /usr/local/lib
SSH> sudo mkdir cassandra
# ホスト上のディレクトリ「/usr/local/lib/cassandra」をコンテナー上のディレクトリ「/var/lib/cassandra」にマップして、Cassandraコンテナー起動する
SSH> docker run -d --name some-cassandra -v /usr/local/lib/cassandra:/var/lib/cassandra cassandra
|
ここで新たに登場したdocker run
のオプションは以下の通り。
オプション | 意味 | 説明 |
---|---|---|
-v マップ元のパス:マップ先のパス | コンテナーが使用するストレージを指定する | リスト6の例では、Dockerホストのディレクトリを、Dockerコンテナーのディレクトリにマップしている |
起動すると、Dockerホストのディレクトリ/usr/local/lib/cassandra
にCassandraのデータファイルが生成される。起動した直後は、データが一切ない状態だが、前回の「CQLを使ったテーブル作成とレコードの追加・参照」で述べた方法でテーブルを生成してデータをインサートすると、そこで登録したデータは、このデータファイルに保存されるようになる。このデータファイルがあれば、Dockerのインスタンスを削除した後でも同じオプションを使うことで、データが保存された状態で起動し直すことができる。
システム構成図:「Dockerホストのストレージ」にマッピングされたCassandraコンテナー
また、ここでコンテナーの関係を整理しておこう。
Dockerを停止し再起動するだけなら、docker stop
とdocker restart
のコマンドを使うことで実現できる。この場合、コンテナーは削除されていないため、停止した状態を保持した状態で起動される。こうやってデータを保持するのであれば、ホスト側のストレージのマッピングは不要に思われるが、実際の開発では、そういうわけにはいかない。というのも、システム開発の過程ではDockerコンテナーのパラメーターを修正しながら起動することが多く、コンテナーを削除してから起動し直すことが必然的に発生するため、やはりホスト側のストレージにデータを記録しておくことが望ましいからだ。
「Azure Storage」をDockerコンテナーにマップする
Dockerコンテナーにストレージをマップするうえで、Dockerホストのストレージを用意する場合、事前にホスト側に必要なストレージを用意しておかなければならない。実際に必要なストレージ容量が見積もれるのであれば、それに越したことはないが、正確に見積もりできることはまれである。
容量が見積もれないのであれば、もともとの仮想マシンで用意されているストレージではなく、Azure Storageからストレージを調達して仮想マシンに割り当て、Dockerコンテナーに割り当てることができたら便利だろう。データベースであれば「データ量の増加に伴い、ストレージをより簡単に増強したい」という欲求があるだろうし、クラウドだからこその利点(大容量、安価、複製が容易、……)があるのでなおさらAzure Storageの方が便利である。
Azure Dockerホストでは、Azure Storage上にDockerボリューム(=ストレージ領域)を簡単に作成して使用できるようにするためのボリュームドライバーazurefile-dockervolumedriver
(以下、Docker Volume Driver for Azure File Storage)が用意されているので、これを使うのがお勧めだ*2。今回はこれを使って説明する。
- *2 通常、LinuxでAzure Storageを利用する場合、(1)「Blobの作成」、(2)「仮想マシンへの割り当て、(3)「ストレージのマウント」をそれぞれ手作業で実施する必要があり、ある程度Linuxの管理に精通していないと、Dockerボリュームを作成するのは困難である。
azurefile-dockervolumedriver
を採用することで、それらの作業を一気に飛ばして、ボリュームを作成・利用できるようになる。残念ながら本記事の執筆時点では、azurefile-dockervolumedriver
はデフォルトではインストールされていないため、手動でインストールする必要がある。
Azure Storageのアカウント名とアカウントキーの取得
Azure Storageを使うために、ここでAzure Storageのアカウントを1つ作成しておこう。これには、Azureポータルサイトにアクセスして[ストレージ アカウント (クラシック)]を開き、上部の[追加]ボタンをクリックして[ストレージ アカウントの作成]ブレードを開き、[名前]欄に任意のストレージアカウント名を指定し、[リソース グループ]欄で[既存のものを使用]を選択してDockerコンテナーと同じ名前を選択し、最後に[作成]ボタンを押せば完了だ。
あとは[すべてのリソース]→[<作成済みのストレージアカウント名>]をクリック→ブレード内メニューから[アクセスキー]をクリックすれば、図6のように表示されるので、アカウント名とアカウントキーをメモしておく。
DockerボリュームドライバーのインストールとAzure Storageアカウント設定
まずは、リスト7の要領でazurefile-dockervolumedriver
をインストールする。先ほど取得したAzure Storageのアカウント名とアカウントキーは、このインストール時に必要となる。
# ボリュームドライバーと設定ファイルを、Dockerホストの一時領域にコピーする
SSH> cd /var/tmp
SSH> wget https://github.com/Azure/azurefile-dockervolumedriver/releases/download/v0.5.1/azurefile-dockervolumedriver
SSH> wget https://raw.githubusercontent.com/Azure/azurefile-dockervolumedriver/master/contrib/init/upstart/azurefile-dockervolumedriver.conf
SSH> wget https://raw.githubusercontent.com/Azure/azurefile-dockervolumedriver/master/contrib/init/upstart/azurefile-dockervolumedriver.default
# 実行権限を付与したボリュームドライバーを、/usr/binディレクトリにコピーする
SSH> chmod +x azurefile-dockervolumedriver
SSH> sudo cp azurefile-dockervolumedriver /usr/bin
# 起動スクリプト(.confファイル)を、/etc/initディレクトリにコピーする
SSH> sudo cp azurefile-dockervolumedriver.conf /etc/init
# 設定ファイル(.defaultファイル)のAzure Storageアカウント情報を書き換えて、/etc/defaultディレクトリにコピーする
SSH> sed "s/youraccount/<Azure Storageアカウント名>/" azurefile-dockervolumedriver.default > azurefile-dockervolumedriver.1
SSH> sed "s/yourkey/<Azure Storageアカウントキー>/" azurefile-dockervolumedriver.1 > azurefile-dockervolumedriver.2
SSH> sudo cp azurefile-dockervolumedriver.2 /etc/default/azurefile-dockervolumedriver
|
<Azure Storageアカウントキー>の指定では、スラッシュ/
がある場合は、それをエスケープするためにバックスラッシュを付けて\/
とする必要があるので注意してほしい。
この例ではAzure Storageアカウントを設定するときにsed
を使ったが、Vimなどのエディターが使えるのであれば、それらを利用してazurefile-dockervolumedriver.default
ファイルのyouraccount
とyourkey
を修正してよい。
Dockerボリュームドライバーの起動
リスト7を実行して各種ファイルを配置した後、ドライバーサービスを起動する。
# 構成ファイルの再読み込み
SSH> sudo initctl reload-configuration
# ドライバーサービスの起動
SSH> sudo initctl start azurefile-dockervolumedriver
|
Dockerボリュームの作成
ドライバーサービスが起動したら、Dockerボリュームを作成してみる(リスト9)。
# Azure File Storage(azurefile、ファイル共有名:myshare)を使ったDockerボリューム「myvol」を作成する(各オプションの意味は後述)
SSH> docker volume create --name myvol -d azurefile -o share=myshare
# Dockerボリュームの一覧を確認する
SSH> docker volume ls
|
リスト9を実際に実行したのが図7である。Azure File Storage(azurefile、ファイル共有名:myshare)を使った、「myvol」という名前のDockerボリュームが生成されたことが確認できる(赤枠内)。
Dockerボリューム作成で使ったdocker volume create
コマンドのオプションは以下の通り。
オプション | 意味 | 説明 |
---|---|---|
--name | ボリュームの名前 | Dockerコンテナーでボリュームをマップするときに使用する名前 |
-d | Dockerボリュームドライバーを指定 | ここでは、Azure File Storageを使うためにazurefile を指定した |
-o | Dockerボリュームドライバーの追加オプション | このオプション以降はドライバー固有のオプションを指定する |
share=<共有名> | Azure File Storageの共有名を指定 | Azure File Storage上に作成されるボリュームの共有名を指定する |
作成されたファイル共有(=Dockerボリュームの実体)を確認するには、Azureポータルサイトで[すべてのリソース]→[<ストレージアカウント名>]をクリック→ブレード内メニューにある[FILEサービス]グループの[ファイル]をクリックすればよい。図8のように表示され、「myshare」という名前のファイル共有があることが分かる。
Cassandra Dockerコンテナー再起動時に「Azure Storage」へマッピング
次に、作成したボリュームをマップした状態でCassandraコンテナーを起動する(リスト10)。
# Cassandraコンテナーの停止と削除
SSH> docker stop some-cassandra
SSH> docker rm some-cassandra
# Azure StorageのDockerボリュームを使用してCassandraコンテナーを起動する
SSH> docker run -d --name some-cassandra -v myvol:/var/lib/cassandra cassandra
|
Cassandraコンテナーが起動されると、myshare内にデータディレクトリが構成される。先ほど確認した、ファイル共有の「myshare」をクリックすると、ディレクトリが構成されていることを確認できる(図9)。
システム構成図:「Azure Storage」にマッピングされたCassandraコンテナー
コンテナーとストレージの関係は以下の通り。
複数のコンテナーをロードする
次に、複数のCassandraコンテナーを同一の仮想マシン内で起動し、簡易的なCassandraクラスター*3を構成する。
事前準備:仮想メモリの拡張
実際に起動する前に、Cassandraコンテナーを複数ロードできるように仮想メモリを拡張しておく必要がある*4。これにはリスト11を実行する。
- *3 Cassandra Dockerコンテナーのクラスター。つまり複数のCassandraコンテナーを結合してひとまとまりにすること。
- *4 本連載では、Dockerホスト作成時のデフォルトサイズである“Standard A1”(1コア、1.75GBメモリ)の仮想マシンを使用しており、複数のCassandraコンテナーをロードするために必要十分なメモリを持っていない。ここでは、実メモリを追加する代わりに、仮想メモリの拡張で複数コンテナーのロードを可能にしている。実際の運用では、あらかじめデータベースの必要とするメモリサイズを見積もり、仮想マシンのサイズ(スペック)を変更するという手順となるが、本記事では、Dockerホストのサイズの見積もりについては言及しない。
# 仮想メモリのスワップ領域(3GB)の作成
SSH> sudo dd if=/dev/zero of=/mnt/swap bs=50MB count=60
# 仮想メモリのセットアップ
SSH> sudo mkswap /mnt/swap
# スワップファイルの有効化
SSH> sudo swapon /mnt/swap
# 利用可能なメモリサイズの確認
SSH> free
|
複数のCassandra Dockerコンテナーの起動(=ロード)
次に、Cassandraコンテナーを起動する。これには、事前に今まで起動していたCassandraコンテナーを停止(docker stop
)&削除(docker rm
)してから、以下の作業を実施すること。
# Cassandra Node1のロード
SSH> docker run -d --name cassandra-nd1 -v myvol:/var/lib/cassandra -m 1G cassandra
# Cassandra Node2のロード
SSH> docker run -d --name cassandra-nd2 --link cassandra-nd1:cassandra -m 1G cassandra
# 2つのCassandraコンテナーが起動したことを確認する
SSH> docker ps
# Cassandra Node2にcqlshで接続
SSH> docker run -it --link cassandra-nd2:cassandra --rm cassandra cqlsh cassandra
# mykeyspace.postsテーブルの内容を表示(事前にリスト4を実行する)
cqlsh>select * from mykeyspace.posts;
|
手順通りに試してきた場合、「Dockerコンテナーにストレージをマップする」前に「CQLを使ったテーブル作成とレコードの追加」を行っているので、テーブルデータは保存されていないはずだ。その場合は、最後のコマンドラインを実行する前に、リスト4の手順を実行する必要がある。
※ロード時に「WARNING: Your kernel does not support swap limit capabilities, memory limited without swap.」というメッセージが表示される場合もある。DockerのホストOSによっては物理メモリ・仮想メモリの利用上限を指定できるが、今回使用しているUbuntuでは仮想メモリ上での上限を指定できないため、このWARNINGが表示される。今回の-m
オプションはメモリの上限だけを指定し、物理メモリと仮想メモリの配分についてはOSに任せる形となる。
ここで新たに登場したdocker run
のオプションは以下の通り。
オプション | 意味 | 説明 |
---|---|---|
-m | コンテナーが使用するメモリサイズの上限を指定する | リスト12の例ではメモリ上限として1GBを指定した。このオプションを指定しないと、Cassandraコンテナーが空きメモリを極力確保しようとするため、複数コンテナーを起動できなくなってしまう |
リスト12では、Node1にDockerボリューム「myvol」をマップして起動し、Node2はNode1のクラスターとして参加するように指定してコンテナーを起動した。Node2はストレージをマップしていないが、Node2に接続してもデータを参照できることを確認できたと思う(図11)。
ここでは、Node1とNode2が同期することを示すために、Node2ではあえてストレージをマップせずに起動した。しかし実際には、同期された後のデータを格納すべきストレージをマップすることが望ましい。
システム構成図:複数のCassandraコンテナーで構成されたCassandraクラスター
各コンテナー構成は以下の通り。
最後に
実運用で必要となる「ストレージのマッピング」について、Dockerホストのストレージをマップしてデータを永続化できることを示し、ストレージとしてAzure File Storageを利用してストレージを自由に拡張できることを解説した。さらに今回は、Cassandraコンテナーを使い、単一のホストでCassandraクラスターを構築する方法を解説した。
次回は、Azure Container ServiceでDocker Swarmを使用して、複数のDockerホストから成るCassandraクラスターを構築する方法を説明する。
1. Dockerとは? Dockerホストの作成から、Dockerコンテナーのロードまで
Dockerの概要やそれが必要な理由、仮想マシンとの違いを解説。初めてDockerを使うWindowsユーザーに向けて、AzureにDockerホストを作成してSSH接続し、Dockerコンテナーを起動・停止する方法を説明する。
2. Dockerコンテナーの起動・停止と、Cassandraのコンテナーへのcqlsh接続&CQL実行
Dockerコンテナーの基本的な使い方(起動・停止)を一通り説明。また、Cassandraのコンテナーにcqlshで接続してCQL文によりテーブル作成やレコード追加を行う手順を解説する。
3. 【現在、表示中】≫ Dockerコンテナーへのストレージのマッピングと、複数コンテナーのロード(単一ホスト)
実運用で必要となる「ストレージのマッピング」(Dockerホストのストレージを利用/Azure File Storageを利用)を解説。さらに、単一のホストに複数のCassandra DockerコンテナーをロードしてCassandraクラスターを構築する方法を説明する。
4. Azure Container Service+Docker Swarmで、複数Dockerホストから成るクラスターの構築
Azure Container ServiceでDocker Swarmを使い、複数のDockerホスト上にCassandraコンテナーをロードする手順を説明する。