Docker、開発環境の構築に便利ですよね!
ローカルを汚さずにサクっと開発環境を作れるし、別のマシンに環境を配ったり、サーバにデプロイしたりするのも楽チンです。
僕は主に開発環境としてDockerを利用していて、ホストマシンからマウントしたソースコードをコンテナ内で実行することによってコードと実行環境を分離しています。
数百万件のデータを扱ったり何かとCPUヘビーな処理をしたくなる時もあるのですが、そんな時にDockerコンテナからホストマシンのCPUを最大限利用する方法を調べてみました。
ちなみに環境は物理2コア、仮想4コアのMacBookProです。
今回利用するDockerのバージョン
こんな感じです。
Boot2Docker version 1.8.2, build master : aba6192 - Thu Sep 10 20:58:17 UTC 2015
Docker version 1.8.2, build 0a8c2e3
docker-machine version 0.4.1 (e2c88d6)
CPU負荷テスト用のイメージを準備、試してみる
CPUに負荷をかけることだけを目的としたうまいイメージがあったので、本当にCPUが使えているかどうか試すためにまずはこれをpullしてきます。
$ docker pull jess/stress
このイメージからコンテナを起動してホスト側マシンのCPUに負荷をかけることが出来れば、ちゃんとCPUが使えていることになりますね!
早速起動してみましょう。コマンドはこちらになります。
$ docker run --rm -it jess/stress --cpu 4
最後の--cpu 4というのはコンテナが起動した際に実行されるコマンドのオプションで、負荷をテストするCPUの数を指定できます。
今回はテストに利用しているMBPが仮想4コアなので、--cpuには4を指定してみました。
実行した結果はどうなるでしょうか?
$ stress: info: [1] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
うまく起動できました。topコマンドでCPU利用率を確認してみます。
Boot2DockerのプロバイダにVirtualBoxを利用しているため、ホスト側から見えるコマンド名はVBoxHeadlessになっています。
PID COMMAND %CPU
36580 VBoxHeadless 100.3
おや、負荷をかけるCPUの数に4を指定しているのに実際に負荷がかかっているのは100%(仮想1コア分)になってしまっているようです。
コンテナ内からホストのCPUを全て使えていないようですね。
Boot2Dockerに割り当てているコア数を確認する
ここで確認するべきなのは、Macは直接Dockerをインストール出来ないので何らかの仮想環境にBoot2DockerというDocker専用の環境を立ち上げて、その中でDockerコンテナを動かしている、という点です。
ということで、VirtualBox上で立ち上げられているBoot2Dockerの設定を確認してみましょう。
一旦Boot2Dockerをストップしてから、VirtualBoxを開きます。
左上のギアアイコンの設定ボタンから、システム→プロセッサーと進んでいくと…
案の定、1CPUしか割り当てられていないことがわかります。
これが原因でstressコンテナから2つ以上のCPUコアに負荷をかけようとしても、実際は1コアしか使えなかったわけですね。
ではここを緑色になっている範囲の最大値である4CPUに指定して再度試してみましょう。
結果
実行するコマンドは先程のものと同じです。
$ docker run --rm -it jess/stress --cpu 4
topコマンドはどうなっているでしょう。
PID COMMAND %CPU
36580 VBoxHeadless 370.8
370.8%、ほぼほぼ仮想4コア分の400%が使えていると考えて良さそうです。
これでコンテナ内で並列に大量の処理を行いたい時も、ホストのCPUパワーをあますところなく利用できますね!
おまけ: 逆にCPU利用数を制限する
VirtualBoxでBoot2Dockerが利用できるコア数を増やしてしまうと、そのVM上で動く全てのコンテナがその分のCPUリソースを利用できるようになってしまいます。
それが嫌な場合、コンテナを起動する時に利用可能なCPUを指定するオプションを使うことによって、コンテナ単位で利用できるCPUに制限を与えることができます。
具体的には
$ docker run --rm -it --cpuset-cpus="0,1" jess/stress --cpu 4
こんな感じで、--cpuset-cpusオプションを使います。
"0"と指定すると0番目のCPUのみ、"0,1,2"と指定すると0,1,2番目のCPUのみ利用、といった感じで利用するCPUを制限できます。"0-3"などと範囲指定することも可能です。
先程、4コア利用可能と設定したBoot2DockerVM上でコンテナを立ち上げて確認してみましょう。
仮想4コア0,1,2,3番のコアがあるので、そのうちの0,1,2番目、3つのCPUのみ利用できるように制限してコンテナを起動してみましょう。負荷をかけようとするCPUの数は4にしておきます。
$ docker run --rm -it --cpuset-cpus="0,1,2" jess/stress --cpu 4
topコマンドを確認してみます。
PID COMMAND %CPU
36580 VBoxHeadless 297.2
負荷をかけるCPU数を4つと指定したにもかかわらず、仮想4コア400%中の約300%、つまり3つ分のCPUリソースのみ利用できている表示になっています。
うまく制限できているということですね。