基本的なDockerのあれこれ

# はじめに
近年、Dockerで環境構築をする機会が増えていますが、駆け出しエンジニアからしたら何が何だか分からず発狂したくなりますよね。
そういった過去を抱えている自分がDockerを最低限使えるようになれたら良いなと願いを込めて記事を書きます。

# Dockerとは
Dockerとは、`内部でコンテナ技術を利用しており、様々な環境でアプリケーション実行環境を構築・運用する`ためのオープンソースのプラットフォームです。
Dockerでは、必要なライブラリ群や。アプリケーションの実行に必要な全てのファイル・ディレクトリ群、インフラ環境などをコンテナとして１つにまとめます。
Dockerを利用すると、`別環境でエラーが発生するなどのリスクを減らす`ことができます。

## コンテナとは
コンテナとは、ホストOS上に論理的な区画を作成し、アプリケーションを動作させるのに必要なライブラリなどを１つにまとめることが出来ます。コンテナは`オーバーヘッドが少ないため。軽量で高速に動作`します。
また、アプリケーションの実行に必要なものをまとめることができるので、`複数のコンテナを組み合わせて１つのアプリケーションを構成するマイクロサービス型のアプリケーションと親和性が高い`です。

## 大まかな機能
Dockerには大きく分けて、次の３つの機能があります。

Dockerイメージを作る機能（Build）
Dockerイメージを共有する機能（Ship）
Dockerコンテナを動かす機能（Run）
以下でこの３つの基本機能を説明していきます。

### Build
Dockerfileというファイルに書かれた内容をもとにDockerイメージを作成します。
Dockerイメージは、Dockerのコマンドを使って手動で作ることも、Dockerfileという設定ファイルを作ってそれをもとに自動でイメージを作ることもできますが、`Dockerfileを使って管理することが望ましい`です。
また、Dockerイメージは積み重ねて利用できます。Dockerでは構成に変更があった部分を差分（イメージレイヤー）として管理します。

### Ship
DockerのイメージはDockerレジストリ(Docker Hubなど)で共有できます。
公式のDockerレジストリであるDocker HubではUbuntuやMySQLなどよく使うもののベースとなるDockerイメージが配布されています。これらのベースイメージをカスタマイズし、イメージを積み重ねて独自のDockerイメージを作っていきます。

### Run
Dockerは、コンテナ単位でサーバ機能を動かします。このコンテナのもとになるのが、Dockerイメージになります。また、Dockerイメージから複数のコンテナを起動することもできます。コンテナの起動・停止・破棄は、Dockerのコマンドを使います。

# 基本的な使い方
以下、Dockerを利用する際の基本的な操作を記載しています。

## Dockerイメージのダウンロード
Dockerイメージを取得するには、`docker image pull`コマンドを使用します。

```bash
# docker image pull [オプション] イメージ名[:タグ名]

$ docker image pull centos:7
#=> CentOSのバージョン７をダウンロード
```

## Dockerイメージの一覧取得
取得したDockerイメージの一覧表示は、`docker image ls`コマンドを使用します。

```bash
# docker image ls [オプション] [レポジトリ名]

$ docker image ls
```

```bash
REPOSITORY       TAG           IMAGE ID       CREATED      SIZE
イメージの名前      イメージタグ名    イメージID       作成日        イメージのサイズ
```

### オプション一覧

| オプション | 内容 |
|:-:|:-:|
| -all, -a  | すべてのイメージを表示  |
| --digests  |ダイジェストを表示するかどうか   |
| --no-trunc  | 結果をすべて表示  |
| --quiet, -q  | DockerイメージIDのみ表示  |

## Dockerイメージの削除
作成したDockerイメージは`docker image rm`コマンドで削除できます。

```bash
# docker image rm [オプション] イメージ名(or ID) [イメージ名(or ID)]

$ docker image rm samle_image
```

### オプション一覧

| オプション | 内容 |
|:-:|:-:|
| --force, -f  | 強制的にイメージを削除  |
| --no-prun  | 中間イメージを削除しない  |

## コンテナ生成・起動
コンテナの生成・起動には、`docker container run`コマンドを使用します。

```bash
# docker container run [オプション] イメージ名[:タグ名] [引数]

$ docker container run -p 8080:80 nginx
#=> ホストの8080ポートにアクセスすると、コンテナ上で動作しているNginx（80番ポート）のサービスにアクセス
```

