話題の”全集中”で『Dockerの使い方』を、僕の中に眠るバーチャル禰豆子のためにまとめた。

#はじめに
Dockerとは、「開発環境を簡単に作れる便利なツール」です。

本格的に野球しようと思っても、場所作るの大変ですよね…。
ベースを用意して、距離測って置いて、バットもボールも観客席も用意して…。
しかし！Dockerを使えば一瞬でPayPayドームが出来上がります！（出来上がりません。）

野球場は無理ですが、システム開発環境であれば可能です。

- LAMPサーバー
- Wordpress
- Rails＋DB　etc...

瞬時にシステム開発環境を作成し、その環境を複数人に配ることが可能という便利なアプリです。


##この記事について
この記事で、コンテナ等の概念は特に触れていません。
以下のような目的で記事を作成しています。

- 実際にDockerを触れてみて、システム環境が整う感覚を味わえる。
- 後日思い出すときにすぐに引き出せる。

ネズコーーー！！！！！！
Dockerがんばって使えるようになるぞーーー！！！

##実行環境
- Mac Catalina
- [Docker for Mac](https://www.docker.com/get-started) 

<font color="blue">※インストールまだの方は、上記公式サイトよりお願いします。</font>

##参考にさせていただいたサイト
特に一番上のサイトを勉強及び参考にさせていただきました。概念もしっかり記述されているので、この記事の読者の方、是非閲覧されてください。

- [【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その1:コンテナってなに？ 〜](https://tech-lab.sios.jp/archives/18811)
- [DockerfileのRUN命令とCMD命令の違い【Docker】](https://rara-world.com/dockerfile-run-cmd/#:~:text=RUN%E5%91%BD%E4%BB%A4%E3%83%BBCMD%E5%91%BD%E4%BB%A4%E3%81%AE,%E3%81%A8%E3%81%8D%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)
- [Docker ドキュメント日本語化プロジェクト](https://docs.docker.jp/index.html)
- [Docker入門（第六回）〜Docker Compose〜](https://knowledge.sakura.ad.jp/16862/)
- [docker-compose `up` とか `build` とか `start` とかの違いを理解できていなかったのでまとめてみた](https://qiita.com/tegnike/items/bcdcee0320e11a928d46)
- [docker-compose.ymlの書き方について解説してみた](https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04)

#では、やってみましょう！
##Dockerfileからコンテナを作成
CentOS7にPHPとApachをインストールしたコンテナを作成します。

###流れ
① Dockerfileを任意の場所に作成（ファイル名：dockerfile）
② 作成したDockefileからイメージを作成。
③ イメージを元にコンテナを作成する。

###手順

####① まずはdockerfileをPCに作成する。

```docker:dockerfile
#DockerHubからcentos7のイメージをもとにする。
FROM centos:centos7

#centos7のイメージの中でApachとphpをインストール
RUN yum -y install httpd php

#Åpachを起動するためのコマンドを実行
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
```

####② 作成したDockerfileを元に、イメージを作成。
オプション等の説明は[Docker ドキュメント日本語化プロジェクト](http://docs.docker.jp/v17.06/engine/reference/commandline/build.html)を参照。

```docker
#内容
docker build -t イメージ名:タグ名 Dockerfileのディレクトリ

#例｜イメージ名はlamptest。タグは1.0。カレントディレクリのdockerfileを使用
docker build -t lamptest:1.0 .
```

上記を実行するとイメージが作成される。
![Screen Shot 2020-11-17 at 11.47.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/7b30b147-5bfa-b953-83d6-b7e61eff2705.png)

####③ 作成したイメージを元にコンテナ起動

```docker
#内容
docker run -d -p ポート番号:ポート番号 --name コンテナ名 イメージ名:タグ名

#例｜ポート80版を8080版に割り当てる。 
#   コンテナ名はtestserver。
#   イメージとタグは、lamptest:1.0を使用する。
docker run -d -p 8080:80 --name testserver lamptest:1.0
```
無事にコンテナの完成です。
![Screen Shot 2020-11-17 at 11.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/3ecca109-a47a-eacc-5db4-a5410b7a8015.png)


[http://localhost:8080](http://localhost:8080)にアクセスすると、以下画面が表示されます。

![Screen Shot 2020-11-17 at 15.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/9df9660f-f602-15d3-5872-bac22bc1e6c5.png)


###※補足※　コンテナの操作
```docker

#起動
docker start コンテナ名

#停止
docker stop コンテナ名

#コンテナの中に入る
docker exec -i -t コンテナ名 bash
```
また操作はGUIでも可能です。
![Screen Shot 2020-11-17 at 15.19.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/900b1fd4-d5b4-53e5-e2bc-2a5991e19783.png)





###dockerfileコマンドの詳細説明
使用頻度の多いものを簡潔に記載しています。
より詳しい説明は[Docker ドキュメント日本語化プロジェクト](https://docs.docker.jp/engine/reference/builder.html)を参照してください。

####From
Dockerイメージをベースに作成する。

```docker

#内容
FROM イメージ名:タグ名

#例｜centosのイメージをベースにする
FROM centos:centos7

```


####Run
FROMで指定したイメージ対してコマンドを実行。

```docker
#内容
FROM 実行するコマンド

#例｜yumでhttpdのインストール
RUN yum -y install httpd
```

####COPY
Dockerイメージ内（コンテナ内）にコピーしたいファイルを指定。

```docker
#内容
FROM イメージ内にコピーしたいファイルのパス　コピー先イメージのパス

#例｜Dockerfileと同じディレクトリにあるhogeファイルを、/tmpディレクトリにコピー。
COPY hoge.txt /tmp
```

####ADD
URLが指定できる、tarアーカイブ(gzip、bzip2、xz)で圧縮されるファイルを指定すると自動展開される。
それ以外は、COPYコマンドと同じ。

```docker
#内容
ADD イメージ内にコピーしたいファイルパスやURL コピー先のイメージパス。

#例｜tar.gzファイルを展開しつつ、イメージ格納
ADD hoge.tar.gz /tmp

#例｜URL先のファイルを、指定したディレクトリに保存する。
ADD https://zukan.pokemon.co.jp/detail/025 /tmp
```

####RUN
イメージ作成時に、コマンドを実行する。

```docker
#内容
RUN コマンド オプション

#例｜lsコマンドを-aのオプションを添えて。
RUN ls -a
```

####CMD
コンテナ起動時に、コマンドを実行する。

```docker
#内容
CMD [ コマンド , オプション ]

#例｜lsコマンドを-aのオプションを添えて。
CMD [ ls , -a ]
```

####ENV
環境変数数に値を入れる。（イコールは省略可能。）

```docker
#内容
ENV 環境変数名=環境変数の値
ENV 環境変数名 環境変数の値

#例｜環境変数MIZUNOKOKYUにichinokataを挿入
ENV MIZUNOKOKYU=ichinokata

```

####USER
ユーザー実行名の切り替え

```docker
#内容
USER ユーザー名

#例｜ユーザー名をakiunleashに切り替え
USER akiunleash

```

##docker-composeで複数のコンテナを作成・連携
アプリとデータベースの複数のコンテナを、一つのシステムとして構築が可能です。
RailsとPostgreSQLのコンテナを別々に作成し、一つのシステムとして連携してみましょう。

###流れ
① docker-compose.yml等の必要なファイルを作成
② docker-compose runを使用してイメージ及びコンテナの作成
③ Gemfileが更新されるので、docker-compose bulde で再度構築
④ Rails側からPostgreSQLに接続できるようusernameやpasswordを設定変更
⑤ RailsからPostgreSQLのデータベースの作成
⑥ 完成！

###手順

####以下４つのファイルを準備します。
- docker-compose.yml
- dockerfile
- Gemfile
- Gemfile.lock


```yml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

```dockerfile:dockerfile
# DockerHubからcentos7のイメージをもとにする。
FROM ruby:2.3.3

# パッケージ管理ソフトのアップデートからの
# build-essential libpq-dev nodejs をインストール
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs

# コンテナ内にmyappディレクトリ作成
RUN mkdir /myapp

# ワークディレクトリに設定
WORKDIR /myapp

# dockerfileと同ディレクトリにあるファイルを、コンテナ内に作成
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock

# Gemfileにかかれてるrailsをインストール 
RUN bundle install

# Railsのファイル及びディレクトリをコンテナに作成
ADD . /myapp
```

```shell:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.0.0.1'
```

```shell:Gemfile.lock
#空ファイル
```

####上記ファイルが保存されたディレクトリでコマンド実行

```docker
docker-compose run web rails new . --force --database=postgresql
```


####Gemfileが更新されるので、再度Gemをインストールするためコマンド実行
```docker
docker-compose build
```

####データーベースと接続するための情報を編集する。
```yml:config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
```

###アプリを起動してみましょう！
```docker
docker-compose up -d
```

####今の状態はデータベースが無いので作成します。
```shell
docker-compose run web rake db:create
```

####確認！
[http://localhost:3000/](http://localhost:3000/)にアクセスし以下のページが表示されれば成功です。
![Screen Shot 2020-11-18 at 11.12.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/9908a98e-5512-79b9-8260-bec12653d6bd.png)


コンテナもしっかりと起動されていることが確認できます。
![Screen Shot 2020-11-18 at 11.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87695/f3886b9d-929b-b9b6-1acb-4ac537daa7c8.png)

不要なコンテナが含まれている場合は一度ダウンして、再起動すると消えます。

```docker
# 一度ダウン
docker-compose down

# 再度アップ
docker-compose up -d
```

###docker-compose.ymlの解説
```yml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

| 項目 | 説明 |
|:-:|:-:|
| version |  docker-composeのバージョン |
| services | コンテナ名（WEBとDBを作成）  |
| image | Docker Hubからイメージを使用  |
| environment  | 環境変数を設定 |
| build  | 指定したdockerfileを使用する。  |
| command | コンテナ作成後に実行するコマンド  |
| volumes | ファイルをマウント |
| ports | ポートの指定  |
| depends_on  | 起動順序 |

#最後に
Dockerとはどういうものかの感覚を掴むための助けになれば幸いです。
内容に誤りがありましたら、ご指摘いただけると助かります。

#変更履歴
| 日付 | 内容 |
|:-:|:-:|
| 2020/11/18 | 初版 |