Dockerって知ってる？#1 Dockerのキホン

#はじめに

Dockerって知ってますか？僕はあまり知りません。

でも、会社のチーム内でみんなが使うコンテナ基盤を構築する事になりました。
いや、本当は一年前に引き受けて寝かしてました。すみません。

そこで、急遽Dockerを学び直すことにしました。

"学び直す" とか、いかにも知ったような口をたたきましたが、以前少し本を読んで動かして「こんな感じなんだなー」って掴んだ程度なので雑魚です。

知ったような口をたたけるようになりましょう。

#環境

- MacBook Pro
- Catalina
- Docker for Mac

#Dockerってなに？

Dockerはコンテナ型仮想環境をかんたんに構築するソフトウェアです。
Go言語で書かれています。

#コンテナってなに？

コンテナはMacOSやLinuxなどのホストOSに、プロセスが実行出来る隔離空間を作成する技術のことです。
Dockerイメージをもとにコンテナを起動することで、様々なアプリケーションの実行環境が構築できます。

#Dockerイメージってなに？

Dockerコンテナを作成するモトとなるものです。
Dockerイメージは、アプリケーション、ライブラリ、設定ファイル等をまとめたものです。

#うん。で、Dockerってなに？

ごっついエンプラサーバや手元のMacBookに、かんたんに好きな環境が作れるものです。

例えば、PHPプログラマのPCには任意のバージョンのPHPがインストールされてます。
そういった個々の環境をイメージという単位でまとめて、専用のサーバに置くことで、その環境をかんたんに共有できちゃうのです。

その専用のサーバには、Docker社が用意しくれているものもあり Docker Hub といいます。

Dockerを使うユーザは、そのイメージをダウンロードして、コンテナとして利用することが出来ます。
つまり、PCに直接PHPをインストールする必要がないので、PCはDockerさえあればもう無敵です。

RubyとかPythonとか他の言語の実行環境はもちろん、ApacheやNginxといったWebサーバも構築できます。
コンテナは作るのも消すのもコマンド１つでとてもかんたんです。

また、ダウンロードしたDockerイメージはカスタマイズして、アップロードすることも出来ます。
なので、気になるあの子や、ムカつくあいつも、あなたと同じ環境をにすぐPCに再現出来ます。
Docker machineを使えば、GCPやAWSやさくらのクラウドにもすぐコンテナを構築出来ます。

再現性が高いという事は、検証環境で動いたアプリが本番環境で動かない！みたいなトラブルが起きにくいということです。

#仮想化の種類（ホスト型・ハイパーバイザー型・コンテナ型）
##ホスト型

ホストOSに仮想化ソフトウェアをインストールするだけで実装でき、ハードウェアをエミュレーションして仮想サーバを構築します。
手軽に構築出来る反面、仮想サーバを動作させるためにホストOSの処理が必要になり、仮想化のオーバーヘッドが大きくなります。

ホスト型仮想化の代表的なソフトウェアには、OracleのVirtualBoxなどがあります。

##ハイパーバイザー型
ホストOSではなく、ハイパーバイザーという仮想化専用OS的なソフトウェアのうえで、ゲストOSが稼働します。
ハイパーバイザーがハードウェアを直接制御するため、ホストOS上で稼働するホスト型と比べてオーバーヘッドが少なく、サーバにおける仮想化の主流です。
他の仮想化ソフトウェアと比べて、仮想マシン間の分離レベルが高く、OSの選択の自由度も高いです。

ハイパーバイザー型仮想化を実現する代表的なソフトウェアには、VMware ESXi、MSのHyper-V、CitrixのXenServerがあります。

##コンテナ型
コンテナではゲストOSはなく、ホストOSのカーネルを共有して使用します。
カーネルを共有するとは、つまりWindowsではLinuxコンテナを直接動かすことは出来ません。
これはWindowsOSではWindowsコンテナしか動作させることが出来ないということです。

DockerではCentOSやUbuntuなどのOSのイメージも提供されていますが、完全なOSが動作している訳ではありません。
あくまで最低限必要なライブラリやバイナリだけで構成されています。

Dockerの他には、LinuxContainer（LXC）などが代表的です。

###なぜWindowsやMac上でLinuxが動作させられるのか

- Docker Desktop（Docker for Mac or Windows）
- Docker Tool Box

上記のソフトウェアをインストールする事で、各OSに予め備わっている仮想化ソフトウェアを利用してLinuxOSを起動させ、その上でLinuxコンテナを起動し動作させています。

尚、仮想化ソフトウェアのうえで動作するLinuxは、軽量なTiny Core LinuxというOSです。

仮想化ソフトウェアは、Macの場合はHypeyKit、Windowsの場合はHyper-Vが使用されます。
Docker Tool Boxを使用する場合は、VirtualBoxが仮想化ソフトウェアとして使用されます。

#Docker for Macのインストール
まずはDockerインストールしましょう。
インストールウィザードはそのままパシパシ進めていけばOKです。

https://hub.docker.com/editions/community/docker-ce-desktop-mac/

インストールが終わるとメニューバーの右側にクジラのマークが表示されます。
起動中はアニメーションがせかせか動いていますので、停止すれば使用可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391107/38cc3707-7fa8-784e-2a1e-87656d53293f.png)
これでMadにDocker Engineがインストールされるので、ターミナルでDockerコマンドが使えるようになります。

#Dockerの初期設定

インストールしたらさっそくアプリを起動して、Dockerの設定画面を確認しましょう。
基本的にはいじるところほぼはないと思いますが、いくつかピックアップして説明します。

