VPS

Dockerのインストール/設定/使い方+オーバーヘッドによるパフォーマンス劣化計測

Dockerとは?その用途

Dockerは簡単に言えば
・仮想環境をより軽い負荷で実行出来る
・システムの設定をファイルに記述する事で同じシステムの再現性を確保出来る
・プログラムのライブラリの様に既に作られた多くのイメージが共有・配布されている
仕組みです。

複数のコンテナ間で乗ってるサーバーのkernelを共有する事が出来ます。
Vagrant等だとそれぞれ別のOSを立ち上げる=その分掛け算でリソースが必要になる為、それに比べると遥かにオーバーヘッドを少なく走らせる事ができます。

本番システムで使うには更に色々考えるべき事がありますが、ひとまず開発・テスト環境を定義し、共有するという用途には、とても向いているのは確かです。

Dockerのオーバーヘッドによるパフォーマンス劣化計測とそれを考慮した注意点

ただ、幾らDockerが軽い軽いと言われてても、それはあくまでVagrantの様な仕組みに比べたらという話であって、OS上で素で使う事に比べ、Dockerという仕組みを挟む事によるオーバーヘッド(余計な資源の使用)の発生と、そこからのパフォーマンス度合いは避けれれません。

問題はそれがどれ位なのか。

Dockerは人的コストの面からそのメリットがよく語られますが、オーバーヘッドについてデータで語っている所は中々見かけず、それを認識されずに使われてる事も多いですが、その認識はシステム設計・選定上重要です。
ここではオーバーヘッドの度合いを計測した結果を共有させて頂きます。

テストに使ったのは
LinodeのDedicated Instane、2CPU(AMD EPYC 7501 32-Core Processor) + メモリ4GBです。
その上でUnixbench(Unixbenchとは何か?)を走らせてみて、結果の差を
– Linode上で素で走らせた場合
– Linode上で走らせたDocker上で走らせた場合
– Linode上で走らせたDocker上で–security-opt seccomp=unconfinedオプション付きで走らせた場合(セキュリティ機能をOffにしたら速くなる事があると言われてる為)
で比較してみました。


全CPUスコア 1735 1255(-28%) 1331(-23%)
1CPUスコア 1124 822(-27%) 895(-20%)
Dhrystone 2 using register variables 3536 3485 3542
Double-Precision Whetstone 1646 1633 1647
Execl Throughput 1332 1300 1324
File Copy 1024 bufsize 2000 maxblocks 2503 1329 1369
File Copy 256 bufsize 500 maxblocks 1646 841 863
File Copy 4096 bufsize 8000 maxblocks 4091 2530 2810
Pipe Throughput 1243 1162 1249
Pipe-based Context Switching 750 594 625
Process Creation 1291 633 1016
Shell Scripts (1 concurrent) 2007 1113 1142
Shell Scripts (8 concurrent) 1953 1039 1071
System Call Overhead 1201 893 1197

Docker無しで素で使うより、全般的に1/4強のパフォーマンスダウンは覚悟しておいた方が良いという事になります。
特に
– ファイルの読み書き
– シェルスクリプトの実行(CPU/OSの性能を通常表す)
の項目にて、劣化が大きいという事が見て取れます。

また、Dockerはセキュリティ機能をオフにすると、そこ迄でもないですが確かに一部速くなる部分がある事は見て取れます(とりわけProcess Creationの部分が速くなってる)。

なお、VPSを使う時には、かなりコスト意識高く運用しており、サーバーのスペックも限られている事も多いますが、
Dockerを使うと、その分ディスクスペースを意外に使ったりする事になるので、それには注意しましょう。

Dockerのインストール

Cent-OSなのでyumを使っていますが、Debian/Ubuntu系の方は、yumの代わりにaptを使えば、基本的には同じ形でインストール作業が行える筈です。

尚、CentOS付属のものではなく、Docker公式の最新安定板を使うようにしてみます。

CentOS 8以降の場合

sudo dnf remove docker docker-common docker-selinux docker-engine;
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo;
sudo dnf install docker-ce;

ここで

 Problem: package docker-ce-3:19.03.10-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of the providers can be installed

といったエラーに遭遇したら
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
から適切なcontainerd.ioをダウンロードしてインストールする(通常最新版)。

wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.2.el7.x86_64.rpm;
dnf remove containerd.io;
dnf install -y containerd.io-1.2.13-3.2.el7.x86_64.rpm;
dnf install -y docker-ce docker-ce-cli;

CentOS 7以前の場合

sudo yum remove docker docker-common docker-selinux docker-engine
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce

Docker Daemonを走らせる

sudo systemctl enable docker.service;
sudo systemctl start docker.service

Hello Worldのdockerを走らせてみて作動確認

docker run hello-world

rootだったらそのまま実行できますが、一般ユーザーの場合には

docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/create: dial unix /var/run/docker.sock: connect: permission denied.

というエラーが出る事があります。

その場合は、dockerは、dockerグループに所属しているユーザーでないと、実行できない為です。
dockerを実行させたいユーザーは、dockerグループに追加します。

sudo gpasswd -a $USERID docker;

なお、ユーザーはグループに追加されても、一旦ログアウトして、またログインし直さないと、グループへの追加が反映されないので気をつけて下さい。

なので、一旦ログアウト&再度ログインしてから

docker run hello-world

と打って、結果がきちんと表示されるか確認して下さい。

Dockerでよく使うコマンド

DockerfileからDockerイメージの作成

docker build --rm -t イメージ名 .;

走っているDockerプロセスをリスト

docker ps;

指定したDockerコンテナでコマンドを実行

docker exec -i -t $コンテナID $何かコマンド

指定したDockerコンテナのログを出力

docker logs $コンテナID

走っている全てのDockerプロセスを止める

docker kill $(docker ps -q);

Dockerのイメージの削除

docker rmi $IMAGE;

全てのDockerイメージの削除

docker images -aq | xargs docker rmi;

止まっている全てのDockerコンテナを削除

docker rm $(docker ps -a -q);

docker-composeをデーモン(=ずっと動いているプロセス)として動かす

docker-compose up -d

docker-composeで立ち上げたプロセスを止める

docker-compose stop