Dockerを使って思い通りの開発環境をなんとか構築できるようになるまでに必要なミニマムの知識を共有するよ①

## はじめに
Dockerで環境構築をして開発しているエンジニアが増えてきました。
  
私がお世話になっているWeb開発会社はRailsをメインに使っていますが、
環境構築はDockerで行っています。Dockerのコマンドを打つだけで、それまで何時間もかかっていた環境構築が、パパっと終わった衝撃は今でも忘れられません。

ただ、Dockerってちょっと、**とっつきにくくないですか？**

Dockerを覚えたいと思って、[公式チュートリアル](https://docs.docker.com/get-started/)や、[それ日本語訳サイト](http://docs.docker.jp/)を読んで勉強しようとしてはみたものの、、、「内容が難しい...」「どこまでの概念を把握すれば良いの？」などと、感じました。
  
そこで自分は、**「習うより慣れろ」**の精神で手を動かして学んでみると、だんだんとDockerの理解が深まり、自分でdocker-compose.ymlやらDockerFileを曲がりなりにも少しずつ書けるようになってきました。

今回はそこまでに必要な最低限の情報をシェアします。
他者が作った開発環境を使うだけではなく、
自分でアレンジしたり、ゼロからそれっぽいものが作れるようになるかと思います。

### 前提
* コマンドライン/プロンプトで基本的な操作ができる読者を想定して書いています。。
* Dockerの基本的な事項が何となくわかっている読者を想定して書いています。```docker-compose up -d```のようなコマンドを打ったことある。
    * Dockerがどんなものかは、例えば以下の記事がわかりやすいかと思います。
        * [Docker入門 #1 【Dockerとは](https://qiita.com/wMETAw/items/b9bc643ded4b92bf6add)
        * [今日から始めるDocker【基礎概念編】](https://qiita.com/yu-croco/items/bf54f007c84aba7c8da6)

## 最低限の知識

### 1：Docker? DockerFile？
Dockerはコンテナと呼ばれるプロセス（プログラム）単位のアプリケーション実行環境です。
Dockerコンテナの構築は、

* Docker Hub(あるいは他リポジトリ)から、既に存在するイメージを```docker pull```して構築する。
* 設定ファイルである、DockerFileを元に```docker build```で構築する。

といった、大きく2つの方法がありますが、どちらもコンテナを構築するコマンドです。
まずここを押さえましょう。

### 2：Docker Compose？ docker-compose.yml?
Docker composeとは、複数のコンテナの構築、起動を自動的に行い、コンテナの管理を容易にする機能です。
以下のような連続するコマンドでDockerを説明しているサイトがあると思いますが、
```$ docker pull mysql  
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql
...```
Docker Compose機能は、上記のようなイメージの取得（あるいはイメージ構築）とコンテナの起動を一気に複数コンテナ分行うことができます。通常、開発環境では「アプリケーションサーバー+DBサーバー」のような複数のサーバー構成が一般的かと思われます。ですので、Docker Composeを使うことで、Dockerコンテナの立ち上げが用意になります。Docker Composeは専用の設定ファイル(docker-compose.yml)を元に動作します。
### 3：docker-compose.ymlのミニマムの知識
```
# docker-compose.yml
version: '2' # ①

services:
  php:
    build: ./php # ②
    volumes:
      - ./src:/var/www

  nginx:
    image: nginx # ②
    ports:       # ③
      - "80:80" 
    volumes:     # ④
      - ./src:/var/www
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:  # ⑤
      - php
      - mysql

  mysql:
    image: mysql:5.7
    environment:   # ⑥
      MYSQL_ROOT_PASSWORD: mysql
```
#### ①
docker-compose.ymlのファイルのバージョン（書式）を指定します。
Versionは2以降を指定して下さい。

現在(2018/07断面では最新のバージョンであるVersion 3が使えるようになってきていますが、例えば[Should I Upgrade My Docker Compose File Version From 2 to 3?](https://vsupalov.com/upgrade-docker-compose-file-version/)では「違いはあるものの大きな違いではない」と解説しています。今回は2を使います。

#### ②
Dockerコンテナの構築方法を指定します。指定の仕方として2つあり、
```
  php:
    build: ./php
```
のようにDockerFile(ここでは./php/DockerFile)を指定して構築する方法と
```
  nginx:
    image: nginx
```
のようにDockerHub(Dockerイメージが多数登録されている公式リポジトリ)のイメージを指定する方法があります。

後述しますが、

* apt-get updateなどのパッケージ更新
* vimなどコンテナ内で作業する際のツールインストール

などを行いたい場合は、DockerFileを使って構築する方法がわかりやすいかと思われます。

#### ③
コンテナのポートを公開（expose）する設定です。例えば
```
    ports:
      - "8080:80" 
```
と記載すると、コンテナ起動後に`http://localhost:8080`とアクセスすると、コンテナの80ポートへアクセスしたことになります。

#### ④
ホストとコンテナのvolume(ディレクトリ)を共有します。
`
      - ./src:/var/www
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
`
の場合、`./src`はコンテナの/var/www/へ自動的にマウントされます。
また、`- ./nginx/default.conf:/etc/nginx/conf.d/default.conf`
のように、ホスト側で予め設定ファイルを作成してから、コンテナに読み込ませる事も可能です。

#### ⑤
コンテナの起動に際して、依存関係を指定することができます。例えば、
`
    depends_on:
      - php
      - mysql
`
と記載すると、`docker-compose up nginx`と打った場合に、nginxコンテナを立ち上げる前にphpコンテナとmysqlコンテナを立ち上げてくれます。コンテナの80ポートへアクセスしたことになります。

#### ⑥
このように書くと、コンテナごとに環境変数を追加することができます。

## おわりに
長くなりましたので、一旦ここまで。
次号でDockerFileに触れていきます。

## 参考
上記の説明は、理解のしやすさを軸に書き下していますので、
細部では説明が適切ではない箇所があるかと思われます。詳細はDocker Document等御覧ください。
以下に参考リンクを記載しておきます。

Docker公式です。
[Docker Documentation](https://docs.docker.com/)
↑の日本語訳
[Docker Documentation　日本語化プロジェクト](http://docs.docker.jp/)

コマンドの詳細な解説です。イメージしやすいです。
[Dockerでよく使うコマンドまとめ](https://morizyun.github.io/docker/about-docker-command.html)

docker-compose.ymlの詳細な記載について解説されてます。
[docker-composeを使うと複数コンテナの管理が便利に](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa)

docker-compose.ymlの記載に慣れてきて、より効率的に書くには...(今読んでいます。)
[今更だけどdocker composeのベストプラクティス](http://innossh.hatenablog.com/entry/2017/04/22/192743)