Docker、仮想化の概要理解〜HelloWorldまでやってみる


対象読者

Dockerがすげえ技術なのはわかるけどそれ以外何もわからない方
VMWareとかVirtualBoxと何が違うかわからない方

はじめに

仮想化技術の概要から始まり、Dockerと従来の仮想化技術の違い、DockerでHelloWorldする方法までを解説する記事となります。DockerはインフラやのにHelloWorldてなんやねんってツッコミたい気持ちはわかりますがちゃんとHelloWorldします。

本記事対象外の内容

Dockerのインストール方法
英語だけでなく日本語でも豊富に記事が存在しているかと思いますのでそちらをご参照ください。

そもそも仮想化とは?

仮想化技術を用いるとWindows上でLinuxOSを動作させたり、MacOS上でLinuxを動作させたりすることができます。物理環境の差異を隠して表面を変える技術だとか説明されます。開発においてはかなり便利です。

例えば、開発環境の違いで想定通りに動作しなかったり、わけわかんないエラーが出たり、あるいは競合するプログラムがあったりするとかなり面倒です。同じMacOSで開発していてもバージョンが違うために動作しなかったりする事もあります。

仮想化を行うことで、こうした開発環境による差異を無くし、さらにプロジェクト毎に開発環境を分けられるのでプログラムの競合が起こる事も減ります。Dockerはそうした仮想化技術の1種です。

仮想化の種類

仮想化には大きく分けて2種類の仮想化があります。

  • ホスト型仮想化
  • コンテナ型仮想化

ホスト型がVMWareやVirtualBoxなどの従来の仮想化技術です。
それに対しDockerはコンテナ型と呼ばれます。ホスト型仮想化では仮想化ソフトウェアを用いて仮想的なOSを構築します。構築されたOSの上でアプリケーションを動作させるためOSによる差異をなくすことができます。ただしオーバーヘッドが大きく、加えて起動時にCPUリソース、メモリ、ストレージなどを割り当てるため起動に時間がかかります。

それに対してDocker(コンテナ型)ではカーネルをホストOSと共有するためオーバーヘッドが非常に少ないです。実行環境の違いをコンテナエンジン(=docker)が吸収し、様々なソフトウェアが詰まったコンテナを動作させることで実行環境を構築します。コンテナについては後述します。


図1 ホスト型仮想化 

図2 コンテナ型仮想化

Dockerの利点

コンテナ型仮想化ではゲストOSを持たないため以下の利点があります。

  • 処理速度が早い

    ホスト型仮想化ではゲストOSを構成する際にCPUリソースやメモリ、ストレージの割り当てが行われるが、コンテナ型技術ではゲストOSを構成しないためオーバヘッドが非常に少ない。(=消費するリソースが少ない)

  • 起動が早い

    Dockerデーモン(Dockerのアプリのこと)が立ち上がってればよくてゲストOSを構成したりしないから当然早い

  • 可搬性が高い
    Dockerエンジンがあれば動く。要するにどこでも動く

  • イメージが軽い

  • インフラのコード化

    色々やらなくていい

  • 便利機能満載

    コンテナ型仮想化独自のメリットという訳ではないが色々設定できるようになると高機能

メリットをたくさんあげましたが、1点注意点としてLinux系のCentOSやUbuntuなどのコンテナが存在しますが、あれは完全なOSを構築している訳ではなく、あくまでカーネルはホストOSであるという点に注意するべきです。カーネルを共有させるべきコンテナは動作させる事ができません。

コンテナ、Dockerイメージ

Dockerイメージとはコンテナ実行に必要なファイルをまとめたファイルシステムです。AUFSなどの特殊なファイルシステムが使用されています。イメージ上のデータはレイヤで構成されていて読み取り専用となっています。その上に構成されるコンテナレイヤーが読み書き可能なレイヤーです。Dockerイメージ+コンテナレイヤーでコンテナとなるイメージです。図にすると下のような感じ。


図3 Dockerイメージとコンテナ

具体例をみてみましょう

CentOSのベースイメージを継承してRubyの実行環境のレイヤーを加えています。因みにベースイメージとは何も継承していない基底イメージのことです。

図4 CentOSベースイメージの継承

作成したRubyの実行環境のイメージをさらに継承してRailsの実行環境も作成できます。

図5 Rubyの実行環境にRailsのレイヤーを加える例

このようにレイヤーを重ね合わせてイメージを作成します。

次は同じイメージを継承する場合です。この場合、CentOSレイヤーを共有することができます。2重でレイヤーを用意しなくていいのでイメージサイズが小さくなります。さらに差分のイメージだけを取得することになるので、通信量も抑えることができます。


図6 ベースイメージの共有

Dockerに触れてみる

Dockerのインストールは省略します。わかりやすい記事が豊富にあると思うのでググってみてください。今回はDockerの動作原理などを確認するのが目的です。

1.Dcokerデーモンが起動していることを確認

図7 Dockerデーモンの起動を確認

Docker is runningとなってればOKです。図3で言うところのコンテナエンジンがこれです。

2.ターミナル上でHello Worldしてみる

Dockerで単純なイメージの取得と動作を確認しましょう。ターミナルを開いて以下のコマンドを入力してみてください。run はその後ろに記述したイメージを取得して実行するサブコマンドです。このコマンドではhell-worldというイメージを取得して実行します。

$ docker run hello-world

初めて実行したのであれば↓のような結果が返ってくると思います。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!        
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

7行目でHello from Docker!と出てますね。

他の記述はどのように動作しているかを細かく説明してくれています。

何をしたのか

図で表すとこんな感じです。Dockerクライアントが実行しているコマンドという認識です。Dockerデーモンが1で起動を確認したソフトです。

図8 動作概要図

1.コマンドを実行するとDockerクライアントはDockerデーモンに接続し、hello-worldイメージを探します。
2.初めて実行した場合はローカル上にイメージは存在しないので、Docker Hub(次の記事で解説)というDocker社がホスティングしているサーバーにアクセスしイメージを探します。
3.イメージが見つかるとダウンロードしてPC上に保存します。
4.取得したイメージを実行します。

イメージがPC上に存在する場合は②と③が省略されるので動作が最初に比べて早いです。

試しにもう一度実行するとターミナル上で以下のような結果が返ってくると思います。

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

以下の記述がなくなっているのがわかると思います。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

ローカル上でイメージが見つからなかったのでプルしましたって記述です。②と③が消えたのがわかったかと。

docker runコマンドを細かくみてみる

docker runコマンドは以下のコマンドをまとめたコマンドです。

docker pull:イメージの取得
docker create:コンテナの作成
docker start:コンテナの起動

よく使うコマンドなので少しづつ覚えていきましょう。

今回はここまで。