Docker入門  Docker事始め　

# 今日の目標
ローカル環境に構築していたRailsとMySQLを、1コマンド叩くだけで実行できるようにするための方法を学ぶ

## そもそもDockerって何？
具体的な導入手順を解説するまえに、まずはDockerについておさらいしておきましょう。


>Dockerは、インフラ関係やDevOps界隈で注目されている技術の一つで、Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです。

こ〜んな説明がされていることが多いかと思いますが

### Docker何それ？美味しいの？？？

となってしまうのでもっと身近な例で例えると

>パソコン上でファミコンを動かすエミュレータのようなもの
-マンガでわかるDockerより-

ファミコンでカセットを入れ替えると違うゲームが遊べるように、dockerではDocker container(以後コンテナ)を入れ替えれば、また違う開発環境を作ることができます。

(ちょっと例えが古くてすみませんwww)

そして、コンテナをどのパソコンでも動かすためにパッケージ化したものをDocker Image(以後イメージ)と呼んでいるんですね。

プログラミングチックいえば、イメージはオブジェクトで、コンテナは実行中のインスタンスに相当します。

## Dockerが便利である理由~冪等性について~

なぜこんなことが実現できるかというと、Dockerには**冪等性(べきとうせい)**があるからですね。
冪等性とは、`何回実行しても結果が変わらない`ということ。

この冪等性のおかげで、同じDockerfileから作られたコンテナは、**何回立ち上げても同じ開発環境が立ち上がる**ので、差異が生じることはほとんどありません。

