娘「平成も終わるし、どっか連れってよ！」父「どっかねぇ・・・そうか、Dockerで行くか！」

# はじめに

本記事は、「そもそもDockerとは？」というレベルの人のための記事であり、
既に使いこなしている方はもっと詳しい方のお話をお聞きください。

# そもそもDockerとは何なのか？

まずは、Dockerという存在が何者なのかという事から始める必要がある。
Dockerはコンテナ型の仮想環境を運用するためのソフトウェアである。

## よく使われる仮想化とは何が違うの？

一般的な仮想環境としては、"VMWare"や"Hyper-V"などがある。
それらの仮想化とはまた違うのがコンテナ型仮想化なのである。

簡単に分けると、３つの仮想化技術がある

### ホスト型とハイパーバイザ型仮想化

ホスト型仮想化は、ホストとなるOS上に仮想のハードウェアを構築し、ゲストのOSを動作させる。

一方、ハイパーバイザ型仮想化は、ホスト型と異なりハードウェア上にハイパーバイザを配置し、その上でゲストOSを稼働させる。

### コンテナ型仮想化

コンテナ型仮想化は、上記の２つの仮想化とは基本的な考え型が異なり、
ハードウェアレベルでの仮想化ではなく、もっと上位レイヤ、
言ってしまえばミドルウェアより上の層を仮想化する技術である。

特にDockerは、Linuxコンテナの技術をベースにしているため、
Linux上での動作しか考慮されていない。

細かい話をすると、
仮想マシンと違いハードウェア的な部分は何も管理しておらず、なんならLinuxカーネルすらホストOSと共用しているのである。

Docker上でCentOSやUbuntuが動くのも、実は全てLinuxベースだからなのである。

#### ではWindowsやMac使いはどうするれば良い？

WindowsもMacも、それぞれ対応したDockerがリリースされている。

Windows版のDockerはHyper-V上に、
Mac版のDockerはHyperKit(Hypervisor Framework)上にそれぞれLinuxの仮想環境を立ち上げて、
その上でLinuxを立ち上げているのである。

### 御託はいいから使おうよ

#### インストール

OSによって異なるので省略。
「"OS名" Docker インストール」でググるとたくさん出てくるので参考にしよう。

#### 初めてのDocker

```shell
$ docker run hello-world
```
すると、以下のようなコンソールが出るはずです。

```shell
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e
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/
```

基本的なDockerコマンドは以下のようになります。

```shell
$ docker run イメージ名
```

今回は、「hello-world」というイメージ名のイメージを実行しています。

### そもそも「イメージ」とはなんぞや？

基本的にはAWSのEC２スナップショットのような、
仮想環境のディスクイメージと似たようなものだと思ってもらって構いません。

よくあるスナップショットと違うのは、
「ベースイメージと、それらの差分がレイヤー化されている点」
であり、容量削減が図られている点である。

が、今はあまり気にしない事にしましょう。「そんなもんだ」と思ってください。

### Docker Hub

