Docker CE for WindowsでDockerを学ぶ (version 18.03.1-ce-win65)

# 概要

この記事は以前に投稿した「[Docker for WindowsでDockerを学ぶ (バージョンCE 17.06.2)] (https://qiita.com/rubytomato@github/items/eec2118e89ee9bd8d17a)」を、2018年7月時点で最新のDocker for Windows Community Edition Version 18.03.1で改定した記事です。

**環境**

* Windows 10 Professional
    * PowerShell 5.1
* Docker Community Edition 18.03.1-ce-win65
    * API Version 1.37

**参考**

* [Get started with Docker for Windows] (https://docs.docker.com/docker-for-windows/)
* [Docker for Windows Stable Release notes] (https://docs.docker.com/docker-for-windows/release-notes/)
* [Docker run reference] (https://docs.docker.com/engine/reference/run/)

# インストール

ダウンロードページよりWindows版のインストーラーをダウンロードして実行します。インストールが終了するとデスクトップにDockerアイコンが作成されますが、ここで一旦PCを再起動します。

**インストール終了**

![d2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/21028cd1-06b7-a46d-1a83-a12208202cff.png)

**Welcome**

再起動すると自動的にDockerが開始されWelcome画面が立ち上がります。

![d4.png](https://qiita-image-store.s3.amazonaws.com/0/22772/733b39b8-04bb-8d05-8428-e3d51fea1a34.png)

**Hyper-V**

Hyper-Vマネージャで仮想マシン(MobyLinuxVM)が作成されていることを確認します。
（Hyper-Vマネージャはスタートメニューの"Windows 管理ツール" → "Hyper-Vマネージャ"でアクセスできます。またはスタートメニューから直接"Hyper-V"と入力して検索）

![d6.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c027dcfb-6068-20ee-64cf-6c6e08c56bf9.png)

## バージョンの確認

**dockerのバージョン確認**

```text
PS> docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:12:48 2018
 OS/Arch:      windows/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: false
```

**docker-composeのバージョン確認**

```text
PS> docker-compose version
docker-compose version 1.21.1, build 7641a569
docker-py version: 3.2.1
CPython version: 3.6.4
OpenSSL version: OpenSSL 1.0.2k  26 Jan 2017
```

**docker-machineのバージョン確認**

* この記事では使用しません。

```text
PS> docker-machine version
docker-machine.exe version 0.14.0, build 89b8332
```

## インストール後の設定

タスクトレイにあるDockerアイコンを右クリックしコンテキストメニューから"Settings..."を選択します。

![d10.png](https://qiita-image-store.s3.amazonaws.com/0/22772/15f1e376-1201-fcba-c2c5-ca17fb8ce681.png)

### General

PC起動時にDockerが立ち上がらないように"Start Docker when you log in"のチェックを外しました。

![d9.png](https://qiita-image-store.s3.amazonaws.com/0/22772/2e1da6cc-2050-5a3d-0c85-6b94b3942c40.png)

### リソースの割り当て

この記事では下図のようにリソースを割り当てました。ApplyボタンをクリックするとDockerが再起動します。

![d7.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c52fdd03-1d4e-cdac-17a8-512be56e80f1.png)

### 共有ドライブの設定

コンテナから利用できるドライブを設定します。今のところ(2018/07)ディレクトリ単位での設定はできないようです。ApplyボタンをクリックするとWindowsアカウントのパスワードを求められますので入力して設定が完了します。

![d8.png](https://qiita-image-store.s3.amazonaws.com/0/22772/fdf13d40-6fff-7f80-f445-4177fbeb2302.png)

### ネットワーク

イメージのダウンロードができない場合などは、DNS Serverを`8.8.8.8`に固定すると改善する場合があります。

![d12.png](https://qiita-image-store.s3.amazonaws.com/0/22772/4c696557-66c5-cd50-a80f-79e6501f76a5.png)


# 基本的なdockerコマンドの使い方

docker 1.13よりコマンドのグループ化が行われ、以下の管理コマンド(Manage Command)へ再編成されています。（従来の(～1.12)コマンドも有効です。）
ただし`docker build`と`docker run`は再編後もtop level commandとして残っています。
また`docker network`や`docker volume`など1.13以前の段階でコマンドの体系がグループ化されていたものがあります。

|Management command|           |
|:-----------------|:----------|
|[docker checkpoint] (https://docs.docker.com/engine/reference/commandline/checkpoint/)|API 1.25+ |
|[docker config] (https://docs.docker.com/engine/reference/commandline/config/)|API 1.30+ |
|[docker container] (https://docs.docker.com/engine/reference/commandline/container/)| |
|[docker image] (https://docs.docker.com/engine/reference/commandline/image/)| |
|[docker manifest] (https://docs.docker.com/engine/reference/commandline/manifest/)|This command is experimental. |
|[docker network] (https://docs.docker.com/engine/reference/commandline/network/)| |
|[docker node] (https://docs.docker.com/engine/reference/commandline/node/)|API 1.24+ |
|[docker plugin] (https://docs.docker.com/engine/reference/commandline/plugin/)|API 1.25+ |
|[docker secret] (https://docs.docker.com/engine/reference/commandline/secret/)|API 1.25+ |
|[docker service] (https://docs.docker.com/engine/reference/commandline/service/)|API 1.24+ |
|[docker stack] (https://docs.docker.com/engine/reference/commandline/stack/)|API 1.25+ |
|[docker swarm] (https://docs.docker.com/engine/reference/commandline/swarm/)|API 1.24+ |
|[docker system] (https://docs.docker.com/engine/reference/commandline/system/)| |
|[docker trust] (https://docs.docker.com/engine/reference/commandline/trust/)| |
|[docker volume] (https://docs.docker.com/engine/reference/commandline/volume/)|API 1.21+ |

**参考**

* Restructure CLI commands by adding docker image and docker container commands for more consistency [#26025] (https://github.com/moby/moby/pull/26025)

**DOCKER_HIDE_LEGACY_COMMANDS**

`DOCKER_HIDE_LEGACY_COMMANDS`環境変数に1をセットすると、docker --helpの出力からレガシーコマンドを隠します。

```text
PS> $env:DOCKER_HIDE_LEGACY_COMMANDS = 1
PS> docker --help
```

## [docker image] (https://docs.docker.com/engine/reference/commandline/image/)

|Child command        |Legacy command             |Notes      |
|:--------------------|:--------------------------|:----------|
|docker image build   |[docker build] (https://docs.docker.com/engine/reference/commandline/build/) |docker buildはtop level command |
|docker image history |[docker history] (https://docs.docker.com/engine/reference/commandline/history/) | |
|docker image import  |[docker import] (https://docs.docker.com/engine/reference/commandline/import/) | |
|docker image inspect | | |
|docker image load    |[docker load] (https://docs.docker.com/engine/reference/commandline/load/) | |
|docker image ls      |[docker images] (https://docs.docker.com/engine/reference/commandline/images/) | |
|docker image prune   | |API 1.25+ |
|docker image pull    |[docker pull] (https://docs.docker.com/engine/reference/commandline/pull/) | |
|docker image push    |[docker push] (https://docs.docker.com/engine/reference/commandline/push/) | |
|docker image rm      |[docker rmi] (https://docs.docker.com/engine/reference/commandline/rmi/) | |
|docker image save    |[docker save] (https://docs.docker.com/engine/reference/commandline/save/) | |
|docker image tag     |[docker tag] (https://docs.docker.com/engine/reference/commandline/tag/) | |

### イメージのダウンロード (pull)

```text
PS> docker image pull ubuntu:18.10
18.10: Pulling from library/ubuntu

//...省略...

Status: Downloaded newer image for ubuntu:18.10
```

### イメージの一覧表示 (ls)

```text
PS> docker image ls
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
ubuntu                     18.10               64a6a5be4188        3 days ago          70.1MB
```

#### イメージIDだけ表示 (ls -q)

```text
PS> docker image ls -q
64a6a5be4188
```

### イメージの削除 (rm)

イメージIDは半角スペースで区切って複数指定できます。

```text
PS> docker image rm 64a6a5be4188
```

### 未使用イメージの削除 (prune)

```text
PS> docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
```

### イメージのビルド (build)

Dockerfileのあるディレクトリで下記のbuildコマンドを実行します。

```text
PS> docker image build -t rubytomato/ubuntu:0.0.1 .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ubuntu:18.10
 ---> 64a6a5be4188

//...省略...

Successfully built 205ed036002c
Successfully tagged rubytomato/ubuntu:0.0.1
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permission
s. It is recommended to double check and reset permissions for sensitive files and directories.
```

**Dockerfile**

使用するDockerfile

```text
FROM ubuntu:18.10

ENV LANG ja_JP.utf8
ENV TZ Asia/Tokyo

RUN apt-get update \
&& apt-get install -y vim locales tzdata \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata

CMD ["/bin/bash"]
```

```text
PS> docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rubytomato/ubuntu   0.0.1               205ed036002c        3 minutes ago       146MB
ubuntu              18.10               64a6a5be4188        3 days ago          70.1MB
```

## [docker container] (https://docs.docker.com/engine/reference/commandline/container/)

|Child command            |Legacy command             |Notes      |
|:------------------------|:--------------------------|:----------|
|docker container attach  |[docker attach] (https://docs.docker.com/engine/reference/commandline/attach/) | |
|docker container commit  |[docker commit] (https://docs.docker.com/engine/reference/commandline/commit/) | |
|docker container cp      |[docker cp] (https://docs.docker.com/engine/reference/commandline/cp/)| |
|docker container create  |[docker create] (https://docs.docker.com/engine/reference/commandline/create/) | |
|docker container diff    |[docker diff] (https://docs.docker.com/engine/reference/commandline/diff/) | |
|docker container exec    |[docker exec] (https://docs.docker.com/engine/reference/commandline/exec/) | |
|docker container export  |[docker export] (https://docs.docker.com/engine/reference/commandline/export/) | |
|docker container inspect | | |
|docker container kill    |[docker kill] (https://docs.docker.com/engine/reference/commandline/kill/) | |
|docker container logs    |[docker logs] (https://docs.docker.com/engine/reference/commandline/logs/) | |
|docker container ls      |[docker ps] (https://docs.docker.com/engine/reference/commandline/ps/) | |
|docker container pause   |[docker pause] (https://docs.docker.com/engine/reference/commandline/pause/) | |
|docker container port    |[docker port] (https://docs.docker.com/engine/reference/commandline/port/) | |
|docker container prune   | |API 1.25+ |
|docker container rename  |[docker rename] (https://docs.docker.com/engine/reference/commandline/rename/) | |
|docker container restart |[docker restart] (https://docs.docker.com/engine/reference/commandline/restart/) | |
|docker container rm      |[docker rm] (https://docs.docker.com/engine/reference/commandline/rm/) | |
|docker container run     |[docker run] (https://docs.docker.com/engine/reference/commandline/run/) |docker runはtop level commnad |
|docker container start   |[docker start] (https://docs.docker.com/engine/reference/commandline/start/) | |
|docker container stats   |[docker stats] (https://docs.docker.com/engine/reference/commandline/stats/) | |
|docker container stop    |[docker stop] (https://docs.docker.com/engine/reference/commandline/stop/) | |
|docker container top     |[docker top] (https://docs.docker.com/engine/reference/commandline/top/) | |
|docker container unpause |[docker unpause] (https://docs.docker.com/engine/reference/commandline/unpause/) | |
|docker container update  |[docker update] (https://docs.docker.com/engine/reference/commandline/update/) | |
|docker container wait    |[docker wait] (https://docs.docker.com/engine/reference/commandline/wait/) | |

### コンテナの実行 (run)

```text
PS> docker run --name my-ubuntu -it ubuntu:18.10 bash
root@71e3519cab5c:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.10 (Cosmic Cuttlefish)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu Cosmic Cuttlefish (development branch)"
VERSION_ID="18.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=cosmic
UBUNTU_CODENAME=cosmic
root@71e3519cab5c:/# exit
exit
PS>
```

exitまたは<kbd>Ctrl + D</kbd>を押すとコンテナから抜け、コンテナは停止します。
コンテナを停止せずにコンテナから抜ける（デタッチ）には<kbd>Ctrl + P + Q</kbd>を押します。コンソールに"read escape sequence"と表示されコンテナから抜けることができます。

```text
root@71e3519cab5c:/# read escape sequence
PS>
```

### 実行中コンテナの一覧表示 (ls)

```text
PS> docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
94ad277059c4        ubuntu:18.10        "bash"              34 seconds ago      Up 32 seconds                           my-ubuntu
```

#### すべてのコンテナの一覧表示 (ls -a)

```text
PS> docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
94ad277059c4        ubuntu:18.10        "bash"              5 minutes ago       Exited (0) 14 seconds ago                       my-ubuntu
```

#### コンテナIDだけ表示 (ls -q)

```text
PS> docker container ls -q
94ad277059c4
```

### 実行中のコンテナを停止 (stop)

コンテナID又はコンテナ名は半角スペースで区切って複数指定できます。

```text
PS> docker container stop my-ubuntu
my-ubuntu
```

### 停止中のコンテナを起動 (start)

コンテナID又はコンテナ名は半角スペースで区切って複数指定できます。

```text
PS> docker container start my-ubuntu
my-ubuntu
````

### コンテナの実行時にデタッチする (run -d)

-dオプションを付けてコンテナを実行するとデタッチします。デタッチするとコンテナはバックグラウンドで実行され制御がプロンプトに戻ります。

```text
PS> docker run --name my-ubuntu -it -d ubuntu:18.10 bash
1777798c58e9cee397a1f623a60a5beba63b16f950a9e92c30ee1aad4adadc4c
PS>
```

### コンテナにアタッチする (attach)

デタッチしたコンテナにアタッチします。
exitまたは<kbd>Ctrl + D</kbd>で抜けるとコンテナも停止します。

```text
PS> docker container attach my-ubuntu
root@1777798c58e9:/#
```

### 実行中のコンテナで指定するコマンドを実行 (exec)

```text
PS> docker container exec -it my-ubuntu bash
root@1777798c58e9:/#
```

### コンテナの削除 (rm)

コンテナID又はコンテナ名は半角スペースで区切って複数指定できます。

```text
PS> docker container rm my-ubuntu
my-ubuntu
```

### 停止中のコンテナをすべて削除 (prune)

```text
PS> docker container prune -f
Deleted Containers:
71e3519cab5c87ed029e32b3096d864da059cd6dc018f485701b6f2f4f17ba83

Total reclaimed space: 25B
```

## [docker volume] (https://docs.docker.com/engine/reference/commandline/volume/)

|Child command            |Notes                      |
|:------------------------|:--------------------------|
|docker volume create     |API 1.21+ |
|docker volume inspect    |API 1.21+ |
|docker volume ls         |API 1.21+ |
|docker volume prune      |API 1.25+ |
|docker volume rm         |API 1.21+ |

### Docker volumeを作成 (create)

Docker volumeを作成します。

```text
PS> docker volume create share_data
share_data
```

作成したvolumeをコンテナへマウントします。

```text
PS> docker run --name c1 -it -d -v share_data:/share_data busybox sh
                                   ^^^^^^^^^^ ^^^^^^^^^^^
                                    |          |
                                    |          +--- コンテナのマウントポイント
                                    +-------------- Docker volumeの名前
```

volumeは複数のコンテナで共有することができます。

```text
PS> docker run --name c2 -it -d -v share_data:/share_data busybox sh
```

c1コンテナのマウントポイント(/share_data)でtest.txtというファイルを作成し、

```text
PS> docker container exec -it c1 sh
/ # cd /share_data
/share_data # echo 'test from c1' > test.txt
```

c2コンテナのマウントポイント(/share_data)にtest.txtファイルが存在することを確認します。

```text
PS> docker container exec -it c2 sh
/ # cd /share_data
/share_data # cat test.txt
test from c1
```

### Docker volumeの一覧表示 (ls)

Docker volumeを一覧表示します。

```text
PS> docker volume ls
DRIVER              VOLUME NAME
local               share_data
```

### Docker volumeの詳細確認 (inspect)

```text
PS> docker volume inspect share_data
[
    {
        "CreatedAt": "2018-07-20T22:31:58Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/share_data/_data",
        "Name": "share_data",
        "Options": {},
        "Scope": "local"
    }
]
```

Docker VolumeはDocker Host(Windows 10のHyper-Vを利用した環境ではMobyLinuxVMという仮想マシン)内に作成されます。上記のinspectの結果のMountpointはDocker Hostのディレクトリになります。

以下の方法でDocker Hostにアクセスして、Docker Volumeが存在するか確認してみます。

```text
PS> docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine /bin/sh
/ # chroot /host
/ # cd /var/lib/docker/volumes/share_data/_data
/var/lib/docker/volumes/share_data/_data # cat test.txt
test from c1
```

**参考**

* [How can I SSH into the Beta’s MobyLinuxVM] (https://forums.docker.com/t/how-can-i-ssh-into-the-betas-mobylinuxvm/10991)

### Docker volumeの削除 (rm)

```text
PS> docker volume rm share_data
share_data
```

コンテナにマウントしているvolumeは削除できません。

## [docker network] (https://docs.docker.com/engine/reference/commandline/network/)

|Child command            |Notes                      |
|:------------------------|:--------------------------|
|docker network connect   | |
|docker network create    | |
|docker network disconnect| |
|docker network inspect   | |
|docker network ls        | |
|docker network prune     |API 1.25+ |
|docker network rm        | |

### Docker networkの作成 (create)

```text
PS> docker network create my-network
920d8c6fa442cc01c6ebf5e7a25be02ad636e9b44efa2014ab7279a3c720d4d0
```

コンテナの実行時に作成したnetworkへ参加させます。

```text
PS> docker run --name c1 -it -d --network my-network busybox sh
```

```text
PS> docker run --name c2 -it -d --network my-network busybox sh
```

この2つのコンテナは同一のセグメントに属しているのでpingで疎通確認ができます。

```text
PS> docker exec -it c1 sh
/ # ping c2
PING c2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.134 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.133 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.114 ms
64 bytes from 172.18.0.3: seq=3 ttl=64 time=0.115 ms
64 bytes from 172.18.0.3: seq=4 ttl=64 time=0.115 ms
^C
--- c2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.114/0.122/0.134 ms
```

### Docker networkの一覧表示 (ls)

bridge,host,noneはデフォルトで作成されているnetworkです。

```text
PS> docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
05832b6662f4        bridge              bridge              local
deb5dd87efce        host                host                local
920d8c6fa442        my-network          bridge              local
0b4c7027e5ec        none                null                local
```

### Docker networkの詳細表示 (inspect)

下記はmy-networkにc1、c2の2つのコンテナを参加させた状態でinspectした結果です。
結果の"Containers"にネットワークに参加しているコンテナが確認できます。

```text
PS> docker network inspect my-network
[
    {
        "Name": "my-network",
        "Id": "920d8c6fa442cc01c6ebf5e7a25be02ad636e9b44efa2014ab7279a3c720d4d0",
        "Created": "2018-07-22T14:54:21.4393187Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0e2b1cb2190b04c6ae2e6ba178a01d1db6e8cd91364f8275722fd725d85606b0": {
                "Name": "c2",
                "EndpointID": "af87cd616d873959b58f5ffe44f2374eb508f9836f3cbd30c55f27a9bb643eb7",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "eb822a594258bd9c9b44b9aa3cb436d67ce995c09f881fa36c7341ccaa9ac6e1": {
                "Name": "c1",
                "EndpointID": "1a80a179fb27644d66fdf344dc16369d076c700783618ceae54e43144ce0718b",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
```

### Docker networkへ接続 (connect)

networkに参加していないコンテナをnetworkへ接続させます。

```text
PS> docker network connect my-network c1
```

### Docker networkから切断 (disconnect)

networkに参加しているコンテナを切断します。

```text
PS> docker network disconnect my-network c1
```

### Docker networkの削除 (rm)

```text
PS> docker network rm my-network
my-network
```

## [docker system] (https://docs.docker.com/engine/reference/commandline/system/)

|child command            |Legacy command             |Notes      |
|:------------------------|:--------------------------|:----------|
|docker system df         | |API 1.25+ |
|docker system events     |[docker events] (https://docs.docker.com/engine/reference/commandline/events/) | |
|docker system info       |[docker info] (https://docs.docker.com/engine/reference/commandline/info/) | |
|docker system prune      | |API 1.25+ |

### ディスク使用量の確認 (df)

Dockerのディスク使用量を確認します。

```text
PS> docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              8                   2                   1.475GB             1.029GB (69%)
Containers          3                   2                   171B                136B (79%)
Local Volumes       1                   0                   13B                 13B (100%)
Build Cache                                                 0B                  0B
```

-vオプションを指定するとさらに詳細な内容が確認できます。

```text
PS> docker system df -v
```

### イベントの監視 (events)

特定のdockerコマンドで発生するイベントをリアルタイムに監視します。

最初にeventsコマンドを実行してイベント監視状態に入ります。

```text
PS> docker system events

```

別のターミナルからdockerコマンドを実行すると、

```text
PS> docker run --name c1 -it busybox sh
/ # 
```

eventsコマンドを実行したターミナルにそのコマンドのイベントがリアルタイムに出力されます。
下記の結果は、上記の`docker run`コマンドのイベントです。

```text
PS> docker system events
2018-07-23T00:32:35.501520700+09:00 container create 3be9867cb27d7070e75257998194ed4ebc3aad421e08a90559127cabf88a6e26 (i
mage=busybox, name=c1)
2018-07-23T00:32:35.504967300+09:00 container attach 3be9867cb27d7070e75257998194ed4ebc3aad421e08a90559127cabf88a6e26 (i
mage=busybox, name=c1)
2018-07-23T00:32:35.556587300+09:00 network connect 05832b6662f4186620418696aa5dccd311bc9bdec0b736c606d450039f058d41 (co
ntainer=3be9867cb27d7070e75257998194ed4ebc3aad421e08a90559127cabf88a6e26, name=bridge, type=bridge)
2018-07-23T00:32:35.987835600+09:00 container start 3be9867cb27d7070e75257998194ed4ebc3aad421e08a90559127cabf88a6e26 (im
age=busybox, name=c1)
2018-07-23T00:32:35.992184000+09:00 container resize 3be9867cb27d7070e75257998194ed4ebc3aad421e08a90559127cabf88a6e26 (h
eight=50, image=busybox, name=c1, width=207)
```

### システム情報の確認 (info)

Dockerのシステム情報を確認します。

```text
PS> docker system info
```

-fオプションで出力フォーマットを指定することができます。
下記はjsonで出力する例です。

```text
PS> docker system info -f '{{json .}}'
```

## その他のコマンド

管理コマンドに編成されていないtop level commandです。

### [login] (https://docs.docker.com/engine/reference/commandline/login/)

Docker registryにログインします。

```text
PS> docker login -u <username>
Password: *********
Login Succeeded
```

ログインするとDocker registryにローカルのイメージをpushすることができるようになります。
（pushするには先にDocker Hubでリポジトリを作成しておく必要があります。）

```text
PS> docker push rubytomato/ubuntu:0.0.1
The push refers to repository [docker.io/rubytomato/ubuntu]
673dabc4635f: Pushed
2869bec4b1a5: Mounted from library/ubuntu
4a11639c84e2: Mounted from library/ubuntu
d6d789572265: Mounted from library/ubuntu
5eee0d150402: Mounted from library/ubuntu
0.0.1: digest: sha256:bb2f883ea6e512e21b95af8cc3f2bb399114fc88272ab2de19720ac7afa61fd0 size: 1362
```

### [logout] (https://docs.docker.com/engine/reference/commandline/logout/)

Docker registryからログアウトします。

```text
PS> docker logout
```

### [search] (https://docs.docker.com/engine/reference/commandline/search/)

Docker Hubから条件を満たすイメージを検索します。

```text
PS> docker search --filter is-official=true mysql
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   6575                [OK]
mariadb             MariaDB is a community-developed fork of MyS…   2080                [OK]
percona             Percona Server is a fork of the MySQL relati…   350                 [OK]
```

### [version] (https://docs.docker.com/engine/reference/commandline/version/)

Dockerのバージョン情報を出力します。

```text
PS> docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:12:48 2018
 OS/Arch:      windows/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: false
```


# 複数のコンテナを連携させる

dockerコマンドを使って複数のコンテナで構成するJavaアプリケーションの実行環境を構築します。

|コンテナ名    |利用するイメージ:タグ          |ポート|
|:------------|:----------------------------|:-----|
|db-server    |mysql:8.0.11                 |3306  |
|app-server   |openjdk:8u171-jdk-alpine3.8  |9000  |
|http-server  |nginx:1.15.1-alpine          |80:80 |

## networkの作成

これから作成する各コンテナが接続するnetworkを作成します。

```text
PS> docker network create --driver bridge my-network
```

**networkの一覧**

```text
PS> docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
3b7067f92b97        bridge              bridge              local
deb5dd87efce        host                host                local
e0b994908c8c        my-network          bridge              local
0b4c7027e5ec        none                null                local
```

**networkの状態**

```text
PS> docker network inspect my-network
[
    {
        "Name": "my-network",
        "Id": "e0b994908c8c12f91a47a9cd7793994458e32313efff75eb7229560eb0467a64",
        "Created": "2018-07-20T21:23:37.0589799Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
```

## volumeの作成

DBのデータを永続化するためのvolumeを作成します。

```text
PS> docker volume create db_data
```

**volumeの一覧**

```text
PS> docker volume ls
DRIVER              VOLUME NAME
local               db_data
```

## DBサーバー用のコンテナを作成

MySQL Serverを実行するコンテナを作成します。データは永続化できるようにDocker volumeをマウントします。

**イメージのダウンロード**

officialの[mysql-server] (https://hub.docker.com/r/mysql/mysql-server/)で公開されているイメージを利用します。

```text
PS> docker image pull mysql:8.0.11
8.0.11: Pulling from library/mysql

// ...省略...

Status: Downloaded newer image for mysql:8.0.11
```

**コンテナの実行**

```text
PS> docker run --name db-server `
-v db_data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=password `
-e TZ=Asia/Tokyo `
--network my-network `
-d `
mysql:8.0.11 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --default-time-zone='+9:00'
```

**DBサーバーが起動したかログで確認**

container lsコマンドで確認するとDBサーバーが起動しているように見えますが、実際には起動中の場合があるのでログで確認します。

```text
PS> docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
eb0f360d84fc        mysql:8.0.11        "docker-entrypoint.s…"   27 seconds ago      Up 25 seconds       3306/tcp            db-server
```

container logsコマンドでログの出力を監視します。
下記のようなログ(ready for connections. ...)が出力されていればDBサーバーの起動は完了しています。

```text
PS> docker container logs --follow --tail 20 db-server

//...省略...

2018-07-20T21:27:15.538249Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.11'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Serve
r - GPL.
```

**コンテナのシェルにアクセス**

コンテナのシェルにアクセスして、コンテナ内からDBサーバーにログインします。

```text
PS> docker exec -it db-server bash
root@eb0f360d84fc:/# mysql -h localhost -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

**mbind: Operation not permitted**

ログに`mbind: Operation not permitted`というメッセージが出力されることがあります。

[mysql 8.0.11 docker: mbind: Operation not permitted] (https://github.com/docker-library/mysql/issues/422)

**動作検証用アプリケーションで使用するDBスキーマの作成**

補足欄に記載しているSQLで、データベース、ユーザー、テーブルを作成します。

**コンテナの停止、起動**

container stopコマンドでコンテナを停止します。

```text
PS> docker container stop db-server
```

container startコマンドでコンテナを起動します。

```text
PS> docker container start db-server
```

## APPサーバー用のコンテナを作成

Javaアプリケーションを実行するためのコンテナです。コンテナ実行時にJavaアプリケーションを実行するのではなく、任意のタイミングで実行するようにします。

**イメージのダウンロード**

officialの[openjdk] (https://hub.docker.com/_/openjdk/)で公開されているイメージを利用します。

```text
PS> docker image pull openjdk:8u171-jdk-alpine3.8
8u171-jdk-alpine3.8: Pulling from library/openjdk

//...省略...

Status: Downloaded newer image for openjdk:8u171-jdk-alpine3.8
```

Javaのバージョン確認

```text
PS> docker run --rm openjdk:8u171-jdk-alpine3.8 java -version
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (IcedTea 3.8.0) (Alpine 8.171.11-r0)
OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)
```

**実行するJavaアプリケーション**

コンテナの連携を確認するために使用するJavaアプリケーションはSpring-Bootを利用したRest APIアプリケーションです。詳細は補足欄に記載しています。

**コンテナの実行**

ローカルPC上のアプリケーションのプロジェクトディレクトリをコンテナと共有し、コンテナ内からアプリケーションのビルドおよび起動・停止が行えるようにします。
この例では`D:/dev/IdeaProjects/demo`というプロジェクトディレクトリをコンテナの`/app`にマウントしています。

```text
PS> docker run `
--name app-server `
-v D:/dev/IdeaProjects/demo:/app:rw `
--network my-network `
-it `
-d `
openjdk:8u171-jdk-alpine3.8 sh
```

**Javaアプリケーションの起動**

ローカルPCで実行可能なjarをビルドしておけば、下記のコマンドでアプリケーションを起動できます。

```text
PS> docker container exec -it app-server java -jar '-Dspring.profiles.active=docker' /app/target/demo.jar
```

**コンテナ内でビルド、起動・停止を行う**

コンテナにアクセスします。

```text
PS> docker container exec -it app-server sh
```

spring-bootプラグインを使ってアプリケーションを起動する方法

```text
/ # cd /app
/app # ./mvnw spring-boot:run -Drun.profiles=docker
```

ビルドしたjarを使ってアプリケーションを起動する方法

```text
/ # cd /app
/app # ./mvnw clean package -Dmaven.test.skip=true
/app # java -jar -Dspring.profiles.active=docker target/demo.jar
```

## HTTPサーバー用のコンテナを作成

**イメージのダウンロード**

officialの[nginx] (https://hub.docker.com/_/nginx/)で公開されているイメージを利用します。

```text
PS> docker image pull nginx:1.15.1-alpine
1.15.1-alpine: Pulling from library/nginx

//...省略...

Status: Downloaded newer image for nginx:1.15.1-alpine
```

動作確認のため、コンテナを実行してブラウザでページにアクセスしてみます。

```text
PS> docker run --name my-nginx --rm -d -p 80:80 nginx:1.15.1-alpine nginx-debug -g 'daemon off;'
```

ブラウザからlocalhostにアクセスして下図のページが表示されることを確認します。

![d11.png](https://qiita-image-store.s3.amazonaws.com/0/22772/76a4da81-5eca-8765-d920-2d2feda5d52f.png)

確認出来たらコンテナを停止させます。

```text
PS> docker stop my-nginx
```

**コンテナの実行**

この例ではAPPサーバーへプロキシさせる設定ファイルを`D:/dev/docker-mount/nginx-1.15.1/conf.d`に配置し、このディレクトリをコンテナの`/etc/nginx/conf.d`へマウントしています。

```text
PS> docker run `
--name http-server `
-v D:/dev/docker-mount/nginx-1.15.1/conf.d:/etc/nginx/conf.d:ro `
--network my-network `
-p 80:80 `
-d `
nginx:1.15.1-alpine
```

**設定ファイル**

APPサーバーへのプロキシ設定は下記の通りです。

```text:default.conf
server {
    listen 80;
    server_name localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;

    location /app/ {
        proxy_pass http://app-server:9000/app/;
        proxy_redirect off;
        proxy_cookie_path /app /;
    }
}
```

## 3つのコンテナが立ち上がった状態

上記の内容で実行したコンテナが立ち上がっている状態です。

```text
PS> docker container ls
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                NAMES
94cbf2d12701        nginx:1.15.1-alpine           "nginx -g 'daemon of…"   18 seconds ago      Up 17 seconds       0.0.0.0:80->80/tcp   http-server
3ec8d007bca0        openjdk:8u171-jdk-alpine3.8   "sh"                     14 minutes ago      Up 14 minutes                            app-server
055717c7f8a0        mysql:8.0.11                  "docker-entrypoint.s…"   2 hours ago         Up 2 hours          3306/tcp             db-server
```

**Javaアプリケーションの動作確認**

ブラウザから下記のアドレスにアクセスしてjsonのレスポンスが返ってくることを確認します。

```text
GET http://localhost/app/memo/1
GET http://localhost/app/memo/list
```


# docker-composeで複数のコンテナを起動する

dockerコマンドで構築した上記の環境をdocker-composeで構築してみます。
これまでに作成したイメージ、コンテナ、network、volumeはすべて削除してから行いました。

## プロジェクトの作成

docker-compose.yml、各コンテナのイメージをビルドするためのDockerfileやコンテナにコピーするファイルを管理するプロジェクトです。
複数メンバーで開発環境を共有する場合、このプロジェクトをVCSで管理するという想定です。各自でdockerをインストールし、このプロジェクトをチェックアウトしdocker-composeで環境を構築します。

```text
/project-root
  |
  +--- docker-compose.yml
  |
  +--- .env
  |
  +--- /mysql
  |      |
  |      +--- Dockerfile
  |      |
  |      +--- /conf
  |      |      |
  |      |      +--- mysqld.cnf
  |      |
  |      +--- /sql
  |             |
  |             +--- 1_schema.sql
  |             +--- 2_init_memo_data.sql
  |
  +--- /app
  |      |
  |      +--- Dockerfile
  |
  +--- /nginx
         |
         +--- Dockerfile
         |
         +--- /conf
         |      |
         |      +--- default.conf
         |
         +--- /repo
                |
                +--- nginx.repo
```

### docker-compose.yml

app-serverコンテナが参照するローカルのプロジェクトディレクトリを${PROJECT_HOME}という環境変数で定義しています。
この環境変数は後述する.envで設定します。

```yaml
version: "3.6"
services:

  db:
    container_name: db-server
    build:
      context: ./mysql
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
    networks:
      - my-network
    restart: always

  app:
    container_name: app-server
    build:
      context: ./app
    volumes:
      - ${PROJECT_HOME}:/app
      - m2-cache:/root/.m2
    environment:
      - SPRING_PROFILES_ACTIVE=docker
    depends_on:
      - db
    networks:
      - my-network
    restart: always
    tty: true

  www:
    container_name: http-server
    build:
      context: ./nginx
    depends_on:
      - app
    ports:
      - 80:80
    networks:
      - my-network
    restart: always

networks:
  my-network:
    driver: bridge

volumes:
  db-data:
    driver: local
  m2-cache:
    driver: local
```

appサービスのttyをtrueにしているのは、コンテナにアクセスしてJavaアプリケーションを起動させる必要があるためです。

### .env

.envファイルで定義した環境変数はdocker-compose.ymlやコンテナ内から参照できます。

```text
PROJECT_HOME=D:\dev\IdeaProjects\demo
```

### DBサーバー用コンテナ

#### Dockerfile

```text
FROM mysql:8.0.11

COPY ./conf/mysqld.cnf /etc/mysql/conf.d

COPY ./sql/1_schema.sql /docker-entrypoint-initdb.d
COPY ./sql/2_init_memo_data.sql /docker-entrypoint-initdb.d

RUN chmod 664 /etc/mysql/conf.d/mysqld.cnf

ENV TZ=Asia/Tokyo
```

#### mysqld.conf

```text
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci

log_output = FILE
general_log = 1
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_syslog = 0
log_timestamps = SYSTEM
long_query_time = 3
slow_query_log = 1
```

#### sql

補足の動作検証用アプリケーションで使用するDBに記載しています。

* 1_schema.sql
* 2_init_memo_data.sql

### APPサーバー用コンテナ

#### Dockerfile

```text
FROM centos:7

RUN yum update -y && yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel && yum reinstall -y glibc-common && yum -y clean all

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV JAVA_HOME /usr/lib/jvm/java-1.8.0-openjdk

RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

EXPOSE 9000
```

### HTTPサーバー用コンテナ

#### Dockerfile

```text
FROM centos:7

COPY ./repo/nginx.repo /etc/yum.repos.d

RUN yum update -y && yum install -y --enablerepo=nginx nginx && yum reinstall -y glibc-common && yum -y clean all

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja

RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

COPY ./conf/default.conf /etc/nginx/conf.d

RUN chmod 664 /etc/nginx/conf.d/default.conf

RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80

STOPSIGNAL SIGTERM

CMD ["nginx", "-g", "daemon off;"]
```

#### default.conf

```text
server {
    listen 80;
    server_name localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;

    location /app/ {
        proxy_pass http://app-server:9000/app/;
        proxy_redirect off;
        proxy_cookie_path /app /;
    }
}
```

## docker-composeコマンド

### サービスのビルド (build)

docker-compose.ymlのあるディレクトリで下記コマンドを実行してサービスをビルドします。

```text
PS> docker-compose build
```

キャッシュを使わずにビルドする場合はオプション`--no-cache`を指定します。

```text
PS> docker-compose build --no-cache
```

### コンテナの起動 (up)

```text
PS> docker-compose up -d
Creating network "docker-java-develop_my-network" with driver "bridge"
Creating volume "docker-java-develop_db-data" with local driver
Creating db-server ... done
Creating app-server ... done
Creating http-server ... done
```

サービスのビルドと起動を同時に行うこともできます。ビルドは変更のあるサービスに対してのみ行われます。

```text
PS> docker-compose up --build -d
```

### コンテナの一覧表示 (ps)

```text
PS> docker-compose ps
指定されたパスが見つかりません。
   Name                 Command             State         Ports
----------------------------------------------------------------------
app-server    /bin/bash                     Up      9000/tcp
db-server     docker-entrypoint.sh mysqld   Up      3306/tcp
http-server   nginx -g daemon off;          Up      0.0.0.0:80->80/tcp
```

### 任意のコマンドを実行 (exec)

コンテナは起動していますがapp-serverコンテナではまだSpring Bootのアプリケーションは起動していません。
下記のexecコマンドでapp-serverコンテナに接続してアプリケーションを起動します。なお、ここで指定しているappはコンテナ名ではなくサービス名です。

```text
PS> docker-compose exec app bash
[root@36b2e310620f /]#
```

spring-bootプラグインでアプリケーションのビルドと実行を行います。プロファイルは環境変数(SPRING_PROFILES_ACTIVE)に定義しているため省略可能です。
初回は依存関係にあるライブラリのダウンロードが行われるため時間がかかりますが、ダウンロード先をDocker volumeにしているので2回目以降は時間はかからないと思います。

```text
[root@36b2e310620f /]# cd /app
[root@36b2e310620f app]# ./mvnw spring-boot:run
```

**Javaアプリケーションの動作確認**

各コンテナが連携していればmemoテーブルのデータがjsonで返ってきます。

```text
GET http://localhost/app/memo/1
GET http://localhost/app/memo/list
```

### 実行中のプロセスの確認 (top)

topコマンドで各サービスのプロセスを確認できます。

```text
PS> docker-compose top
app-server
指定されたパスが見つかりません。
 PID    USER   TIME    COMMAND
-------------------------------
15312   root   0:00   /bin/bash

db-server
指定されたパスが見つかりません。
 PID    USER   TIME   COMMAND
-----------------------------
15125   999    0:00   mysqld

http-server
指定されたパスが見つかりません。
 PID    USER   TIME                    COMMAND
----------------------------------------------------------------
15568   root   0:00   nginx: master process nginx -g daemon off;
15692   999    0:00   nginx: worker process
```

### コンテナの停止 (down)

コンテナを停止します。

```text
PS> docker-compose down
Stopping http-server ... done
Stopping app-server  ... done
Stopping db-server   ... done
Removing http-server ... done
Removing app-server  ... done
Removing db-server   ... done
Removing network docker-java-develop_my-network
```

### コンテナのログを確認 (logs)

サービスが起動しないなどの原因を調べたい場合はlogsコマンドでコンテナのログを確認します。

```text
PS> docker-compose logs
```

特定のコンテナに絞りたい場合はサービス名を指定します。

```text
PS> docker-compose logs db
```


# 補足

## 動作検証用のDB、アカウントの作成

**1_schema.sql**

```sql
CREATE DATABASE IF NOT EXISTS sample_db
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_general_ci
;

CREATE USER IF NOT EXISTS 'test_user'@'%'
  IDENTIFIED BY 'test_user'
  PASSWORD EXPIRE NEVER
;

GRANT ALL ON sample_db.* TO 'test_user'@'%';

USE sample_db;

CREATE TABLE IF NOT EXISTS memo (
  id BIGINT AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  description TEXT NOT NULL,
  done BOOLEAN DEFAULT FALSE NOT NULL,
  updated TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) NOT NULL,
  PRIMARY KEY (id)
) CHARACTER SET = utf8mb4, COLLATE utf8mb4_0900_ai_ci;
```

**2_init_memo_data.sql**

```sql
INSERT INTO memo (title, description, done) VALUES ('title 1', 'description 1', false);
INSERT INTO memo (title, description, done) VALUES ('title 2', 'description 2', false);
INSERT INTO memo (title, description, done) VALUES ('title 3', 'description 3', true);
INSERT INTO memo (title, description, done) VALUES ('title 4', 'description 4', false);
INSERT INTO memo (title, description, done) VALUES ('title 5', 'description 5', true);
INSERT INTO memo (title, description, done) VALUES ('title 6', 'description 6', false);
INSERT INTO memo (title, description, done) VALUES ('title 7', 'description 7', false);
INSERT INTO memo (title, description, done) VALUES ('title 8', 'description 8', true);
INSERT INTO memo (title, description, done) VALUES ('title 9', 'description 9', true);
INSERT INTO memo (title, description, done) VALUES ('title 10', 'description 10', true);
```

## 動作検証用のJavaアプリケーション

コンテナの動作検証用にRest APIアプリケーションをSpring Bootで開発しました。
以下にコントローラーのソースコードとpom.xml、application.ymlの内容を記載します。
アプリケーションはmemoテーブルのデータをjsonフォーマットでレスポンスする単純なRest APIです。

エンドポイントは下記の2つだけです。

```text
GET localhost:9000/app/memo/list
GET localhost:9000/app/memo/{id}
```

**コントローラー**

```java
@RestController
@RequestMapping(path = "memo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class MemoController {

    private MemoService service;

    public MemoController(MemoService service) {
        this.service = service;
    }

    @GetMapping(path = "{id}")
    public ResponseEntity<Memo> memo(@PathVariable(value = "id") Long id) {
        Memo memo = service.findById(id);
        return new ResponseEntity<>(memo, HttpStatus.OK);
    }

    @GetMapping(path = "list")
    public ResponseEntity<List<Memo>> list(Pageable page) {
        Page<Memo> memos = service.findAll(page);
        return new ResponseEntity<>(memos.getContent(), HttpStatus.OK);
    }

}
```

**pom.xml**

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo</name>
	<description>Demo application</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.14.RELEASE</version>
		<relativePath/>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.datatype</groupId>
			<artifactId>jackson-datatype-jsr310</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version><!--$NO-MVN-MAN-VER$-->
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-java8</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>${project.name}</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludeDevtools>true</excludeDevtools>
					<executable>true</executable>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<compilerArgs>
						<arg>-Xlint:all,-options,-path</arg>
					</compilerArgs>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>
```

**application.yml**

```yml
# SPRING CORE
spring:
  application:
    name: demo
# OUTPUT
  output:
    ansi:
      enabled: detect
# PROFILES
  profiles:
    active: dev
# DATASOURCE
  datasource:
    url: jdbc:mysql://localhost:3306/sample_db?useSSL=false&allowPublicKeyRetrieval=true
    username: test_user
    password: test_user
    driver-class-name: com.mysql.cj.jdbc.Driver
    tomcat:
      maxActive: 4
      maxIdle: 4
      minIdle: 0
      initialSize: 4
# JPA
  jpa:
    open-in-view: true
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true
  jackson:
    serialization:
      indent_output: true
      write-dates-as-timestamps: false
      write-durations-as-timestamps: true

# EMBEDDED SERVER CONFIGURATION
server:
  port: 9000
  context-path: /app

logging:
  level:
    root: info
    org.springframework: info
    com.example: debug

---

spring:
  profiles: docker
  datasource:
    url: jdbc:mysql://db-server:3306/sample_db?useSSL=false&allowPublicKeyRetrieval=true
    username: test_user
    password: test_user
    driver-class-name: com.mysql.cj.jdbc.Driver
```