![picture_pc_73e5bc8e6474390aa6b4b3a955f7d0b5](https://user-images.githubusercontent.com/41051390/80859628-4b577b80-8c9d-11ea-975b-eed94e9e6bf5.png)

![picture_pc_eb29a8e08168426ef73b3f1dd50eba61](https://user-images.githubusercontent.com/41051390/80859663-6f1ac180-8c9d-11ea-94f9-52739e689a05.png)

という悩みから開放されるので、環境構築で躓くことがなくなるはずです。

## Dockerfileについて
コンテナを作成するには、
• DockerHubから公開されているイメージををダウンロードする
• Dockerfileを使って作成する

この2パターンあります。
**Dockerfile** というのは、**コンテナ**を作成するためのレシピのようなものです。

コマンド一つ一つの一つが、コンテナという料理を完成させるための原材料と考えればわかりやすいかもしれません。

**docker-compose build** といったような、所定のdockerコマンドを実行することでDockerは**Dockerfile** を読み込み、それを元にコンテナを作成します。

## docker-composeについて
Docker composeというのは複数のコンテナを同時に動かすためのツールのこと。

そして、そのDocker composeを利用するためにYAML形式で書いたファイルがdocker-compose.ymlです。
[docker-compose.ymlの書き方](https://qiita.com/keitah/items/ead34aaa18deab1c403e)

## 参考にするべきリファレンス
どんな場合でも公式ドキュメントが一番正確な一次情報となるわけですが、
Dockerの場合は下記2つが公式なサイトとなります。

[Docker公式サイト](https://www.docker.com/)

[Docker公式ドキュメント](https://docs.docker.com/)

当然英語となるわけですが、実は有志の方が作成してくれている日本語のドキュメントもあります。それが、下記のサイトですね。

[Dockerドキュメント日本語化プロジェクト](http://docs.docker.jp/)

ただし、こちらは情報が古い場合があるので、最初の情報を得る場合は、やはりDocker公式ドキュメントを参照するようにしましょう。

Qiitaやテックブログなどを参考にする場合は、リファレンスの該当箇所も合わせて読んでおくといいかもしれません。

##dockerのリファレンスの読み方
ここまでで、基本的なDockerfileやDockerComposeの概念について説明してきましたが、そうは言ってもすべてを網羅しているわけではないので、より深く理解していくためにはリファレンスを参照することになるでしょう。

リファレンスを読む場合のポイントは以下です。

###BestPracticeを参照する
動かすだけであればDockerfileやDockerComposeは適当に書いても問題ないですが、BestPracticeを参照すると、よりイメージを軽くすることができたり、パフォーマンスを上げることができます。

[Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)

**否定の見出しが書かれている箇所は注意深く読み込む**

全部に目を通す必要はないですが、少なくとも否定の見出しで書かれいる箇所は注意深く読み込んでおく必要があるかもしれません。

例えば、上記のベストプラクティス内で、

*Don’t install unnecessary packages*

という箇所があります。

イメージを作る際には余計なライブラリなどを入れるなという内容なのですが、これを知らないと、重くて遅いコンテナになってしまいます。

#本題　RailsアプリをDockerizeしてみる

Dockerizeする方法は色々とあるのですが、今回は**Dockerfile**と**docker-compose.yml**を使用します。

Dockerfileとdocker-comoose.ymlは、すごく噛み砕いていうと、Dockerにアプリケーションを立ち上げさせるための指示書です。

Dockerfileとdocker-comoose.ymlに書かれている内容を元に、Dockerは上から順番にプログラムを実行していきます。

### Dockerの導入

手元のPCにdockerを導入する

dockerコマンドを使うためには、 Dockerクライアントというものを使用します。

Dockerクライアントは、一言でいえば、Dockerのコマンドや便利機能をひとまとめにしてパッケージ化したものです

```
$ brew install docker
$ brew cask install docker
```
これだけでインストールはOKです。

```
$ docker -v
```

[![Image from Gyazo](https://i.gyazo.com/a023903cb152b467a1c8d83c4753f03e.png)](https://gyazo.com/a023903cb152b467a1c8d83c4753f03e)
上記のようにバージョンが表示されればインストール成功です！

### docker command not foundが表示された場合
もし、 docker command not found のような表示がされた場合は、
• dockerクライアントが導入されていない
• dockerクライアントは導入されているけど、何かしらが原因で動いていない

この2つが考えられます。

後者の場合は一旦dockerクライアントをアンインストールして

https://hub.docker.com/editions/community/docker-ce-desktop-mac

のページからブラウザ経由でダウンロードしてみてください。

docker-composeコマンドを使うためには、caskまたはパッケージからインストールしてきたDocker Desktopを起動する必要があります。

インストール後にLaunchpadからDockerアプリを起動しておきましょう！

##MySQLをセットアップする
Dockerではコンテナ内でMySQLを動かすので、ローカルマシンに別途インストールする必要はありません。

ですが、場合によってはローカルで確認したいことがあるのと思うので、brewを使ってインストールしておきます。

```
$ brew install mysql@5.7
brew link mysql@5.7 --force
```

こんな感じで@バージョン名とすることでバージョンを指定してインストールすることができます。

brew link　mysql＠5.7 --forceについてはforceオプションをつけてMySQL5.7を強制的に有効化するように指定しています。

### おまけ　最新版のMySQLのバージョンを使用する場合
ローカルに最新版のMySQLをインストールする場合も基本的にbrewでのインストール実行コマンドは同じ。

```
$ brew install mysql
$ brew link mysql --force
```
バージョン指定がなくなるだけですね。

MySQLにおけるローカルでの作業は以上です。

## config/database.ymlを編集する

Railsアプリケーションではデータベースに接続するためのファイルとして、YAMLという形式が記述したconfig/database.ymlがあります。

Railsでアプリケーションを作成する際にもdatabase.ymlをいじったと思いますが、dockerizeするときにも、このファイルに手を加える必要があるんですね。

さっそくみていきましょう。

```yml:config/database.
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: chat-space_development
test:
  <<: *default
  database: chat-space_test

production:
  <<: *default
  database: chat-space_production
  username: root
  password: <%=  ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock
```
こんな感じになっているかと思います

このファイルをdockerizeするため、現在のconfig/database.ymlを次のように書き換えてください。

```yml:config/database.yml
default: &default
 adapter: mysql2
 encoding: utf8
 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
 username: <%= ENV.fetch("MYSQL_USERNAME", "root") %>
 password: <%= ENV.fetch("MYSQL_PASSWORD", "root") %>
 host: <%= ENV.fetch("MYSQL_HOST", "database") %>
development:
 <<: *default
 database: docker_example_for_chat-space_development
test:
 <<: *default
 database: docker_example_for_chat-space_test
production:
 <<: *default
 database: docker_example_for_chat-space_production
```
違いとしては2つあって、一つはrootやpasswordなどを環境変数にセットしつつfetchしているところですね。
(まあ、これに関してはdockerizeするというよりも単純に書き方の一つではあるのですが)

で、もう一つはMYSQL_HOSTにdatabaseを指定していることです。

これで、config/database.ymlの修正は終わりです。

## Dockerfileの書き方について
さて、ここからはDockerfileの書き方について整理していきます。

```
$ mkdir -p docker/development
$ touch docker/development/Dockerfile
```
復習しておくとDockerfileとは、

• コンテナを作成するためのレシピに相当
• Dockerにアプリケーションを立ち上げさせるための指示書

でした

Dockerfileについてみていきましょう。

```
# docker_example_for_chat-space(Rails/MySQL)
FROM  ruby:2.5.1-alpine
LABEL maintainer="Keita Higaki<higaki.keichan@gmail.com>"
# 文字コードの設定
ENV LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \^
    LC_CTYPE="utf-8"
# 環境変数
ENV APP="/docker_example_for_chat-space" \
    CONTAINER_ROOT="./" \
    NOKOGIRI_OPTION="--use-system-libraries \
                    --with-xml2-config=/usr/bin/xml2-config \
                    --with-xslt-config=/usr/bin/xslt-config" \
    MYSQL_PORT=4306 \
    SERVER_PORT=4000
# ライブラリのインストール(追加したい場合は以下に追記)
RUN apk update \
 && apk upgrade --no-cache \
 && apk add --update --no-cache \
	    alpine-sdk \
　　　　　　　 build-base \
	    bash \
	    imagemagick \
	    jq \
	    less \
	    libgcrypt-dev \
	    libxml2-dev \
            libxslt-dev \
	    mariadb-dev \
	    mysql-client \
	    nodejs \
	    redis \
	    tzdata \
	    wget \
            xvfb \
	    yaml-dev \
            yarn \
            zlib-dev \
 && gem install -q -N bundler \
 && gem install -q -N pkg-config \
 && gem install -q -N rails -v 5.0.7 \
 && gem install -q -N nokogiri -v 1.10.1 -- $NOKOGIRI_OPTION \
 && gem install -q -N mysql2 -v 0.4.10
# 実行するディレクトリの指定
WORKDIR $APP
COPY Gemfile Gemfile.lock $CONTAINER_ROOT
RUN bundle install --jobs=4 --retry=3
# RAILS_SERVE_STATIC_FILES=trueにすることで、rails serverを起動時にpublic/assetsを読み込む
ENV RAILS_SERVE_STATIC_FILES=true \
    PORT=$SERVER_PORT \
    TERM=xterm
EXPOSE $SERVER_PORT
EXPOSE $MYSQL_PORT
```
ファイル内で記述されているFROMやRUNといった環境変数のようなものが、処理を実行するためのコマンドになります。

種類自体は、そこまで数が多くないので、主要なコマンドを整理してみましょう。

### FROM
FROMは、ビルドする際にどのImageをベースにするかという意味を持つコマンドです。

![picture_pc_066c75a1a7705e31a51ab1864cb9bcfc](https://user-images.githubusercontent.com/41051390/80898603-51526880-8d40-11ea-8ebb-ef13ef1350fa.png)

というような命令をDockerにしていると思ってもらえればいいでしょう。

単純に使う言語の設定だと思ってくれれば大丈夫です。

**alpine** は数あるLinuxのディストリビューションのひとつで、余計なライブラリがデフォルトで入っていない分、非常に軽量なイメージです。

そのため、イメージのサイズを軽くしたい場合は指定する場合が多いです。
[リファレンスリンク](http://docs.docker.jp/v1.10/engine/reference/builder.html)

### LABEL
LABELは、Dockerfileのメタデータを記述 する意味を持つコマンドです。

イメージの詳細内容を確認する docker image inspect イメージ名 を実行してみると、冒頭出力されるイメージ情報の中の 「ContainerConfig」という欄に Labels が表示。 


このようにイメージにメモ書きを残すことができる機能が LABEL になります。

例えば次のように記述すると、このDockerfileが誰がメンテナンスするかを指定する意味合いになります。

```
LABEL maintainer="Keita Higaki<higaki.keichan@gmail.com>"
```
ぶっちゃけ、なくてもいいのですが、書いていた方が責任の所在がわかります。

[リファレンスリンク](https://docs.docker.com/engine/reference/builder/#label)

### ENV

ENVは、環境変数のkeyとvalueを設定するコマンドです。書き方は2種類あって、

```
ENV LANG="C.UTF-8"....
```
このようにKeyとValueをイコールで結び付ける方法と、

```
ENV LANG C.UTF-8
```
上記のようにKeyとValueの間にスペースを挿れて書く方法があります。

前者の書き方の方が、一つのENVに対して以下のようにバックスラッシュを使い、一度に複数の環境変数を改行して定義することができるので便利です。

```
ENV APP="/docker_example_for_chat-space" \
    CONTAINER_ROOT="./" \
    NOKOGIRI_OPTION="--use-system-libraries \
                    --with-xml2-config=/usr/bin/xml2-config \
                    --with-xslt-config=/usr/bin/xslt-config" \
    MYSQL_PORT="4306" \
    SERVER_PORT="4000"
```
また、実はこの記述をする理由として2つの意味があって、

• 一つずつ定義するよりもまとめて定義する方が記述が冗長にならない
• ENVを実行するたびにイメージのサイズが増幅するので、少しでも軽くしたいから

です。このような理由から、今回のDockerfileではバックスラッシュによる記述をしています。

なお、定義した環境変数を使うには

```
$CONTAINER_ROOT
```
上記のように、変数名の前に$を付けてあげればOKです。

[リファレンスリンク](https://docs.docker.com/engine/reference/builder/#env)

###RUN

RUNは、 引数に設定したコマンドをビルド時に実行します。引数の書き方がshell形式とexec形式があり、今回紹介しているのはshell形式ですね。

```
# ライブラリのインストール(追加したい場合は以下に追記)
RUN apk update \
 && apk upgrade --no-cache \
 && apk add --update --no-cache \
	    alpine-sdk \
　　　　　　　 build-base \
	    bash \
	    imagemagick \
	    jq \
	    less \
	    libgcrypt-dev \
	    libxml2-dev \
            libxslt-dev \
	    mariadb-dev \
	    mysql-client \
	    nodejs \
	    redis \
	    tzdata \
	    wget \
            xvfb \
	    yaml-dev \
            zlib-dev \
 && gem install -q -N bundler \
 && gem install -q -N pkg-config \
 && gem install -q -N rails -v 5.2.2.1 \
 && gem install -q -N nokogiri -v 1.10.1 -- $NOKOGIRI_OPTION \
 && gem install -q -N mysql2 -v 0.4.10
```
RUNもENVと同じようにバックスラッシュを使ってまとめて定義することで、イメージ化された際の最終的な容量を軽くすることができます。

Railsを動かすためには、さまざまなライブラリが必要になるので、そのためにRUNコマンドを使ってインストールしている箇所になります。

また記述する際にはABCのアルファベット順にすることがリファレンスで推奨されているので、保守性・可読性を高めるために意識しましょう。

また、後半でgem installをしている箇所は、それぞれが比較的インストールに時間がかかる重いgemなので、予めインストールすることで、後のbundle installをキャッシュにより高速化させる効果があります。

[リファレンスリンク](https://docs.docker.com/engine/reference/builder/#run)

###COPY
COPYはプロジェクトソースにあるファイルやディレクトリを指定先にコピーします。

```
COPY Gemfile Gemfile.lock $CONTAINER_ROOT
```
ENVで先程CONTAINER_ROOTという環境変数を定義したので、そこにGemfileとGemfile.lockをコピーするように指定しています。

コンテナのルートディレクトリにローカルからコピーしてきたGemfileとGemfile.lockが配置されるようになるので、これでRailsアプリを動かすための各種コマンドが使えるようになっているはずです。

[リファレンスリンク](http://docs.docker.jp/v1.10/engine/reference/builder.html#copy)

### WORKDIR 

WORKDIRは、文字通りRUNやCMDなどの命令を実行するためのディレクトリを指定するコマンドです。

```
WORKDIR $APP
```
このように環境変数と組み合わせれば、スッキリ書けます

[リファレンスリンク](http://docs.docker.jp/v1.10/engine/reference/builder.html#workdir)

###EXPOSE
 EXPORSEは、コンテナ実行時に指定したポートで接続用意ができていることをDockerに伝えるコマンドです。

```
EXPOSE $SERVER_PORT
EXPOSE $MYSQL_PORT
```
つまり、Dockerに対して、

![picture_pc_a7c6a518a38f3194594f31efdad6758d](https://user-images.githubusercontent.com/41051390/80908584-f3cc1500-8d5b-11ea-9fbf-c14619b929ca.png)

というようなイメージになります。これも環境変数に置き換えておくと管理がラクです。

[リファレンスリンク](https://docs.docker.com/engine/reference/builder/#exposehttps://docs.docker.com/engine/reference/builder/#expose)

###まとめて定義すると、イメージ容量削減になる理由
先ほど

>RUNもENVと同じようにバックスラッシュを使ってまとめて定義することで、イメージ化された際の最終的な容量を軽くすることができます。

こんな感じの記述をしましたが

実はDockerfileに記述したそれぞれのコマンドは、記述されるたびにコンテナ内に処理を実行するための場所を確保していきます。

![picture_pc_568e418501e973b0a65430c06ca8a6a2](https://user-images.githubusercontent.com/41051390/80908685-df3c4c80-8d5c-11ea-92bb-2e1e96954363.png)

上記の画像のように、それぞれのコマンドが実行されるたびに実行するためのスペースがテトリスのブロックのように積み上げられていくようなイメージを持つとわかりやすいかもしれません。

特に、RUNやENVは他のコマンドよりもたくさんのスペースを必要とするので、書けば書くほどコンテナも重くなります。

コンテナが重くなると、その分処理速度やアプリケーション立ち上げ時にかなり時間がかかってしまうんですね。

だからこそ、バックスラッシュ(/)やアンパサンド(&)などを使い、一つのコマンドに対して複数の処理を記述していくことが公式でも推奨されています。

## docker-compose.ymlの書き方について
続いてdocker-compose.yml について解説していきます。

＊別記事でも解説してます
[Docker入門編　docker-compose.ymlの書き方](https://qiita.com/keitah/items/ead34aaa18deab1c403e)


まずは、プロジェクトのルートディレクトリでdocker-compose.ymlを作成

```
$ touch docker-compose.yml
```
復習しておくとDocker Composeは、

• それぞれのコンテナを同時に動かすためのツール
• それを利用するためにYAML形式で書いたファイルがdocker-compose.yml

でした

```
# 開発環境用のdocker-compose
version: '3.2'

services:
 database:
   restart: always
   image: mysql:5.7
   ports:
     - 3000:3000
   volumes:
     - mysql-datavolume:/var/lib/mysql
   environment:
     MYSQL_ROOT_PASSWORD: root

 app:
   build:
     context: .
     dockerfile: ./docker/development/Dockerfile
   command: >
     bash -c "
       rm -f tmp/pids/server.pid &&
       bundle install --quiet &&
       bundle exec rails db:migrate:reset &&
       bundle exec rails s -p 3000 -b '0.0.0.0'
     "
   ports:
     - "４000:4000"
   volumes:
     - .:/docker_example_for_chat-space
     - "bundle:/usr/local/bundle"
   depends_on:
     - database


volumes:
 bundle:
   driver: local
 mysql-datavolume:
   driver: local
```

ポイントとしては、それぞれのコンテナについての記述をインデントを用いてひとまとめにしている点ですね。色分けすると、次のようなイメージです。

![picture_pc_8f82f1cd01fe1c35a2dba3cd97d4f2f9](https://user-images.githubusercontent.com/41051390/80909070-37288280-8d60-11ea-9d54-c9f3d568973d.png)

docker-compose.ymlはYAML形式で書かれているため、インデントに対して厳格です。そのため、インデントが一つずれるだけで、ビルドしたい際にエラーしてしまいます。

記述する際には、

• TAB文字の場合はスペース二つ分になっているか
• SPACEで入力する場合は、余計なスペースが入っていないか

上記の設定が使用しているエディタに反映されているか確認が必要です。

それでは主要な箇所を見ていきましょう。

###version: '3.2'

```
version: '3.2'
```
ここはComposefileのバージョンを指定しています。

このメジャーバージョンによって、書き方が微妙に異なるので注意が必要です。

###services

```
services:
  # ズラッと各要素が並ぶ
 database:
   # database要素の内容を定義
 app:
　　# app要素の内容を定義
```
Docker-Composeでは、アプリケーションを動かすための各要素をServiceと読んでいます。

そのため、ComposeFileにも、serviceとして、それぞれのServicesの内容をネストさせて記述していきます。(書き方自体はYAMLの書き方でOK)

完成形をみてみると、databaseとappがServiceとして定義されていますね。

各要素には任意の名前をつけることができ、わかりやすければなんでもOKですｌ

で、実はconfig/database.ymlでMYSQL_HOSTがdatabaseと記述していたのはこれが理由です。

「MYSQLはdatabaseとしてServiceを定義したから、接続するときはそこを参照してね」

といったことをDockerに伝えているわけです。

ちなみに、ここで定義した名前は、dockerのログに表示されるので、立ち上げたら確認してみてくださいね。

###volumes:

volumesはローカルにあるファイルを同期して読み込むための設定を行っています。

```
volumes:
 bundle:
   driver: local
 mysql-datavolume:
   driver: local
```
例えば、新しくgemをインストールしたときにいちいちdocker buildしていては、いくら軽いとはいえ時間がかかります。

しかし、このvolumes:を設定することで、指定したパスのディレクトリをコンテナ内に設置され、Dockerコンテナ内でローカルにあるファイルを参照することができるようになるんですね。

これを設置するという意味からmount(マウント)するといいます)

で、このマウント機能を使うと、gemを新しく追加した際にはビルドしなくてもコンテナ内でbundle installするだけでよくなるんですね。

その設定が、以下の箇所になります、

```
bundle:
   driver: local
```

###driver
driverは、volumeに使用するドライバ(動かすための接続先)の指定するためのkeyになり、そのvalueとしてlocalを指定することで、マウント機能を実現しています。 
[リファレンスリンク](https://docs.docker.com/compose/compose-file/#driver)

###restart 
restartは、実行時に再起動するかどうかを指定しています。

```
restart: always
```
今回でいうと、dockerをビルド時や立ち上げる際にMySQLを再起動させるようにしているという意味合いになっています。

[リファレンスリンク](https://docs.docker.com/compose/compose-file/#restart)

###environment
evrironmentは、環境変数を設定します。DBのパスワードなどを記述したりします。

```
environment:
     MYSQL_ROOT_PASSWORD: root
```
なお、MYSQL_ROOT_PASSWORDという環境変数は、MySQLのimageを使用する際に予め決められているものになります。この変数をTypoするとMySQL起動時にエラーするので、注意しましょう。

[リファレンス ](https://docs.docker.com/compose/compose-file/#environment)
MySQLの環境変数について
https://hub.docker.com/_/mysql

###ports
portsは、DBなどのDockerImageを立ち上げる際に使用するポート番号 です。

```
database:
    restart: always
    image: mysql:5.7
    ports:
      - 4306:3306
    (中略)
```
ここでは、「databaseを使う時に4306というポート番号にアクセスするから、3306に転送してね」という意味を表しています。これがポートフォワードと呼ばれる仕組みですね。

また、今回DockerfileでRailsのアプリケーションサーバーPumaが使用するポート番号に4000を指定しています。

```
#docker/development/Dockerfile
(中略)
ENV (中略)
    SERVER_PORT=4000
(中略)
EXPOSE $SERVER_PORT
(中略)
```
そのため、docker-compose.ymlでもappコンテナで使用するポート番号を次のように設定する必要があるんですね。

```
# docker-compose.yml
app:
   build:
     context: .
     dockerfile: ./docker/development/Dockerfile
   command: >
     bash -c "
       rm -f tmp/pids/server.pid &&
       bundle install --quiet &&
       bundle exec rails db:migrate:reset &&
       bundle exec rails s -p 4000 -b '0.0.0.0'
     "
   ports:
     - "４000:4000"
```

もし仮にDockerfileとdocker-compose.ymlのポート番号で整合性が合わないと、puma自体は立ちがりますがブラウザで動作確認した際、以下のようにERR_EMPTY_RESPONSEとなるので注意しましょう！


![picture_pc_f1f44ceccc49232897848e09ebbda87a](https://user-images.githubusercontent.com/41051390/80909467-a3f14c00-8d63-11ea-9615-5c279dbf050d.png)

[リファレンスリンク](https://docs.docker.com/compose/compose-file/#ports
)
###volumes
serviceの各要素にも、実はvolumeを定義することができます。

```
volumes:
     - mysql-datavolume:/var/lib/mysql
# 中略
 volumes:
     - .:/hello_world_rails
     - "bundle:/usr/local/bundle"
```
復習になりますが、volumesはマウントする設定ファイルのパスを指定する記述になります。

mysqlのconfigファイルなどを指定したりします。
[リファレンスリンク](https://docs.docker.com/compose/compose-file/#short-syntax-3)

###build
buildはdocker-compose.ymlで対象のコンテナを起動させる際に、対応するDockerfileの置き場所を相対パスで指定します。

もしDockerfileをプロジェクトのルートディレクトリに作成している場合は、buildの書き方は次のようになります。

```
build: .
```
例えば　Dockerfileを　Local・Staging・Productionなどのように、アプリの実行環境ごとに分割した場合

```
build:
     context: .
     dockerfile: ./docker/development/Dockerfile
```
と書くことができます。
contextは現在のディレクトリ(docker-compose.ymlの置き場所)を表していて、dockerfileというkeyに対して参照先("./docker/development/Dockerfile")をvalueで渡せば、任意の位置にDockerfileを置くことができます。

[リファレンスリンク](https://docs.docker.com/compose/compose-file/#build)

###depends_on
depends_onは、Service同士の依存関係を指定します。
ここで指定されたSeriviceは、その指定元のSeriviceが起動する前に実行されるようになります。

```
app:
  # 中略
  depends_on:
       - database
```
今回でいうと、app内でdatabaseがdepends_onとして指定されているので、appよりも先にdetabaseが起動するという意味になります。

[リファレンスリンク](https://docs.docker.com/compose/compose-file/#depends_on)

### docker-compose.ymlについては以上です

#最後に某スクールで開発し、デプロイしたアプリケーションをDockerizeしたコードを掲載しておきます。

こちらはDockerコンテナを作成しただけで、デプロイはCapistranoを直にアプリケーションに導入しEC2に接続しています。（コンテナデプロイではない）

```Go:Dockerfile
 FROM ruby:2.5.1 
 
# 必要なパッケージのインストール（基本的に必要になってくるものだと思うので削らないこと） 
RUN apt-get update -qq && \ 
    apt-get install -y build-essential \  
                       libpq-dev \         
                       nodejs            
# 作業ディレクトリの作成、設定 
RUN mkdir /app_name 
##作業ディレクトリ名をAPP_ROOTに割り当てて、以下$APP_ROOTで参照 
ENV APP_ROOT /app_name 
WORKDIR $APP_ROOT 

# ホスト側（ローカル）のGemfileを追加する
ADD ./Gemfile $APP_ROOT/Gemfile 
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock 
 
# Gemfileのbundle install 
RUN bundle install 
ADD . $APP_ROOT 
```


```yml:docker-compose.yml
version: "3" 

services: 
   db: 
     image: mysql:5.7 
     environment: 
       MYSQL_ROOT_PASSWORD: password 
       MYSQL_DATABASE: root 
     ports: 
       - "4306:3306" 
  
   web: 
     build: . 
     command: rails s -p 3000 -b '0.0.0.0' 
     volumes: 
       - .:/app_name 
     ports: 
       - "3000:3000" 
     links: 
       - db 
```
コンテナの外枠を作るだけなので、非常にシンプルな記述に仕上げました。

docker-compose.ymlの書き方についてはこちら
[Docker入門編　docker-compose.ymlの書き方](https://qiita.com/keitah/items/ead34aaa18deab1c403e)

檜垣慶太

[Twitter](https://twitter.com/keitah0322)

#長々とありがとうございました！