Amazon EC2にDocker CEの環境を構築する


Docker公式ドキュメンテーション（英語）で公開されている手順に従って、Amazon EC2にDocker CEとDocker Composeをインストールしました。

[Get Docker for CentOS | Docker Documentation](https://docs.docker.com/engine/installation/linux/centos/)  
Docker公式によるCentOSへのDocker CEインストール手順（英語）  
[CentOS 7にDocker CEをインストール &larr; RootLinks Co., Ltd.](https://www.rootlinks.net/2017/04/15/centos-7%E3%81%ABdocker-ce%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/)  
インストールするにあたって、確認コマンド等が丁寧に掲載されたこちらの記事が大変参考になりました。

**動作環境**

- AMI ID: ami-29d1e34e(CentOS Linux 7 x86_64)
- インスタンスタイプ: t2.medium
- OSバージョン: CentOS Linux release 7.3.1611 (Core) 
- ユーザー名: centos（EC2のデフォルトユーザー名）

**前提条件**

- Amazon EC2にインスタンスが作成されていること
- インスタンスのキーペア（秘密鍵）がクライアントの```~/.ssh```に保存されていること
- Elastic IPがインスタンスのパブリックIPに割り当てられていること
- OSのrootパスワードが設定されていること

<a name="docker-ceをインストールする"></a>
## Docker CEをインストールする

**SE Linuxの無効化は非推奨**  
Docker CEのインストール手順を紹介するサイトの中にはSE Linuxの無効化を推奨しているものがあります。しかし **安易にSELinuxを無効化すると脆弱性に繋がる恐れがある** ため、その危険性を十分に理解しなければなりません。本稿ではSELinuxを無効化することなく、Docker CEをインストールする手順を紹介します。

**Yumリポジトリを最新化する**

```
$ sudo yum -y update
```

**Docker CEに必要なパッケージをインストールする**

```
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
```

**Docker CEリポジトリを追加する**

```
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
```

[yumまとめ - Qiita](http://qiita.com/tenbrother/items/96422c7604ecfe990533)  
yumとyum-config-managerの基本的なコマンドについてまとめられた投稿

**Yumリポジトリのキャッシュを更新する**

```
$ sudo yum makecache fast
```
**安定版のDocker CEパッケージのみインストールが有効であることを確認する**

```
$ cat /etc/yum.repos.d/docker-ce.repo

[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://download.docker.com/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg
```
[docker-ce-stable]のみ```enabled=1```（有効）となっていることを確認します。

**Docker CEリポジトリに含まれるパッケージの一覧を確認する**

```
$ yum list docker-ce.x86_64  --showduplicates |sort -r

利用可能なパッケージ
読み込んだプラグイン:fastestmirror
docker-ce.x86_64            17.03.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            17.03.0.ce-1.el7.centos             docker-ce-stable
Determining fastest mirrors
 * updates: ftp.iij.ad.jp
 * extras: ftp.iij.ad.jp
 * base: ftp.iij.ad.jp
```

**Docker CEパッケージの情報を確認する**

```
$ sudo yum info docker-ce

読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * epel: ftp.jaist.ac.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
インストール済みパッケージ
名前                : docker-ce
アーキテクチャー    : x86_64
バージョン          : 17.03.1.ce
リリース            : 1.el7.centos
容量                : 65 M
リポジトリー        : installed
提供元リポジトリー  : docker-ce-stable
要約                : The open-source application container engine
URL                 : https://dockerproject.org
ライセンス          : ASL 2.0
説明                : Docker is an open source project to build, ship and run any application as a
                    : lightweight container.
                    : 
                    : Docker containers are both hardware-agnostic and platform-agnostic. This means
                    : they can run anywhere, from your laptop to the largest EC2 compute instance and
                    : everything in between - and they don't require you to use a particular
                    : language, framework or packaging system. That makes them great building blocks
                    : for deploying and scaling web apps, databases, and backend services without
                    : depending on a particular stack or provider.
```

**Docker CEをインストールする**

```
$ sudo yum install docker-ce
```

<a name="dockerの動作確認をする"></a>
## Dockerの動作確認をする
<a name="dockerのサービスを開始する"></a>
### Dockerのサービスを開始する
**現在のDockerのサービス起動設定を確認する**

```
$ systemctl list-unit-files | grep docker
docker.service                                disabled
```
デフォルトの場合、```docker.service```は```disabled```（自動起動しない）となっています。

**Dockerのサービスを自動起動するように設定する**

```
$ sudo systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
```

**Dockerのサービスが自動起動となっていることを確認する**

```
$ systemctl list-unit-files | grep docker
docker.service                                enabled 
```
docker.serviceが```enabled```（自動起動する）となっていることを確認します。

**Dockerのサービスを開始する**

```
$ sudo systemctl start docker
```

**Dockerのサービスが開始されていることを確認する**

```
$ systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2017-06-25 06:25:09 UTC; 25s ago
     Docs: https://docs.docker.com
 Main PID: 28170 (dockerd)
   Memory: 16.1M
   CGroup: /system.slice/docker.service
           ├─28170 /usr/bin/dockerd
           └─28176 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.soc...
```
``` Active: active (running)```となっていればサービスが開始されています。

<a name="sudoコマンドなしでdockerを操作する"></a>
### sudoコマンドなしでDockerを操作する

rootでないユーザーでDockerを操作すると、デフォルトでは以下のようなエラーが出力されてコマンドを実行することができません。

```
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```
これはユーザーが```var/run/docker.sock```の権限を持っていないことが原因です。ユーザーをdockerグループに加えることで上記のエラーを回避することができますが、この対処は公式Dockerが警告するように脆弱性を生む原因となります。そのためdockerグループに追加するのは信頼されたユーザー（sudoersに含まれるユーザー）のみにしましょう。

[Post-installation steps for Linux | Docker Documentation](https://docs.docker.com/engine/installation/linux/linux-postinstall/#configure-docker-to-start-on-boot)

*/var/run/docker.sockとは*

>Dockerはデーモンプロセス（dockerd）と通信するクライアントとして動くわけですが、その際のソケットにはUNIXドメインソケット（/var/run/docker.sock）が利用されます。そのため、dockerdは特権的な動作が可能です。dockerdが使うUNIXドメインソケットに対して書き込み権限を有するということはルート権限があるのと同じことと言えます。  
もし一般ユーザがこのdocker.sockに書き込み権限を持っていると、自由にルートを取りどんなコードも実行できてしまう脆弱性が生まれることになります。

[Dockerコンテナ内からホストマシンのルートを取る具体的な方法（あるいは/var/run/docker.sockを晒すことへの注意喚起） | 48JIGEN *Reloaded*](https://rimuru.lunanet.gr.jp/notes/post/how-to-root-from-inside-container/)

**dockerグループを表示する**

```
$ getent group docker
docker:x:993:
```

**dockerグループにユーザーを追加する**

```
$ sudo usermod -aG docker `whoami`
```

**dockerグループにユーザーが追加されていることを確認する**

```
$ getent group docker
docker:x:993:centos
```

**dockerグループを更新する**

```
$ sudo newgrp docker
```

<a name="dockerの動作確認をする-1"></a>
### Dockerの動作確認をする
**インストールしたDockerのバージョンを確認する**

```
$ docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Mon Mar 27 17:05:44 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Mon Mar 27 17:05:44 2017
 OS/Arch:      linux/amd64
 Experimental: false
```

**hello-worldコンテナを起動し、動作確認をする**

```
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b04784fba78d: Pull complete 
Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
```