Docker in Docker (dind) でプロジェクト毎にSandbox化すると便利だよ

# motivation
近頃はほとんどのプロジェクトでDockerないしKubernetesといったコンテナで開発します
特にフリーランスだと複数の仕事が同じDockerホスト上のコンテナとしてぶら下がります
あまり大きな問題が出たことはありませんが

- プロジェクト終了時に全てのコンテナを削除したい
- コンテナ、イメージ名がかぶる可能性
- 他のプロジェクトのイメージが
- お客さんの前あるいは配信時に、他の案件のコンテナリストが表示される

等の問題が生じる可能性があります

まず、シェルなどをまとめたものを下記においておきます
https://github.com/YukiMiyatake/util/tree/master/environment/docker_sandbox

```bash
$ docker images

REPOSITORY                TAG                   IMAGE ID            CREATED             SIZE
docker                    dind                  3c34f16aeaa0        19 hours ago        505MB
<none>                    <none>                31f248f7f9b6        19 hours ago        658MB
kgb_secret_project        latest                bc7c96ecde80        3 days ago          814MB
cia_secret_project        latest                4b7b8690eb05        6 days ago          2.89GB
docker                    dind-alpine           a4b37e66ffc7        7 days ago          230MB
rothschild_report         latest                10 days ago         3.09GB
golang                    latest                54e71dcafb7c        2 weeks ago         803MB
ubuntu                    16.04                 5f2bf26e3524        3 weeks ago         123MB
ubuntu                    18.04                 775349758637        3 weeks ago         64.2MB
buildpack-deps            stretch               81af74c34933        5 weeks ago         835MB
golang                    1.12.7                be63d15101cb        4 months ago        814MB
docker                    1.13.0-dind           7d6978320b24        2 years ago         99MB
```

こんな情報がバレてしまうと、命が危険だ！！



もちろん、案件ごとにPCを換える、マルチブートにする、ユーザーを切り替える、案件ごとにVMを作りそこでDockerする
等の方法で、回避は可能だが
例えばWindowsでHyper-Vを有効にしている場合にはVMを作れない
そのため、現実的な回避手段として
dindを思いついた


# dindとは
DockerはOSの殆どの操作はできますが、一部の操作は出来なくなっています
通常Dockerコンテナ内からDockerを起動できないようになっています

```bash
$ docker run -it ubuntu:18.04 bash

root@d3da654e2a5f:/# docker
bash: docker: command not found
```

コンテナ内からDockerを使う方法は、dindとdoodの2種類の方法があります

## 通常のDocker
ホストPCのDocker上で全てのイメージを起動します
全てのプロジェクトのコンテナは同じDocker上に存在します（皆兄弟）

<img width="505" alt="スクリーンショット 2019-11-22 16.24.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13916/16076ff6-4e98-da34-9159-a08b0f0e28cb.png">

不便ですよね？

## dind

プロジェクト毎に dind Dockerを立ち上げます（ privileged フラグが必須！！ ）
プロジェクト毎のDockerにログインし、そこで Dockerイメージを作成します
Dockerイメージは親子関係で作成されます

<img width="530" alt="スクリーンショット 2019-11-22 16.25.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13916/b12fca11-e0a3-78cc-b983-e148e4dc5786.png">


```bash
$ docker run -it --privileged -v $('pwd'):/volume -w /volume  -d docker:dind

root@e394f7876063:/volume# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

root@e394f7876063:/volume# docker run -it busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
0f8c40e1270f: Pull complete 
Digest: sha256:1303dbf110c57f3edf68d9f5a16c082ec06c4cf7604831669faf2c712260b5a0
Status: Downloaded newer image for busybox:latest
/ # exit

root@e394f7876063:/volume# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@e394f7876063:/volume# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              020584afccce        3 weeks ago         1.22MB
```

別プロジェクトのコンテナは見えないし影響を与えない
完全にプロジェクト毎のSandbox環境に成功しました！


## dood
dindに近い考え方として　Docker Out of Dockerがあります

dindなDockerを立ち上げます。
このとき privilegidフラグはたてず、docker.socファイルを Volumeでマウントします
プロジェクトのDockerコンテナにログインし、dockerコマンドを使うと ホスト上のdockerホストに繋がります
ここで作ったコンテナはホスト上に作成されます=兄弟関係

<img width="655" alt="スクリーンショット 2019-11-22 16.25.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13916/8df1fc93-1115-83ea-8940-dc649100e6f8.png">