設定は歯車のマークをクリックします。

##General
ホストOS（今回だとMacOS）起動時のDockerの自動起動や自動アップデートなどの設定が可能です。
Dockerは性質上、起動しているだけで、それなりにメモリを食います。
なので、使わないときはクジラをクリックしてQuitしておきましょう。

また、必要なときだけ立ち上げたい派の人は、下記のチェックを外しておきましょう。
>Start Docker Desktop when you log in

他はとりあえずそのままでいいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391107/a22ad460-5f92-b22a-69f2-51e23ffb4720.png)

##Resources
###ADVANCED

Dockerに割り当てるメモリやストレージ等のハードウェアリソースを制御出来ます。

###FileSharing

バインドマウントという機能で使用します。

Dockerに対してPCのフォルダ共有を許可する為の設定です。
表示されているフォルダはデフォルトで共有が許可されています。

###Proxies

PCが直接インターネットに接続していな場合に設定が必要な場所です。

###Network

コンテナをNetwork接続するために必要な設定ですが、特にデフォルトのままで問題ありません。
とりあえずこれだけ押さえておけば十分だと思いますので、次に進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391107/4a2777e3-6ae1-1fd5-4f97-e55b9e11ddac.png)

#コンテナを起動してみよう

とりあえず実際に起動してみましょう。
下記のコマンドを実行してみます。

```
docker run hello-world   
```

```
例）
% docker run hello-world 
Unable to find image 'hello-world:latest' locally　　　←ローカルにハローワールドってイメージなかったよ
latest: Pulling from library/hello-world　　　←latestってタグが付いたイメージをpullするよ
b8dfde127a29: Pull complete 　　 ←このイメージIDのやつをpullしたったぜ
Digest: sha256:89b〜　　　←ハッシュ値だよ
Status: Downloaded newer image for hello-world:latest　　　←hello-world:latestをダウンロードしているよ

Hello from Docker!　　　←DockerからのHello!!
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.　　　←DockerクライアントはDockerデーモンに接続したよ！
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.　　　←DockerデーモンはDockerHubからハローワールドイメージを引っ張ってきたよ！
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.　　　←Dockerデーモンはイメージから新しいコンテナを作成したよ！（略
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.　　　←Dockerデーモンは君の端末に結果を出力したよ！

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/
```

長々英字が表示されたと思います。ゾッとしますね。

この中の番号付きリストは今何が行われたのかを、記載してくれています。
文中に雑に解説を入れたので見てみて下さい。イメージIDとかタグとかについては後述します。

#docker run コマンドとは？

docker run とは下記のコマンドをまとめて実行するのと同義です。

```
docker pull　→DockerイメージをDockerHubから引っ張ってくるコマンド
docker create →Dockerイメージからコンテナを作るコマンド
docker start　→作成したコンテナを起動するコマンド
```

#docker run コマンドの結果を分析してコンテナ起動の流れを理解する

docker startコマンドは、明示的に指定しない限り、コンテナを起動すると同時に、イメージの制作者が設定したコマンドが実行されます。
今回起動したコンテナは、上記の結果を出力するだけのものです。
この実行結果からイメージ取得〜コンテナが起動されるまでの流れを理解しましょう。

DockerクライアントであるPC上では、Dockerデーモンというプロセスが動作しています。
実行結果の雑コメントからわかるように、まずDockerはローカルに同じイメージがないかどうかチェックします。
見つからない場合は、インターネットを経由してDockerHubからイメージをダウンロードします。（docker pull）

ローカル上にイメージがある場合、イメージをダウンロードせずコンテナが起動出来る事になります。
もう一度下記のコマンドを実行すると先程より早く結果が表示されることが確認出来ると思います。

```
docker run hello-world
```

イメージの有無は、同一イメージIDの有無から判断します。
イメージIDはDockerイメージに割り当てられる一意のIDで、docker imagesコマンドで確認出来ます。

また、Dockerイメージにはタグという機能があります。
タグはバージョン管理等の目的で使用され、指定しなければlatestというタグのものが選択されます。

```
% docker images
REPOSITORY        TAG       IMAGE ID       CREATED       SIZE
nginx             latest    35c43ace9216   3 weeks ago   133MB
docker/whalesay   latest    6b362a9f73eb   5 years ago   247MB
```

#Dockerイメージを複製して任意のタグ付けをする

下記のように指定することで任意のイメージを複製し、任意のタグ付けをすることが出来ます。

```
docker tag ローカルにあるイメージ名　複製後のイメージ名:タグ名
```

実際に実行してみます。

```
% docker tag hello-world new-hello-world:original
```

docker imagesで結果を確認します。
異なるイメージ名ですが、同じイメージIDが2つあり、タグ名が異なっているのが確認出来ますね。

```
% docker images                                  
REPOSITORY        TAG        IMAGE ID       CREATED         SIZE
hello-world       latest     d1165f221234   14 hours ago    13.3kB
new-hello-world   original   d1165f221234   14 hours ago    13.3kB
```

#Dockerイメージの詳細情報を表示する

コンテナ起動時に実行されるコマンドやイメージのOSの情報が表示されます。

```
docker inspect イメージ名(イメージIDでも可)
```

```
例）
% docker inspect hello-world
```

#Dockerイメージの削除

不要になったイメージは下記のコマンドで削除してください。

```
docker rmi イメージ名
```

そのイメージを使用してつくられたコンテナがあると削除出来ません。
その場合は、コンテナを削除するか、-fを付けると強制削除が出来ます。

```
例）
docker rmi -f hello-world
```