イメージの理屈よりも、まずは[Docker Hub](https://hub.docker.com/)の存在を覚えましょう。

Docker Hubとは、Dockerイメージがたくさん置いてある場所です。
ここに公開してあるDockerイメージは基本的に自由に使うことができますし、
自身のDockerイメージを作成して公開することもできます。

例として、Webブラウザのデファクトとも言えるnginxを見てみましょう。
「nginx」で調べると、以下のように検索できます。

<img width="1313" alt="スクリーンショット 2019-04-29 19.29.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97156/3c7fdaec-fd2b-c7b4-807d-0b515de8cc12.png">

検索結果から一番上を選択すると、以下のような画面となりますので、右側にあるコマンドをチェックします。
すると、右側にコマンドが書いてありますので、それを打ち込んでみましょう。

<img width="1295" alt="スクリーンショット 2019-04-29 19.33.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97156/fbccff8a-a805-e885-336b-3b1881fb4545.png">

```shell
$ docker pull nginx 
Using default tag: latest
latest: Pulling from library/nginx
27833a3ba0a5: Pull complete 
ea005e36e544: Pull complete 
d172c7f0578d: Pull complete 
Digest: sha256:e71b1bf4281f25533cf15e6e5f9be4dac74d2328152edf7ecde23abc54e16c1c
Status: Downloaded newer image for nginx:latest
```
さて、これでdockerイメージがダウンロードできました。
（先ほどちょっと出て来ましたが、この3行出ているPull completeがDockerイメージのレイヤーを表しています。）

きちんとダウンロードできたか確認しましょう。

```shell
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              27a188018e18        12 days ago         109MB
hello-world         latest              fce289e99eb9        3 months ago        1.84kB
```

nginxと、先ほど実行したhello-worldがあることが確認できますね。

では、nginxを起動します。

```shell
$ docker run -d --name nginx -p 80:80 nginx
```

先ほどとは違って、いくつか引数を追加しています。
各引数の説明が以下になります。

|引数 | 説明|
|:--|:--|
|-d|バックグラウンド起動|
|-p | 外部からアクセスするためのポートフォワーディング設定 |
|--name| コンテナ名を指定します。指定しない場合にはランダムな項目が指定されます。|


起動できたか確認しましょう。

```shell
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
4408569f2a06        nginx               "nginx -g 'daemon of…"   36 seconds ago      Up 34 seconds       0.0.0.0:80->80/tcp   nginx
```

さて、これでブラウザを開き、以下のサイトにアクセスします。
http://localhost/

以下のように表示されれば、正常にnginxのコンテナが起動しています。

<img width="616" alt="スクリーンショット 2019-04-29 19.44.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97156/e7624494-f078-0eda-cfe5-69670743b286.png">

最後に、nginxを落としましょう。

```shell
$ docker stop nginx
```

もう一度、docker ps を実行することで、何も実行されていないことがわかります。

```shell
$ docker ps                                
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

ちなみに、落としたコンテナは裏で残っています。残っているコンテナを見る場合には、 -a オプションをつけます。

```shell
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS               NAMES
4408569f2a06        nginx               "nginx -g 'daemon of…"   23 minutes ago      Exited (0) About a minute ago                       nginx
35b7780b3329        hello-world         "/hello"                 About an hour ago   Exited (0) About an hour ago                        sad_curie
```

### 落ちているコンテナを再実行する

もう一度実行したい場合には、以下のようにコマンドを入力します。

```shell
$ docker start nginx
```

### 落ちているコンテナを削除

もう不要になったコンテナは容量を圧迫しますので、不要なら以下のコマンドでこまめに削除しましょう

```shell
$ docker rm nginx
```

## 意味はわかった。ではなぜDockerを使うのか？

Dockerが採用される一番の目的は、
「環境構築の容易性」と、「環境の統一化」ということにあります。

### DevOpsとの親和性

例えば、JavaのWebアプリを開発したとして、
ローカルの開発環境はWindowsで、開発サーバと本番サーバがLinuxだとした場合、
環境依存のエラーや、ハードウェア起因のエラーが出たり、
インストール手順の漏れによるリリース失敗等の可能があります。

しかし、Dockerでは、DB環境も含めてコンテナで提供することが可能であるため、
サーバにはDockerだけインストールしておけばよく、
作成したDockerイメージを起動するだけで同じ環境を作ることができます。

つまり、開発ーテストー本番運用をスムーズにすることができるのである。
この辺りが、DepOpsというやり方にもマッチし、Dockerの採用はどんどん進んでいく事になります。

### 環境構築の容易性

簡単に環境が作れるということは、スケールアウトも容易という事になります。
特に、Dockerは起動・終了が早いという最大の利点があるため、
素早いスケールアウトが望めます。

## まとめ

Dockerだけ覚えればいいと思っただろ？

まだまだあるよ！

- Dockerコンテナのネットワーク構成
- Dockerfileによるイメージのビルド

などの基礎知識や、

- docker-compose
- Kubernetes

などの周辺技術も知っておかないとお話になりませんが、それらのお話はまた改めて・・・


## 最後に


娘氏「そんなのどうでもいいから私と遊んでよ」