【翻訳】なぜDockerを気にしなければならないのか?

原著者[Chinmay Shah](https://medium.com/@chinmay_shah)氏の許諾を得て翻訳・公開しています。
記事:[Why you should care about Docker?](https://towardsdatascience.com/why-you-should-care-about-docker-9622725a5cb8)
原文公開日:2019年1月23日

もしあなたがソフトウェアエンジニア、もしくはデータサイエンティストなら、もうdockerについて聞いたことはあるでしょう。  

私が気になっているのは、インターネットで見て回ったディープラーニングのフレームワークや他のほとんどのフレームワークがdockerをサポートしていることです。
このdockerとは何なのか考えるようになりました。  

dockerとは何なのか、ひと目見ただけで直感で理解できるものではありません。  

![DockerLogo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/a112b68a-4338-8129-27a9-03ecc8a393e5.png)

しかしdockerに取り掛かる前に、 仮想マシンとコンテナが何なのか理解する必要があります。  

# "コンテナ"、"仮想マシン"とは何か?

コンテナと仮想マシンは、目的という点で似ています。それは、アプリケーションとアプリケーションの依存関係を、どこでも実行できる自己完結型のユニットに分離することです。  

またコンテナと仮想マシンは、物理ハードウェアの必要性を取り除き、エネルギー消費と費用対効果の両方の面でコンピューティングリソースの効率的な使用を可能にしています。  

コンテナと仮想マシンの主な違いは、アーキテクチャのアプローチです。
![ArchitectureOfVMandContainer.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/b71738c1-5c17-ad88-b3cd-008f61ccc6f3.jpeg "仮想マシンとコンテナのアーキテクチャ")


上記の図から明らかなように、仮想マシンはホストOSの上に追加レイヤーを追加して構築されています。
これらはコンテナでは使われていません。  

もしあなたが私のような人であれば、dockerはたくさんの実験ができ、環境変数について気にする必要がない、良いVMと考えておいてください。

# Dockerとは何か？
Dockerが実際に行うことは、インフラの要件とニーズからアプリケーションコードを分離することです。'コンテナ'と呼ばれる、隔離された環境で各アプリケーションを実行することで分離しています。

これは開発者が、最終的に実行されるシステムについて気にかけることなく、Dockerコンテナで実行するためのコードに集中できることを意味しています。そしてDevOpsは、Dockerコンテナにインストールされるプログラムの正しさを確認することに集中でき、デプロイ後に必要なシステムの数やメンテナンスの複雑さを削減することができます。

#なぜ気にしなければならないのか?
あらゆるDockerコンテナは、何もインストールされていないバニラのLinuxとして開始します。  

そしてアプリケーションを実行するために、ダウンロードしてインストールする必要がある全ての依存関係をコンテナに指示します。このプロセスは```Dockerfile```で行われます。

このセクションでは、Dockerはまったく同じ依存関係が加えられ、分離された新しいマシンとして毎回起動しているので、Dockerはアプリケーションのデプロイから推測の作業(とデバッグにかける時間)を毎回取り除いてくれるというだけで十分です。

Dockerの環境では、異なるバージョンの依存関係はインストールされません。また依存関係を見失うこともありません。Dockerは無意味なことを行いません。  

1. **使いやすさ:** Dockerはどんな開発者やシステム管理者、アーキテクト、その他の人に対しても、軽量なアプリケーションを素早くビルド、テストするためにコンテナを利用することをとても簡単にさせます。どんな人でもラップトップ上でアプリケーションをパッケージ化できます。 そしてこのパッケージ化したアプリケーションは、どのパブリッククラウドでもプライベートクラウドでもベアメタルでも変更なしで実行できます。「一度ビルドすればどこでも実行できる」のです。  
 
2. **スピード:** Dockerコンテナはとても軽量で高速です。
コンテナはカーネル上でのサンドボックス化された実行環境なので、リソースを少し使用するだけです。仮想マシンは毎回全ての仮想OSを立ち上げるので実行に時間がかかるのに比べ、Dockerコンテナはすぐに作成し実行することができます。  

3. **Docker Hub:** DockerのユーザはDocker Hubのエコシステムがますます充実していることから恩恵を受けており、Dockerイメージのapp storeと考えることができます。Docker Hubは数万のパブリックイメージを持っています。このパブリックイメージはコミュニティによって作成され、すぐに使用することができます。Docker Hubは、あなたのニーズに合ったイメージの検索が信じられないほど簡単にでき、プルダウンし変更をほとんどすることなく使用できます。  

4. **モジュール性とスケーラビリティ:**Dockerはアプリケーションの機能を個別のコンテナに入れることが簡単にできます。例えば、Node.jsのアプリ、Postgresデータベース、Redisサーバーを別々のコンテナで動かしているとします。Dockerを使うことで、あなたのアプリケーションを作るためにこれらのコンテナをリンクさせることが簡単になり、将来個別にコンポーネントのスケールやアップデートが簡単になります。  

# Dockerを使い始めてみましょう
Dockerのウェブサイトに行きましょう。もしWindows10 Homeエディションを使っているならDocker Toolboxが必要です。  

Dockerをインストールしたならば、Dockerでubuntuイメージを実行しましょう。  

Dockerは、プレビルドされたイメージを使うことや既存のイメージ上で構築することができます。既存のイメージ上で構築するのはすごくワクワクします。  

必要なもののみでイメージをカスタマイズしましょう。  

Dockerfileを見始めるに、インストールが完了していることを確認しましょう。  

Docker Quickstart Terminalを開きます。  
![DockerQuickStartTerminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/a272e4af-3809-ee20-fc74-ab23aa3ebd9f.png "Docker Quick Start Terminal")  

セットアップが正常に終わっていることを確認するために、Dockerが提供しているデフォルトのイメージを実行してみましょう。  

```
docker pull hello-world
```

![docker_pull_command.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/da97fe7a-a418-0f2d-d4da-eeb3dc7d0e25.png "docker pull コマンド")  

プルしたイメージを見るために以下のコマンドを入力します。  

```
docker image ls
```

最後に、Docker上でHello, worldを表示するためにしばらく待ちます。  

![running_the_helloworld_container.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/c08edef5-a424-fb51-d757-1ca4657d5313.png "hello-worldコンテナを実行")

```
docker run hello-world
```

# Dockerfile - すべてが始まるところ
Dockerはパワフルなツールですが、そのパワーはDockerfileと呼ばれるものを使用することにより発揮されます(上記のとおり)。

> 
*この```Dockerfile```は、イメージを組み立てるためにコマンドラインで使用できる全コマンドを含むテキストドキュメントです。```docker build```を使用することで、複数のコマンドラインの命令を連続して実行できる自動ビルドを作成することができます。
DockerのDockerfile Referenceより*  

Dockerイメージは読み取り専用のレイヤーから成り立っています。
各レイヤーはDockerfileの命令を表します。このレイヤー1つ1つは、以前のレイヤーからの差分として積み上げられています。  

Dockerコンテナが起動するとき、何をすべきか教えられている必要があります。コンテナには何もインストールされておらず、何も知っておらず、何もないのです。  

Dockerfileが最初に要求するものは**ベースイメージ**です。
ベースイメージはコンテナに、UbuntuやRHEL、SuSE、Node、JavaなどのOSのインストールを指示します。  

次にセットアップの指示を出します。
環境変数、インストールの依存関係、ファイルが存在する場所などといったものは全てDockerが知っておく必要があります。  

最後に、コンテナに何をすべきか指示します。通常、セットアップの指示で指定されたアプリケーションのインストールやコマンドが実行されます。

# DockerでUbuntuを実行してみましょう
以下に、各行の説明とレイヤーごとに何が起きているかをコメントで書いているサンプルのDockerfilesがあります。

```
# Docker hubからubuntu 18.04を取得します。

# その他のUbuntuバリエーションは
https://hub.docker.com/_/ubuntuにあります。
FROM ubuntu:18.04

# 必要なものをアップデートします。

RUN apt-get update

# イメージがビルドされたとき、最初に開かれるディレクトリは、/homeととなります。

WORKDIR /home
```

このファイルをDockerfileとして保存します。  

Docker Quickstart Terminalを開き、Dockerfileがある場所にカレントディレクトリがあることを確認してください。  

```
docker build .
```

これを行うとdockerはイメージを作成しますが、イメージに名前をつけなければ、dockerによってランダムな名前を与えられることを覚えておいてください。  

```
docker build -t ubuntu1:latest .
```

これは、ubuntu1として名前がつけられて、イメージがビルドされます。  

```
docker image ls
```

![docker_images.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406773/e5ec9014-591b-1750-5ed6-8104574b8058.png "Docker images")


少なくとも10GB割り当てる必要がある仮想マシンを使うときと比べて、イメージサイズが111MBのみで済んでいることが分かります。  

ビルド時に *-t* タグを使っていないときは、リポジトリ名とタグはnoneとなることに注意してください。そのためイメージを使用しようとするときは、IMAGE IDを覚えておく必要があります。  

*-t*は基本的に*repository:tag*のフォーマットとなります。  

タグをつけ忘れたならば、dockerはデフォルトでlatestのラベルを付けます。  

最後に、  

```
docker run --rm -it ubuntu1:latest
```

*--rm* は、コンテナ実行後に、そのコンテナをすぐに破棄します。  

*-it*はターミナルを使用して対話したい場合に使います。  

dockerターミナル上で、Ubuntuシステム上で入力できる全てのコマンドを入力できます。  

# まとめ
これで、あなたがDockerのハッキングを始められる必要な知識を備え、このツールの信じられないほどの力を実感できるようになったことを望んでいます。  

もしあなたがこれを気に入ってくれたのなら、[Pythonの開発のためのDocker パート2](https://medium.com/@chinmay_shah/docker-for-python-development-83ae714468ac)があります。  

[Twitter](https://twitter.com/chinmayshah899)や[Linkedin](https://www.linkedin.com/in/chinmayshah99/)、[E-Mail](mailto:chinmayshah3899@gmail.com)で気軽に連絡してください。  

# 翻訳を終えて
記事を初めて翻訳したため、分かりづらい表現があったかもしれません。
誤訳等ありましたらご指摘をお願いします。