---
# System prepended metadata

title: KT#005-kanda Docker
tags: [docker]

---

# KT#005-kanda Docker
###### tags: `docker`
## 参考ページ
公式ページ・図付きの解説ページを時間のあるときに読むとわかりやすい。
[Docker ドキュメント日本語化プロジェクト](http://docs.docker.jp/v1.9/)
[Docker入門（第一回）～Dockerとは何か、何が良いのか～](https://knowledge.sakura.ad.jp/13265/)
[いまさらだけどDockerに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)

## Dockerを一言でいうと？
仮想マシンのように仮想OSごと立ち上げるのでは無く、ホストOSのカーネルを利用して簡単・高速・軽量にアプリケーションを動作させるコンテナ技術。

## コンテナって何？使い方は？
### コンテナ技術の需要
あるホストOS上で、仮想的に環境を構築したい場合、従来（コンテナを使わないという意味）は仮想OSを起動し、その上にミドルウェアをインストールするなどしていた。
例）VirtualBoxでCentOSを起動してその中にMySQLをインストールして利用

この方法は、「ホスト環境を汚さない」という点では便利であったが、
- 仮想OSを起動するためリソースや時間を多く消費する
- 作り上げた環境を移行したりコピーしたりすることが難しい
といった欠点も多くあった。

そこで、仮想OSをまるまる立ち上げずに、ホストOSのカーネルだけを借りてミドルウェアを動かそう、という技術が生まれた。これがコンテナ技術である。ここでいう「コンテナ」は基本的に一つのミドルウェア（WebサーバやDBサーバなど）を指す。

コンテナ技術を利用すると、ホストOSでもともと稼働しているカーネルを利用するだけなので、軽量かつ高速にアプリケーションを動作させることができる。

また、1つの環境が1つのコンテナに対応しているため、ある開発メンバが構築した環境を他のメンバに共有することも簡単である。

### イメージとコンテナ
Dockerでは、そのコンテナの構築元となる「イメージ」と、実際に動作する実体である「コンテナ」という２つの存在がある。
#### イメージ
オブジェクト指向プログラミングにおける「クラス」のようなもの。すべてのコンテナは特定の一つのイメージから生成される。
イメージはDocker Hubに代表されるようなレジストリからダウンロードしてくるのが一般的である。また、あるイメージを拡張する形で新しいイメージを作成することが可能である。

イメージはレイヤー構成になっており、ベースとなるイメージに対してレイヤーを追加していく形でカスタマイズしていく。例えば、プレーンのCentOSに何かパッケージをインストールしたり、特定のポートを開放したり、ホストのファイルをイメージの中にコピーすることができたりする。レイヤーを追加したものをベースにコンテナを起動する。また、レイヤーを追加したものをまた別のイメージとしてまとめることもできる。

例）Springで作成したWebアプリケーションをコンテナでデプロイしたい場合
1. Webアプリケーションをwarファイルにビルドする
1. tomcatのイメージを準備する
1. tomcatのイメージをベースに、warファイルをコピーする
2. ポート番号8080を開放する
3. コンテナを起動する

#### コンテナ
オブジェクト指向プログラミングにおける「インスタンス」のようなもの。なにか一つのイメージに基づいて実際に起動されたプロセスを指す。

ユーザが実際にアプリケーションを動作させたりアプリケーションにアクセスするときはコンテナに対して操作を行うことになる。コンテナはホストマシンのCPUやメモリを使用する。起動時にホストマシンのもののうちどれぐらいを割り当てるかを指定可能である。

また、コンテナ同士は適切な設定をすれば疎通可能である。

## どうやって動かすん？
### Dockerのインストール
ホストマシンのOSによってインストール方法が異なる（大体そうだが）。
#### Linux系の場合
各ディストリビューションに応じたパッケージ管理ツールでDockerサービスをインストールする。
#### Windows/MacOS
Docker公式ページからアプリケーションをインストールする。

### Linux以外でDockerが動くのはなぜか
前述の通り、DockerのコンテナはホストマシンのLinuxカーネルを利用することで動作している。WindowsやMacOSはホストマシンにLinuxカーネルを持っていないため、そのままではホストマシンのLinuxカーネルを利用することができない。

そこで、DockerをWindowsで動作させるためには「Docker for Windows」のインストールが必要となる。これは、Windows上で動作するデーモンであり、Hyper-Vの機能を利用して動作している。結局**DockerにLinuxカーネルを提供するために仮想環境を裏で動かしている**のである。コンテナは裏で動いているDockerデーモンから必要なLinuxカーネルを提供してもらって動作する。

## ハンズオン
### 環境構築
各々のOSに合わせたDockerをインストールしておく。
### イメージを持ってくる
`docker pull <イメージ名>`でDocker Hubから該当するイメージを取ってこれる。メジャーなものはだいたいググればどういうイメージ名で取れるかわかるようになっている。

ちなみにイメージ名は`<リポジトリ名>/<イメージ名>:<タグ>`という命名規則があり、この内`<リポジトリ名>`と`<タグ>`は省略が可能である。

試しにubuntuのイメージをpullしてみる。コマンドは `docker pull ubuntu`。
pullできたかどうかは、 `docker images`で確認できる。ホスト上にダウンロードされたイメージが一覧表示されるので、ubuntuがあることを確認する。タグを指定しなかった場合、自動でタグが`latest`であるものをダウンロードする。
### 起動してみる
以下のコマンドでコンテナを生成・起動する。ややこしいが、**コンテナの「生成」と「起動」は別物である。**
```docker run -it ubuntu```

`docker run`は新しくコンテナを生成しつつ、そのコンテナを起動するコマンドである。
オプション`-it`はおまじないのようなもので、対象のコンテナに対して標準入力で操作しつつ出力もコンソールに流したい場合に利用する。コンテナを操作したい場合はこれつけとけば良い。

コンテナを起動したときに、そのコンテナが実行するコマンドはイメージによって規定されている。例えばTomcatのイメージでは、コンテナを起動すると自動でcatalinaが起動してwebアプリケーションをホストしてくれる。

`docker run`には様々なオプションがある。中でも`-p`オプションは疎通確認のためには重要である。このオプションは、ホストのポートとコンテナのポートをバインドしてくれるオプションである。

例えば、postgresのコンテナを起動し、ホストマシンからそのDBを参照したいとする。コンテナ自体はホストマシン上に存在するため、ホスト名は`localhost`でよいが、ポート番号を5432(postgresのデフォルトポート)に指定しても疎通できない。それは、`localhost:5432`でフォワードされるポートはあくまでホストマシンのポートであり、コンテナのポートとは別扱いであるためである。ここで、`-p`オプションで`5432:5432`としておくと、ホストマシンのポート5432に対するパケットはコンテナの5432にフォワードされる。

### コンテナの寿命
コンテナは基本的に生き続ける。停止してもコンテナは残り続ける。どれだけのコンテナが残っているかは`docker ps -a`でわかる。コンテナは停止させたり再開させたりが可能。もし停止したときに自動で削除させたいなら`docker run`コマンドのオプションで`--rm=true`をつけるといい感じになる。

## Dockerfileとは？
公式で転がっているイメージから、独自のカスタマイズをしてから起動したいケースが出てきたりする。また、毎回毎回決まったオプションをつけ直さないといけないのも手間である。そういった問題を解決してくれるのがDockerfileである。

ベースとなるイメージに対して行う操作をあらかじめ定義するのに用いられる。開発者は行いたいカスタマイズの内容をDockerfileにまとめ、そのDockerfileを基にイメージを**ビルド**する。ビルド済みのイメージからコンテナを生成することで、Dockerfileで定義した通りのコンテナを起動することができる。複数の開発環境で同じイメージを使いまわしたい場合は、そのDockerfileを共有すればよい。

Dockerfileでできる例を以下に挙げる。
- ホストマシンのファイルをイメージ内に埋め込む（コピーする）。
- ポートを開放する。
- コンテナ内で特定のコマンドを実行させる。
- 環境変数を指定する。
## docker-composeとは？
複数のコンテナを起動し、コンテナ間で疎通させたいとき、docker-composeを利用すると楽に実現できる。

docker-composeは複数のコンテナを一括で管理できる仕組みであり、コンテナの名前付けによる名前解決や、コマンド一発で複数のコンテナを起動・停止できる。WebサーバとDBサーバを同時に立てて、同一のネットワーク内に配置し、コンテナ名をホスト名として名前解決できたりする。

Dockerfileは「イメージの作成時」に効果を発揮するのに対し、docker-composeは「コンテナの起動時」に効果を発揮する。

複数のコンテナに限らず、単一のコンテナの起動時でもdocker-composeは有用で、細かい起動時のカスタマイズ（ボリュームのマウントなど）のためにdocker-composeはどんどん使おう。
## Kubernetesとは？
コンテナのオーケストレーションのためのソフトウェア。Google様が先導して開発している。

docker-composeよりも大規模かつスケーラビリティや可用性が求められるアプリケーションにとって有用。負荷が高まったら自動でコンテナを増やし、ロードバランシングまでしてくれる。また、アプリケーションの監視もでき、デプロイ・運用のデファクトスタンダードとなりつつある。