LoginSignup
27
21

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-11-22

motivation

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

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

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

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

$ 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を起動できないようになっています

$ docker run -it ubuntu:18.04 bash

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

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

通常のDocker

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

スクリーンショット 2019-11-22 16.24.52.png

不便ですよね?

dind

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

スクリーンショット 2019-11-22 16.25.07.png

$ 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ホストに繋がります
ここで作ったコンテナはホスト上に作成されます=兄弟関係

スクリーンショット 2019-11-22 16.25.14.png

$ 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の開発用途だ

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

実際の使い方を

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

dindイメージの作成

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

コンテナの作成

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

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

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

コンテナの実行

docker start $PROJECT_GROUP
docker exec -it $PROJECT_GROUP bash

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

その他

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

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

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

メリット

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

デメリット

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

27
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
21