（手っ取り早くDockerが使えるようになるための）Docker入門

# はじめに
当記事は、手っ取り早くDockerが使えるようになるための記事となります。
具体的には、

- Dockerについてざっくりと理解して
- 簡単な環境を構築し
- 作った環境をDocker Hubで共有

ができるようになることを目標としています。

そのため、より深くしっかりと理解したいかたは、以下の記事を参照されるとよいかと思います。

- [【図解】Dockerの全体像を理解する -前編-](https://qiita.com/kotaro-dr/items/b1024c7d200a75b992fc)
- [いまさらDockerに入門したので分かりやすくまとめます](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)
- [Dockerを支える技術](https://www.slideshare.net/enakai/docker-34668707)

# Dockerとは
## 三行で
- Linuxカーネルの機能であるコンテナ型仮想化を使用したアプリケーション実行環境を構築するツール
- OS内に「コンテナ」とよばれる隔離された仮想領域を確保
- アプリケーションとOSなどの実行環境をまとめてコンテナに閉じ込めて管理

※コンテナにはLinuxコンテナ、Windowsコンテナとありますが、当記事ではLinuxコンテナを対象としています

## Dockerイメージ、コンテナ、レジストリについて
Dockerイメージ、コンテナ、レジストリについてまとめます。

|名称|説明|
|:--|:--|
| Dockerイメージ|アプリケーションのインストールや各種設定など、アプリケーションが動作するのに必要な情報がすべてまとめられていたもの。|
| Dockerコンテナ|Dockerイメージとしてまとめられたアプリケーションが実際に実行状態（プロセスとして動いている状態）となっているもの。|
| Dockerレジストリ|Dockerイメージをバージョン管理するシステム。<br>クラウドサービスとしての [Docker Hub](https://hub.docker.com/) や個人レジストリなどがある。|

Dockerイメージ、コンテナ、レジストリの関係は以下のようになります。

![image_container_registry (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22736/448da661-b661-96a7-761c-b82cf1a37961.png)

# Dockerを使うメリット
いろいろメリットはあるかと思いますが、個人的には以下の３つを挙げます。

## 手軽にミドルウェアが試せる
たとえば最新のElasticsearchを試してみたい場合、（後述しますが）たった2つのDockerコマンドで構築することができます。

## 環境構築をコードで管理できる
Dockerでは `Dockerfile` や `docker-compose.yml` といったテキストファイルに環境構築手順を記載していき、
それらのファイルを参照してDockerコマンドを実行することで、手順に沿った環境を構築することができます。

つまり環境構築手順をコード化すること（**Infrastructure as Code** ）で環境構築が多少ラクになります。

## 環境差異が起こりづらい
一度作った環境は `Dockerイメージ` としてまとめられ `Dockerレジストリ` へ登録します。
Dockerが導入されているサーバであれば、`Dockerレジストリ` から `Dockerイメージ` を取得し、`Dockerコンテナ`化することで、容易に同じ環境が構築できます。

また、構築後の環境に変更を加えたい場合は（例えばミドルウェアのバージョンアップなど）、
環境に直接手を加えるのではなく、改めて `Dockerイメージ` を作り直します。
後はその `Dockerイメージ` を `Dockerコンテナ`化して動作の確認を行い、問題が無ければ各環境に配布する流れとなります。

直接環境に手を加えない（**Immutable Infrastructure**）で、新しい `Dockerイメージ` を作り直す手順にすることで、環境への修正漏れを防ぐ効果があります。

# 実演
それでは実際に環境構築をしていきます。

## ０）事前準備
### Dockerインストール
公式サイトを参考に、[Docker](https://docs.docker.com/install/#supported-platforms) および [Docker Compose](https://docs.docker.com/compose/install/) のインストールを行います。
なお、当記事では以下の環境となります。

- ホストOS：Ubuntu18.04.1
- Docker：18.09.1
- Docker Compose：1.23.2

### Docker Hubアカウント作成
`Dokcerレジストリ` として Docker Hubを利用します。
[このページ](https://hub.docker.com/signup)にてアカウントを作成してください。


## １）もっとも簡単なやりかた
まずはもっとも簡単なやりかたでElasticsearchを構築します。
`docker image pull` と `docker container run` のたった2コマンドで導入できます。

```bash
# Elastic社公式Dockerイメージを取得
$ docker image pull docker.elastic.co/elasticsearch/elasticsearch:7.0.1

# イメージを確認
$ docker image ls

# コンテナ化
$ docker container run -d --name sample-es01 -p 19200:9200 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.0.1

# コンテナ確認
$ docker container ls

# Elasticsearch確認
$ curl localhost:19200
```
- *docker image pull* イメージ名
- *docker container run* [オプション] 元となるイメージ名
  - オプション
     - -d　コンテナをバックグラウンドで起動させる
     - --name　コンテナ名を指定
     - -p　ポートフォワーディング
     - -e　環境変数を設定

## ２）Dockerfileを使用したやりかた
取得した `Dockerイメージ` に対してインストールや初期設定など、何がしかの作業を追加したい場合は、
`Dockerfile` にその作業内容を記載することで作業自体を自動化できます。

![demo2 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22736/0ef10a14-ab74-cbc0-568d-68d9687ecba2.png)

今回はCentOS7にElasticsearchを導入してみます。
まずは以下の `Dockerfile` を作成します。

```dockerfile:Dockerfile
#ベースはCentOS7
FROM centos:centos7

#必要なソフトウェアをインストール
RUN yum install -y java wget

#ユーザ「elasticsearch」を追加
RUN groupadd -g 1000 elasticsearch && \
    adduser -u 1000 -g 1000 -d /usr/share/elasticsearch elasticsearch

USER elasticsearch
WORKDIR /usr/share/elasticsearch

#Elasticsearch7のダウンロード
RUN wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.0.1-linux-x86_64.tar.gz \
  && tar zxvf elasticsearch-7.0.1-linux-x86_64.tar.gz

#Elasticsearchの初期設定
RUN echo -e $"\n\
network.host: 0.0.0.0\n\
discovery.type: single-node\n\
" >> /usr/share/elasticsearch/elasticsearch-7.0.1/config/elasticsearch.yml

#コンテナ起動時にElasticsearchをフォアグラウンドで起動
CMD ["/usr/share/elasticsearch/elasticsearch-7.0.1/bin/elasticsearch"]
EXPOSE 9200
```

`Dockerfile` を作成後、`docker iamge build` コマンドで `Dockerイメージ` をビルドします。

```bash
# docker iamge build -t イメージ名 Dockerfileの格納ディレクトリ
$ docker image build -t elasticsearch-7.0.1 .
```

`Dockerイメージ` のビルド後は、先ほどと同じように、`docker container run` コマンドで `Dockerコンテナ`化します。

```bash
$ docker container run -d --name sample-es02 -p 29200:9200 sample-es02
```

これでElasticsearchの導入ができました。

もし使用するElasticsearchのバージョンを上げたかったり、Elasticsearchの設定を変更したい場合は、`Dockerfile` を修正し、コンテナを作り直せばいいのです。

## ３）Dockerイメージの共有
作成した `Dockerイメージ` は `Dockerレジストリ` に登録することで、別環境との共有が可能となります。

![demo3 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22736/e915cc57-a6bc-fe63-1931-ddd7718126a3.png)

### Dockerイメージのタグ付け
`Docker Hub` 上の自分のリポジトリに登録するには、まず登録する `Dockerイメージ` に対し、
> Docker Hubアカウント/イメージ名[:タグ名]


の形式でタグ付けを行う必要があります。

```bash
# 実演２）で作成したイメージ「sample-es02」に対してタグ付け
$ docker image tag sample-es02 shinyashikis/my-elasticsearch7:0.0.1
# イメージ確認
$ docker image ls
```

### Dockerイメージの登録
タグ付け後は `Docker Hub` にログインし、`docker image push` コマンドにより `Dockerイメージ` を登録します。

```bash
# Docker Hubにログイン
$ docker login -u shinyashikis -p xxxxxxxxxxxxxx
# タグ付けしたイメージをDokcer Hubに登録
$ docker image push shinyashikis/my-elasticsearch7:0.0.1
```

これで `docker image pull` コマンドや、`Dockerfile` のFROM句で指定することで登録したイメージを取得することができます。

```bash
$ docker image pull shinyashikis/my-elasticsearch7:0.0.1
```
```dockerfile:Dockerfile
FROM shinyashikis/my-elasticsearch7:0.0.1
```

## ４）Docker Composeを使用したやりかた
これまでは一つのコンテナの作成を例にあげてきましたが、複数コンテナの場合はどうでしょう。
複数コンテナ構成の場合、コンテナ間の通信やコンテナの起動順などを考慮する必要が出てきます。
そのようなケースにおいては、マルチコンテナ管理ツールである `Docker Compose` を使用したほうが管理しやすくなります。

![demo4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22736/a4777960-3c61-9aa1-581f-83f665ce3e6e.png)

今回は、ブラウザからspring-bootコンテナへアクセスすると、Elasticsearchの情報を表示するだけの簡単なアプリを構築してみます。

![demo4-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22736/4c791912-c96a-4abd-21ad-0386f5ffffd5.png)

それでは、まず以下のディレクトリ構成で必要な資材を配置していきます。

```bash
$ tree
.
├── docker-compose.yml                #コンテナの構成を管理するファイル
└── my-spring-boot                                   
    ├── Dockerfile                    #spring-boot用Dockerfile
    └── sample-es-0.0.1-SNAPSHOT.jar  #spring-bootアプリ
```

```dockerfile:my-spring-boot/Dockerfile
#ベースはJDK8イメージ
FROM openjdk:8-jdk-alpine

#アプリをjava-app.jarとしてデプロイ
COPY ./sample-es-0.0.1-SNAPSHOT.jar java-app.jar

#アプリ実行
CMD ["java","-jar","/java-app.jar"]
```
```yml:docker-compose.yml
version: "3"
services:
  my-spring-boot:
    build: my-spring-boot/       #spring-boot用Dockerfileの格納先を指定
    image: sample-sb04           #イメージ名
    container_name: sample-sb04  #コンテナ名
    ports:
      - 48080:8080
    links:
      - my-elasticsearch         #Elasticserchコンテナへ通信する際のエイリアス
  my-elasticsearch:
    image: shinyashikis/my-elasticsearch7:0.0.1    #実演３）で作成したイメージを指定
    container_name: sample-es04          　        #コンテナ名
    ports:
      - 49200:9200
```

docker-compose.ymlなど必要な資材配置後は `docker-compose up` コマンド一発でビルド＆コンテナの起動が行われます。

```bash
$ ls
docker-compose.yml my-spring-boot

#ビルド実行
$ docker-compose up -d

#コンテナ確認
$ docker-compose ps

#ブラウザで確認
http://localhost:48080/myEsInfo
```

以下のようなElasticserchの情報がブラウザに表示されていればOKです

```
Elasticsearchの情報
nodeName: 1497813f0e6f
clusterName: Cluster [elasticsearch]
```

# おわりに
駆け足ではありますが、簡単な環境を構築して他サーバでも共有できる状態までできました。
実際には、データの永続化を考慮したり、コンテナ起動時に複雑な処理を行わせるためにシェルを実行させたりと、今回の例のように簡単にはいかない場合もあります。

そういった場合は、冒頭で紹介したサイトや公式サイト、書籍などを参考にしていただければと思います。

また、実演で使った資材は以下に格納しておきます。

- 実演　２）Dockerfileを使用したやりかた
  - https://github.com/shinyashikis/docker-sample02
- 実演　４）Docker Composeを使用したやりかた
  - https://github.com/shinyashikis/docker-sample04

# 参考書籍
- [Docker実践入門――Linuxコンテナ技術の基礎から応用まで](https://www.amazon.co.jp/Docker%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80%E2%80%95%E2%80%95Linux%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-Software-Design-plus-%E4%B8%AD%E4%BA%95/dp/4774176540)
- [Docker/Kubernetes 実践コンテナ開発入門](https://www.amazon.co.jp/Docker-Kubernetes-%E5%AE%9F%E8%B7%B5%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80-%E5%B1%B1%E7%94%B0-%E6%98%8E%E6%86%B2/dp/4297100339)