### オプション一覧

| オプション | 内容 |
|:-:|:-:|
| --attach, -a  | 標準入力/出力/エラー出力にアタッチ |
| --detach, -d  | コンテナを生成し、バックグラウンドで実行  |
| --name [コンテナ名]  | コンテナ名を設定  |


##  コンテナ停止
起動しているコンテナを停止する時は、docker container stopコマンドを使用します。

```bash
# docker container stop [オプション] コンテナ名(or ID) [コンテナ名(or ID)]

$ docker container stop sample_container
```

## コンテナ削除
停止しているコンテナを削除するときは、`docker container rm`コマンドを使用します。

```bash
$ docker container rm [オプション] コンテナ名(or ID) [コンテナ名(or ID)]

$ docker container rm sample_container
```

### オプション一覧

| オプション | 内容 |
|:-:|:-:|
| --force, -f  | 起動中のコンテナを強制的に削除  |
| --volumes, -v  | 割り当てたボリュームを削除す  |

# Dockerfileを利用する
Dockerfileとは、Docker上で動作させるコンテナの構成情報を記述するファイルのことです。
具体的には、以下のようなものを記載しておきます。

- ベースになるDockerイメージ
- Dockerコンテナ内で行った操作（コマンド）
- 環境変数などの設定
- Dockerコンテナ内で動作させておくデーモン実行

## 記載例

```Dockerfile
# CentOSのベースイメージを設定
FROM centos:7

# build時に指定したコマンドを実行させる
RUN echo "now building..."
RUN yum -y install httpd
RUN sed -i '/#ServerName/a ServerName www.example.com:80' /etc/httpd/conf/httpd.conf

# index.htmlをコンテナにコピー
ADD ./index.html /var/www/html/

# 80番ポートをエクスポート
EXPOSE 80

# イメージ作成後、指定したコマンドを実行する
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
```

### 主な命令文

| 命令 | 内容 |
|:-:|:-:|
| FROM  | ベースイメージの設定  |
| RUN  | build時にコンテナ内で実行  |
| CMD  | 完成したイメージからコンテナを作成するときに実行  |
| LABEL  | ラベルを設定  |
| EXPOSE  | ポートのエクスポート  |
| ENV  | 環境変数  |
| ADD  | ファイル/ディレクトリをコンテナにコピー  |
| COPY  | ファイルのコピー  |
| ENTRYPOINT  | コンテナの実行コマンド  |
| VOLUME  | ボリュームのマウント  |
| USER  | ユーザーの指定  |
| WORKDIR  | 作業ディレクトリの変更  |
| ARG  | Dockerfile内の変数  |
| SHELL  | デフォルトシェルの設定  |

# docker-composeを利用する
一般的にDockerを利用する際は、複数のDockerコンテナが協調して動作します。Docker Composeを利用することで、複数のコンテナをまとめて管理する事が出来ます。
`docker-compose.yml`というファイルにコンテナの構成情報を定義し、同一のホスト上の複数のコンテナを一括管理できます。

## 記載例

```docker-compose.yml
version: '3' # バージョンを指定
services: # 管理したいコンテナのサービス
  db: # DBサーバー用のコンテナの設定
    image: mysql:5.7 # コンテナで使用するイメージ名を記載
    environment: # 環境変数を設定
      MYSQL_ROOT_PASSWORD: password # 任意のパスワードを設定
      MYSQL_DATABASE: sample_db # 任意のデータベース名を設定
    ports:
      - "3306:3306" # ホストの3306ポートとコンテナの3306ポートを接続

  web: # APPサーバー用のコンテナの設定
    build: . # docker-compose.ymlと同じ階層のDockerfileを使ってイメージをbuild
    command: bundle exec rails s -p 3000 -b '0.0.0.0' # コンテナ立ち上げ時に起動するコマンド
    volumes: # ボリュームを設定
      - .:/sample_app # 作業ディレクトリをコンテナ内の/sample_appにマウント
    ports: # ポートを設定
      - "3000:3000" # ホストの3000ポートとコンテナの3000ポートを接続
    links:
      - db # dbコンテナと接続
```

# 終わりに
こんな簡単なことかよっっ！！と思うかもしれないけど、意外と基礎を固めることは大事なのでド忘れした時などに見返してね！