- Docker〜コンテナ型仮想化〜
- この記事では、コンテナ型の仮想化を実装するソフトウェアである「Docker」を紹介します。
- わかりやすいDocker入門
- このページでは、Dockerのインストール、Dockerコンテナの操作等について説明します。
- コンテナ型仮想化に関連したOSS
- ここでは、コンテナ型仮想化に関連したOSSを紹介いたします。
Dockerとは、docker社が開発しているコンテナ型仮想化の実装の1つです。オープンソースソフトウェアとして公開されていて、コンテナ型仮想化としては、事実上のデファクトスタンダードと呼ばれています。
VM Ware、KVM、Virtualboxなどで採用されている完全仮想化や凖仮想化などの技術では、ハードウェアをエミュレーションした複数の仮想マシンを動かします。それとは違い、Dockerでは、1つのOSの上に完全に独立した複数のネームスペースを作り出します。カーネルは、ホストコンピュータと共有します。
Dockerでは、この空間に自動的に小さなファイルシステムをデプロイし、単独のプロセスを動かします。Dockerではユーザ、プロセス、ネットワークなどもホストコンピュータと独立して管理されます。
Dockerは、もともとアプリケーション開発者の間で注目され、現在まで普及が進みました。Dockerを使うとシステムに対する設定手続きなどが、すべてコード化されるためです。また、Dockerを使うと、アプリケーション開発において近年普及してきたCI/CDの手法をシステムにも容易に取り入れることができます。CI/CDは、アプリケーション開発のステージに自動化を取り入れて、顧客にアプリケーションを提供する頻度を高める手法です。CIは継続的インテグレーション、CDは継続的な配布および継続的な開発を指しています。Dockerを利用することで、OSやサーバー、ソフトウェアにも、同じようにCI/CDの考え方を取り入れることができると考えられています。
Dockerでは、アプリケーションの動作に必要な最小限のファイルのアーカイブを使います。これをDockerイメージと呼びます。コンテナは、このDockerイメージとその上で動作するアプリをセットにして起動します。Dockerには以下、数多くのメリットがあります。
Dockerイメージのリポジトリは、インターネット上で公開されています。最も一般的なリポジトリは、Docker-HUBです。Docker-HUBでは、様々な定義されたDockerイメージが公開されていて、様々なOSSのオフィシャルなイメージも取得できます。
次は、docker searchコマンドで、httpdコンテナのイメージを検索した結果です。
$ docker search httpd ⏎ NAME DESCRIPTION STARS OFFICIAL AUTOMATED httpd The Apache HTTP Server Project 2505 [OK] centos/httpd 23 [OK] centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 22 armhf/httpd The Apache HTTP Server Project 8 polinux/httpd-php Apache with PHP in Docker (Supervisor, CentO… 2 [OK] lolhens/httpd Apache httpd 2 Server 2 [OK] :
OFFICIALの欄に[OK]と表示されているものが、オフィシャルなイメージです。このように、httpdのコンテナだけでも用途に合わせて、複数のイメージが公開されています。Docker-HUBにはより詳細なドキュメントが公開されていますので、その情報を参考に用途に合ったものを選ぶことができます。
そして、Docker-HUBで公開されている基本的なDockerイメージは、あらかじめ設定済みです。そのため、初期設定や細かな設定等の作業は不要で、すぐに動作させることができます。
例えば、Webサーバ(Apache)の公式イメージはhttpdという名称で配布されています。docker runコマンドは、このイメージを自動的にダウンロードしてデプロイして、起動します。
$ docker run -d -p 80:80 -v webcontents:/usr/local/apache2/htdocs httpd ⏎
この例では、コンテンツが保存されたボリュームを、コンテンツのディレクトリにマウントしています。また、外部からアクセスできるように、コンテナの80番ポートを、ホストの80番ポートに紐付けて公開しています。このように、オプションやボリュームの指定をするだけで、すぐにコンテナを実行することが実現できるのです。
仮想サーバを一台起動すると、8Gbyte程度のディスク容量が必要になります。しかし、Dockerは、他の仮想環境に比べて少ないディスク容量で動作します。また、Dockerは、起動が早く、仮想化による性能の劣化もほとんどありません。次は、Webサーバ(httpd)のコンテナイメージのサイズを調べた結果です。
$ docker images httpd ⏎ REPOSITORY TAG IMAGE ID CREATED SIZE httpd latest b7cc370ac278 4 weeks ago 132MB
SIZEの欄を見ると、132MBとなっています。従来の仮想サーバと比較すると、約5%のリソースの量で動作するのです。
Dockerでは、イメージサイズを小さくする工夫も行われています。Dockerイメージの作成時に使われるAlpine Linuxのイメージは、約5MBと非常に軽量なのが特徴です。
$ docker images alpine ⏎ REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest 055936d39205 4 weeks ago 5.53MB
このイメージから派生したコンテナは、さらに少ないリソースで稼働します。
$ docker images ventz/bind ⏎ REPOSITORY TAG IMAGE ID CREATED SIZE ventz/bind latest d5b9c9b769aa 5 weeks ago 16.2MB
このBINDのコンテナは、たった16.2MBで動作します。
Dockerの各コンテナに割り当てるCPU時間やメモリも簡単に設定することができます。例えば、WWWサーバのメモリを512Mに限定するには、次のように--memoryオプションでサイズを指定するだけです。
$ docker run -d -p 80:80 --memory 512m httpd ⏎ 6143987d654da232386f5db6fc3394958e4be32cf403eb4c581cf29c96c0d04e
Dockerイメージは、リポジトリ内で階層的に管理されます。どこから作成されたかも明確に管理できるため、バージョン管理が行いやすくなっています。次は、httpdコンテナにコンテンツを入れた独自のコンテナを作成した場合の例です。docker image historyコマンドでイメージを確認すると、これまでに行った変更をコメント付で確認することができます。
$ docker image history httpd-designet:1.0 ⏎ IMAGE CREATED CREATED BY SIZE COMMENT 4bc4ba5a19cd 3 weeks ago httpd-foreground 61.4MB httpd with www.designet.co.jp b7cc370ac278 4 weeks ago /bin/sh -c #(nop) CMD ["httpd-foreground"] 0B <missing> 4 weeks ago /bin/sh -c #(nop) EXPOSE 80 0B <missing> 4 weeks ago /bin/sh -c #(nop) COPY file:8b68ac010cb13f58… 133B :
Dockerは、OS環境の制約を受けにくい作りになっています。そのため、ほとんどのLinuxの上で動作します。また、CentOSのDocker環境の上で、Debianのコンテナを動かすということもできます。
Docker-HUBは、Docker社が提供するコンテナレポジトリです。作成したコンテナイメージを、レポジトリに登録しておくことで、どのような環境にもすぐにイメージを運ぶことができます。
Docker-HUBには、docker loginでログインし、docker pushコマンドでイメージをアップロードするだけで、イメージをアップロードすることができます。
$ docker login ⏎ $ docker push tune1111/httpd-dg:1.2 ⏎ The push refers to repository [docker.io/tune1111/httpd-dg] 8eac8bf1da5b: Pushed a8eceb11d25e: Pushed 428d798f86c4: Pushed d12cae5562ef: Mounted from library/httpd d188fb853e8f: Mounted from library/httpd 320e3241be93: Mounted from library/httpd 5de0920316a3: Mounted from library/httpd 6270adb5794c: Mounted from library/httpd 1.2: digest: sha256:f0531e4cb13ee55bd414d5433d23305d2725147c80f865b5d751852a4eb4369a size: 1993
Dockerで作成したイメージは、ローカルリポジトリでも管理できます。また、GitLabなどで作成した独自のレポジトリサーバでも管理ができます。
Dockerイメージを集中管理することで、様々な環境で同じ状態のシステムを構築することができます。例えば、オンプレミスのサーバとクラウド上のサーバとで、同じイメージを使用できます。そのため、Dockerは、環境に左右されず運用ができます。
最近では、Googleが提供するGKE(Google Kubernetes Engine)、Amazonの提供するEKS(Amazon Elastic Container Service for Kubernetes)など、Dockerコンテナを使えるクラウド型サービスが提供されています。オンプレミスで動作を検証したコンテナは、こうしたクラウドサービスでも同じように動かすことができます。
作成したDockerイメージをGitLabなどのレポジトリで管理することで、同じシステムをそのまますぐに別の環境に作成ができるようになります。そのため、Dockerで構築したシステムイメージから、すぐにステージング環境や検証用環境を構築することができます。
Dockerには、バージョン管理を支援する機能があり、非常に便利です。
Dockerでは、Dockerfileという書式を使って、コンテナイメージを作成します。例えば、次のDockerfileは、httpdコンテナのイメージにコンテンツを同梱して、新しいコンテナを作成しています。
FROM httpd LABEL maintainer="admin@designet.jp" COPY www.designet.co.jp /usr/local/apache2/htdocs
もし、元になるhttpdのコンテナのバージョンが上がっても、次のようにdocker buildコマンドでイメージを作り直すだけで、自動的に最新のhttpdコンテナから、新しいコンテナイメージを作成することができます。
$ docker build -f Dockerfile -t httpd-designet:1.2 . ⏎ Sending build context to Docker daemon 60.99MB Step 1/3 : FROM httpd ---> b7cc370ac278 Step 2/3 : LABEL maintainer="admin@designet.jp" ---> Running in 38dad19d8ddf Removing intermediate container 38dad19d8ddf ---> 5b7b9e5425df Step 3/3 : COPY www.designet.co.jp /usr/local/apache2/htdocs ---> 50401e525d20 Successfully built 50401e525d20 Successfully tagged httpd-designet:1.2
Dockerのコンテナには、「registory:tag」という規則で名前を付けます。registoryは、コンテナの名称です。そして、tagとしてリリース番号を付与します。さらに、最新のコンテナイメージには、次のようにdocker tagコマンドを使うことで、latestというタグをつけます。
$ docker tag httpd-designet:1.2 httpd-designet:latest ⏎
docker runは、latestというタグの付いた最新のイメージを使いコンテナを起動します。そのため、新しいコンテナイメージを作成したら、次のようにコンテナを再起動するだけでバージョンアップが完了します。
$ docker stop httpd ⏎ $ docker run -d -p 80:80 httpd-designet ⏎
また、コンテナを入れ替えることも簡単にできるため、次のようにリリース番号を指定してコンテナを起動することで、ロールバックも簡単に行うことができます。
$ docker stop httpd ⏎ $ docker run -d -p 80:80 httpd-designet:1.1 ⏎
もし、問題がなければ、古いリリース番号のコンテナイメージを削除することもできます。
$ docker rmi httpd-designet:1.1 ⏎
Dockerの利用においては、Dockerの特徴を生かすため、次のような手順が推奨されています。
Dockerコンテナには、必要最小限のソフトウェアだけをインストールします。
1つのコンテナ上に1つのサービスやプロセスだけを起動するような構成が推奨されています。
コンテナイメージ内の情報は、動的に変更しないことが推奨されています。DBやログなど、常に更新される永続的なデータを保管する際には、外部ストレージをコンテナにmountして使います。
Dockerのデメリットとして、次のような点が挙げられます。
Docker利用のガイドラインを守ろうとすると、エンジニアは従来とは異なる考え方や知識を学び理解する必要があります。
DockerコンテナのレジストリであるDocker-HUBのコンテナは、安全とは限りません。バイナリでソフトウェアが置かれているので、ウィルスや悪意あるプログラムが含まれている可能性があります。
Dockerのすべてのコンテナは、ホストコンピュータのネットワークやストレージを共有して利用します。別のホスト上のコンテナと、リソースを共有することはできません。
Dockerでは、1サービス/1コンテナで動作させるため、多数のコンテナが乱立します。コンテナが増加すると、一つ一つのコンテナを管理することが難しくなります。
Dockerコンテナ同士が連携して動作するので、連携情報を管理する必要があり、導入が非常に面倒です。
こうしたDockerのデメリットを補うために、コンテナの管理を行うオーケストレーションツールが使われることがあります。Kubernetesは、代表的なコンテナ・オーケストレーションツールです。
ただし、Kubernetesでコンテナを管理する場合、最低3~5台のコンテナ実行環境が必要です。1台のサーバしか利用しないなど、小規模のシステムでコンテナを管理したい場合は、オープンソースソフトウェアのPortainerが便利です。Portainerは、Docker単体、 Kubernetes、Nomadのデプロイが可能で、WebUIで簡単にコンテナの管理や監視を行うことができます。
コンテナ型仮想化の技術では、オープンソースのDockerおよびKubernetesが事実上のデファクトスタンダードとなりました。一方で、コンテナ型仮想化が非常に重要な技術となったことから、コンテナに関する標準化が進んでいます。この標準化によって、あらたなコンテナツールが生み出されるなど、様々な変化が起きています。
2015年に、Docker、CoreOS、マイクロソフト、RedHat、VMWareなどが、オープンコンテナイニシアティブ(OCI)を発足し、標準化が始まりました。
2016年には、Kubernetesとコンテナランタイムが通信するための仕様としてCRI(Container Runtime Interface)が規定されています。
2017年に、OCIは次の2つの仕様を作成しました。
その結果、これまでDockerが担ってきた役割が、次のような仕組みがいくつかの要素に分割されました。
低レベルのランタイムは、カーネルの機能を使ってコンテナに必要な独立した環境を用意し、実際にコンテナを動作させる役割を担っています。
低レベルのランタイムの実装としては、runc、gVisor、Kata Containerなどがあります。
高レベルのランタイムは、DockerやKubernetesなどのコンテナ管理ツールから、コンテナに関する処理を引き受けます。具体的には、次のような機能を持っています。
高レベルのランタイムの実装としては、containerd、CRI-O、rktなどがあります。
podmanは、RedHat社が開発したコンテナ管理ツールです。OSSで公開されていて、RedHat Enterprise Linux/CentOS 7.6以降でパッケージが配布されています。また、ubuntuなどでもパッケージで導入することができます。Redhatは、Dockerやcontainerdのようなデーモンプロセスを必ず経由して使うシステムは、これらのプロセス停止により全機能が停止してしまうため危険だと主張しています。
それを避けるため、podmanは、UNIXドメインソケットを使わずに動作します。また、systemdとの連携なども簡単に行えるようになっていたり、ユーザー毎のローカルレポジトリが利用できるようになっているなど、Linuxとの親和性がより強化されています。
なお、podmanは、Dockerと互換性を持って作られていて、引数などの指定方法は、すべてDockerと同じです。さらに、podの管理やKubernetesの管理用のYAMLファイルを出力する機能が追加されています。
下図は、podmanのアーキテクチャです。