【さらっとだけ覚えたい】Docker入門

# 前置
現場でついに出会ってしまった私が、
イメージだけつかみたいがために、情報をかき集めた結果になります。

# Dockerってなに
プロセスとして仮想OSを用意するイメージ。(これをコンテナという)
それぞれは独立して動いている。

【VMのイメージ】
![VM.jpg](https://qiita-image-store.s3.amazonaws.com/0/24484/149be47f-2233-f9dc-44d9-e674b28d75f3.jpeg)

【Dockerのイメージ】
![Docker.jpg](https://qiita-image-store.s3.amazonaws.com/0/24484/d12dc760-5510-dbb6-795e-60bd282f2e0c.jpeg)

## メリット
軽いらしいです。
開発環境で動いて、本番でうごかなーいなんてこともならないらしいです。

## Docker Compose
dockerだけだと、コンテナをひとつひとつ作成、起動する。
Composeを使えば、複数のコンテナの立ち上げや依存関係を管理できる。

# お試し環境
## ホストはCentOS7で
CentOSの場合、6がもうサポートされないとか何とか。
なのでホストは7でやる。

## VitrualBox + CentOS7
結局、仮想マシン使うのかよｗｗｗｗ
というつっこみはしないでください(・ω・)
お勉強ですから。

べ、べつにVagrantとかでもいいんだからねっ(そういう話じゃない？

以下、CentOSを使うまでのごにょごにょ。

**[1]VirtualBoxが古すぎると、CentOS7でネットワークの設定ができなかった**

**[2]ネットワークの設定で使用したコマンド**

```bash
# GUIっぽい設定できるやつ開いてくれる 
nmtui

# ネットワークの更新
systemctl restart NetworkManager

# 確認
ip a
```

**[3]その他にやったこと**

```bash
# パッケージの更新
yum update
reboot

# 以下の手順で必要そうなもののインストール
yum install -y bzip2 kernel-devel gcc

# CDドライブのマウント
mkdir /media/cdrom
mount -r /dev/cdrom /media/cdrom

# GuestAdditionsのインストール
sh /media/cdrom/VBoxLinuxAdditions.run install

# VirtualBoxの共有フォルダ設定したものをマウント
mkdir -p /mnt/project
mount -t vboxsf project /mnt/project
echo -e "mount -t vboxsf project /mnt/project\nexit 0" | tee -a /etc/rc.local
chmod 744 /etc/rc.d/rc.local
```

# インストール
## Docker
参考：https://docs.docker.com/engine/installation/linux/docker-ce/centos/#install-using-the-repository

```bash:リポジトリの追加
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager --enable docker-ce-edge
yum-config-manager --enable docker-ce-testing
```

```bash:dockerインストール
yum makecache fast
yum install docker-ce
docker --version
```

```bash:起動
systemctl start docker
systemctl enable docker
systemctl list-unit-files | grep docker
```

## docker-compose
```bash::docker-composeインストール
curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
```

## 20170712時に試した環境
```bash:環境
[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

[root@localhost ~]# docker -v
Docker version 17.06.0-ce, build 02c1d87

[root@localhost ~]# docker-compose -v
docker-compose version 1.14.0, build c7bdf9e
```

# Dockerコマンド
## のまえにライフサイクル
を知っておくと、各コマンドのイメージがつきやすいかも。

参考：[Dockerにおけるコンテナのライフサイクル](http://enakai00.hatenablog.com/entry/20140628/1403933390)

|コマンド|説明|
|:--|:--|
|run|イメージから、プロセスの起動とスナップショットの作成|
|start|スナップショットからプロセス起動|
|stop|プロセスの停止|
|rm|スナップショットの削除|

## ローカルにあるイメージを表示
```bash
docker images
```

## コンテナの実行
```bash:実行と停止
docker run -itd イメージ名 [コマンド]

docker stop コンテナ名
```

|オプション|説明|
|:--|:--|
|-it|コンテナ内で操作するのに必須|
|-d|バックグラウンドで実行|
|-p HostPort:GuestPort|ポートの割り当て|
|--name 名前|コンテナにつける名前|
|-v GuestDir|データボリューム(後述)|
|-v HostDir:GuestDir|データボリューム(後述)|
|--volumes-from コンテナ名|データボリューム(後述)|

※事前にイメージの取得を行わなくても、run時に存在しなければ勝手に取りに行く

```bash:いちおうイメージ取得のコマンド
# 「https://hub.docker.com/explore/」でも探せる
docker search イメージ名

docker pull イメージ名[:タグ]
```

※タグ
イメージのバージョンは、TAGというみたい。
タグを指定しない場合、latestが自動で落ちてくる

## コンテナの中でコマンドを実行
```bash
docker exec コンテナ名|コンテナID コマンド

# /bin/bashでシェル起動
docker exec -it コンテナ名|コンテナID /bin/bash
```

## コンテナ簡易情報の一覧取得(コンテナ名とか)
```bash
docker ps[ -a]
```

## イメージの削除
```bash
docker rmi イメージID
```

## コンテナの削除
```
docker rm コンテナ名
```

## コンテナの詳細を取得
```bash
docker inspect コンテナ名|コンテナID
```

## 再起動
```bash
# 直前のコンテナ情報を確認
docker ps -l

# 細かい情報はいらない
docker start コンテナ名
```

## コンテナの標準出力を見る
```
docker logs コンテナ名
```

# イメージの作成
せっせとコンテナを作ってコミットする方法もあるが、
メンテナンス等の問題もあるので、Dockerfileを用意して、
ゼロからイメージを作成するほうが良い。

## Dockerfileの記述方法
```
# 元となるイメージ名の指定
FROM イメージ名

# このファイルの管理者情報
MAINTAINER 管理者情報

# ファイルのコピー
ADD コピー元 コピー先

# コンテナ内で実行するコマンド
RUN コマンド

# 環境変数の設定
ENV 変数名 値

# docker runで指定するコマンド
CMD ["コマンド"]
```

## ビルド(イメージとして追加)
```bash
docker build -t イメージ名[:タグ] DockerFileのあるパス
```

```bash:イメージ名を後から付け直す
docker tags イメージID イメージ名:タグ
```

**※ビルド中、yumのRPMDBが破損する・・**
Dockerのストレージドライバの種類によって、バグがあるらしく。
参考：[aufs/overlayfs/btrfs bugs](http://qiita.com/AkihiroSuda/items/7db89f48d50b98fa1fa8)
参考：[ストレージドライバってなんやねん](http://knowledge.sakura.ad.jp/knowledge/5021/)

```bash
[root@localhost ~]# docker info
~
Storage Driver: overlay
~
```

ので

```yaml
RUN yum install -y yum-plugin-ovl
```
で一旦解消

# コンテナのネットワーク
個人的には、開発で使う分にはそんなに気にしなくて良いような知識。
とばしてもおｋ。

ここでのネットワークとは、コンテナの連結的なことみたい。
指定がなければdockerは「bridge」にコンテナを作成する。

```bash:デフォルトの三つ
docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
37eddf42572b        bridge              bridge              local
a4c6bd57e68e        host                host                local
43939dacfb4f        none                null                local
```

## ネットワークの分離
という意味合いで公式では紹介されているので、
その作成と加入方法を転載。

```bash:ブリッジネットワークの作成
docker network create -d bridge ネットワーク名
```

```bash:起動と同時に加入
docker run -d --net=ネットワーク名 イメージ名
```

```bash:あとから加入
docker network connect ネットワーク名 コンテナ名|コンテナID
```

# データ･ボリューム
コンテナの中でデータを保持しても、コンテナを削除してしまえば残らない。
ので、永続化を目的にボリュームを用意する。

**[1]ホストのお好きなディレクトリをコンテナが参照**

```bash
docker run -v /tmp/host:/tmp/guest -d centos
```

**[2]ホスト側にDocker用のボリュームを作成し、それを参照**
「/var/lib/docker」配下に配置されるため、[1]の短縮っぽい記載ができる。

```bash
docker run -v /tmp/guest -d centos
```

コンテナが削除されれば、その参照ができなくなるようだ。
「/var/lib/docker/volumes/」にある。

```bash
# ボリュームの確認
docker volume ls

# 削除
docker volume rm ボリュームID
```

**まとめ：ボリューム用のコンテナを用意しよう(データボリュームコンテナ)**

```bash:ボリューム付でコンテナの作成だけする
docker create -v /dbdata --name dbdata centos
```

```bash:コンテナ名でボリュームを参照する
docker run -d --volumes-from dbdata --name db mysql
```

**共有ストレージ**
※要プラグイン調査

ホストに依存しない設定が可能。

```bash:ストレージの作成
docker volume create -d プラグイン名 --name ボリューム名 -o size=サイズ
```

バインドには「-v」オプションを使えばよい。

# Docker Compose
複数のコンテナを使うDockerアプリケーションを、定義・実行するツール。

docker-compose.ymlの記載方法だけなんとなくわかれば、
あとはコマンドで立ち上げるだけ。

## 流れ
[1]Dockerfileつくる
[2]docker-compose.ymlで独立したDockerfileをとりまとめる
[3]docker-compose upでアプリケーション全体を起動・実行

## 基本的なコマンド
```yaml:バックグラウンドでコンテナを作成、実行
docker-compose up -d
```

```yaml:コンテナの開始、停止(コンテナが存在しないとだめ)
docker-compose start
docker-compose stop
```

```yaml:yamlを元にコンテナを停止、削除
docker-compose down
```

```yaml:コンテナ一覧
docker-compose ps
```

## docker-compose.yml
環境変数は${変数}で使える。

```yaml:例)docker-compose.yml
version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
     - logvolume01:/var/log
    links:
     - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
```

**version**
Composeファイル形式のフォーマット。
20170710現在では２で。

```yaml
version: '2'
```

**大項目**
は、「services」「networks」「volumes」になる。

**services用設定**
定義できるものは「docker run」に似ている。

```yaml
services:
  web:  # 任意のサービス名をつけられる
    hostname: name  # ホスト名はコンテナの判別にも便利
    depends_on:  # 依存関係のある他サービスを先に実行
      - db
    networks: # カスタムネットワークを指定する場合
      - custom_network
      default: # アプリ全体に適用されるデフォルトネットワークの場合
        aliases:
          - hoge # ネットワーク上のサービスに対してのエイリアス
    build:
      context: . # Dockerfile があるディレクトリのパス
    image: centos  # buildが存在する場合はイメージ名付与
    environment: # 環境変数を追加
      - Hoge=hoge
    expose:  # 他のコンテナへに対し開放ポートを指定
      - "80"
    ports:  # ホストとコンテナのポートをバインド
      - "80":"80"
    volumes:  # ボリュームの紐付け
      - /tmp/guest_dir
      - /tmp/host:/tmp/guest
    volumes_from:  # 他のボリュームへの紐付け
      - db
    working_dir: /tmp/guest_dir # コンテナの作業用ディレクトリ
    # tty: true # dockerコマンドの-tにあたるもの
    privileged: true  # ケーパビリティの制限を解放
```

※[depends_onとlinksの違い](http://qiita.com/sivertigo/items/9baa73d922a68788402b)
バージョン２ではlinksはかかなくてもいいみたい

※privilegedとかケーパビリティとか
http://www.tsugihagi.net/entry/2014/10/05/083120

**volumes用設定**
定義できるものは「docker volumes create」に似ている。

共有ストレージとか使ってないなら無縁？

```yaml
valumes:
```

**networks用設定**
定義できるものは「docker network create」に似ている。

カスタムネットワークとか使ってないなら無縁？

```yaml
networks:
```