```bash
$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker:dind bash

root@b49f798ae8ca:/# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
b49f798ae8ca        docker:dind         "bash"              6 seconds ago       Up 5 seconds                            crazy_goodall
root@b49f798ae8ca:/# docker images
REPOSITORY                TAG                   IMAGE ID            CREATED             SIZE
docker                    dind                  3c34f16aeaa0        24 hours ago        505MB
<none>                    <none>                31f248f7f9b6        24 hours ago        658MB
ubuntu                    16.04                 5f2bf26e3524        3 weeks ago         123MB
ubuntu                    18.04                 775349758637        3 weeks ago         64.2MB
buildpack-deps            stretch               81af74c34933        5 weeks ago         835MB
golang                    1.12.7                be63d15101cb        4 months ago        814MB
docker                    1.13.0-dind           7d6978320b24        2 years ago         99MB

(ホストのDockerイメージが見えている)

root@b49f798ae8ca:/# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
0f8c40e1270f: Pull complete 
Digest: sha256:1303dbf110c57f3edf68d9f5a16c082ec06c4cf7604831669faf2c712260b5a0
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest

root@b49f798ae8ca:/# docker images
REPOSITORY                TAG                   IMAGE ID            CREATED             SIZE
docker                    dind                  3c34f16aeaa0        24 hours ago        505MB
<none>                    <none>                31f248f7f9b6        24 hours ago        658MB
ubuntu                    16.04                 5f2bf26e3524        3 weeks ago         123MB
ubuntu                    18.04                 775349758637        3 weeks ago         64.2MB
busybox                   latest                020584afccce        3 weeks ago         1.22MB
buildpack-deps            stretch               81af74c34933        5 weeks ago         835MB
golang                    1.12.7                be63d15101cb        4 months ago        814MB
docker                    1.13.0-dind           7d6978320b24        2 years ago         99MB

（ホストのDockerイメージに追加された）
```


通常のDocker起動と違うのは、Dockerコンテナから兄弟関係のコンテナを作成＆利用出来ることです
プロジェクトごとにDockerイメージは別れないので今回の目的には合致しません

CIや、状況に応じてコンテナを生成破壊をするサービスには DooDが向いています（たいていは DinD使わなくてもよい）

# dindを使いこなす
まず、Docker in Doockerの開発者によると
dindを使うときは本当にdindが必要なのか再度考えてみろ
大抵のことはdoodでできる
dindはDockerの開発用途だ

https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/

ということで、おそらく私の使ってるdindも、開発者いわく、使うなと言うことだろうけど
面白いんで使ってみます

実際の使い方を

https://github.com/YukiMiyatake/util/tree/master/environment/docker_sandbox

上記にスクリプトなどを追加して、より良い環境を構築中です

## dindイメージの作成
プロジェクト毎に、dindのDockerイメージを作成します
dindの公式イメージはalpineですが、開発用のホストとして使うのは辛いので
ubuntuなりarchなり好きなイメージを作りましょう
上記の Dockerfileとwrapdockerで、好きなOSのイメージを作れるようにしています

## コンテナの作成
コンテナ名を環境変数で指定するために direnvを使ってます

```bash
docker run -it --privileged --name $PROJECT_GROUP -v $('pwd'):/volume -w /volume  -d docker:dind
```

docer_run.shに、コンテナの作成例をかいています
ディレクトリをマウントすると大抵の場合便利です
スクリプトでは dindイメージをそのまま使っていますが、プロジェクトで使うツールや言語などをDokerfileで書いておくと便利です

## コンテナの実行

```bash
docker start $PROJECT_GROUP
docker exec -it $PROJECT_GROUP bash
```

コンテナの中に入ります
普段どおりにコンテナを作って開発を行います


## その他
プロジェクトが終了した際などは、親のコンテナを削除すれば全部キレイになくなります！

ただし dindはvolumeを自動でつくるため、volumeも削除しましょう（volumuとコンテナを全部Cleanにするスクリプト作りたい）

あと、時々 commitしてコンテナをイメージに焼いて置くと安心

###メリット
プロジェクトごとにディレクトリもコンテナも分かれるので、もしもの時の心配がない
他のプロジェクトの修正の影響を万が一にもうけない
フォルダもプロジェクトごとにSandbox化できるので、変なことが起きにくい
スクリーンショット見せたときに、他のサービスのコンテナリストが出ない
マイクロサービス等のコンテナが複数あるサービスで、全てのコンテナを消すのが簡単

###デメリット
Sandbox毎にOSやDBのイメージがPullされるのでストレージ容量を使う
Privilegeフラグが必要