初心者のDocker事始め

# やること

Mac上でDockerを使いNginx環境を作りつつDockerをそれとなく理解していく。ある程度の流れと雰囲気が掴めればOK。

# Dockerのインストール

今回はHomebrewを使ってインストールしていく。

```sh
$ brew install docker
$ brew install docker-compose
$ brew cask install docker
```

でインストールして、

```sh
$ open /Applications/Docker.app
```

で、Dockerアプリケーションを起動。起動が終わったら

```sh
$ docker ps
```

で、

```sh
CONTAINER ID   IMAGE   COMMAND...
```

みたいなヘッダーが表示されればOK。

`/Applications`にFinderのアプリケーションに表示されている色々なものがあります。`open /Applications/any.app`は覚えておくと良いかもしれない。

# NginxをインストールしてHTMLを表示して遊ぶ

## Nginxのイメージを取得する。

イメージというのはコンテナを作る元になるもの。イメージはDocker Hubっていうところから取得可能。`docker search`コマンドでイメージを検索できる。

```sh
$ docker search nginx
```

を叩くと、

```sh
NAME                                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                                                  Official build of Nginx.                        11305               [OK]
jwilder/nginx-proxy                                    Automated Nginx reverse proxy for docker con…   1588                                    [OK]
richarvey/nginx-php-fpm                                Container running Nginx + PHP-FPM capable of…   709                                     [OK]
jrcs/letsencrypt-nginx-proxy-companion                 LetsEncrypt container to use with nginx as p…   506                                     [OK]
webdevops/php-nginx                                    Nginx with PHP-FPM                              125                                     [OK]
```

こんな感じで利用可能なNginxイメージが表示されます。イメージは純粋にそれそのものだったりNginxであればいい感じに設定してくれているものがあったり等々。今回は一番上のnginx(Official build of Nginx.)をpullする。

```sh
$ docker pull nginx
```

`Using default tag: latest`と表示される。これはデフォルトで最新を取ってくるよって意味。バージョン指定が必要ならイメージ名の後ろにタグを付与する。pullが終わったら`docker images`でpull済みのイメージ一覧を表示してNginxがpullされていることを確認する。

```sh
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              27a188018e18        11 days ago         109MB
```

こんな感じで表示されればOK。

## イメージからコンテナを起動する

以下のコマンドで先程pullしたイメージからコンテナを生成/起動します。

```sh
$ docker run -d -p 8080:80 --name test-webserver nginx
```

`-d`はバックグラウンド起動でそのままterminalを使う場合は設定しておいた方が良い。iTermとか使ってればオプション指定しなくても良いかも。オプションを省略した時は`ctrl+c`でコンテナを **停止** させられます。バックグラウンド起動した時は`docker stop [name]`で停止します。
`-p`はポート転送設定オプションになります。[ホストPort]:[コンテナ:Port]の形で指定する。`8080:80`であれば`0.0.0.0:8080`にアクセスするとそのまま`container:80`にアクセスするよって感じ。
`--name`はコンテナの名前。適当にわかりやすい名前を付けると良い。
`nginx`はpullしたイメージ名。
コマンドを実行したら実行中コンテナ一覧を表示してみる。

```sh
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
f8fda9e72931        nginx               "nginx -g 'daemon of…"   12 seconds ago      Up 11 seconds       0.0.0.0:8080->80/tcp   test-webserver
```

こんな感じで表示されてればOK。

## アクセスしてみる

0.0.0.0:8080とcontainer:80がつながっているのでlocalhost:8080にアクセスすればEginxのデフォルトページが表示されるはず。ってことで、

```sh
$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
:
:
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
:
:
</body>
</html>
```

と返ってくればOK、成功。

## HTMLを書き換える

### コンテナにログインして書き換える

以下のコマンドでログイン。rootでログインした状態になる。自分の環境がfishでもコンテナ内にfishが無いのでbashプロセスを起動。

```sh
$ docker exec -it test-webserver /bin/bash
root@xxxxxxxxxxxx:/#
```

`-it`は手元のterminalで操作するよ、的な意味。
`/bin/bash`はbashプロセス立ち上げて、それを操作するよの意味。

pwdとかlsとかやってみる。

```sh
$ pwd
/
$ ls -la
total 72
drwxr-xr-x   1 root root 4096 Apr 28 04:48 .
drwxr-xr-x   1 root root 4096 Apr 28 04:48 ..
-rwxr-xr-x   1 root root    0 Apr 28 04:48 .dockerenv
drwxr-xr-x   2 root root 4096 Mar 26 12:00 bin
drwxr-xr-x   2 root root 4096 Feb  3 13:01 boot
drwxr-xr-x   5 root root  340 Apr 28 04:48 dev
drwxr-xr-x   1 root root 4096 Apr 28 04:48 etc
drwxr-xr-x   2 root root 4096 Feb  3 13:01 home
drwxr-xr-x   1 root root 4096 Mar 26 12:00 lib
drwxr-xr-x   2 root root 4096 Mar 26 12:00 lib64
drwxr-xr-x   2 root root 4096 Mar 26 12:00 media
drwxr-xr-x   2 root root 4096 Mar 26 12:00 mnt
drwxr-xr-x   2 root root 4096 Mar 26 12:00 opt
dr-xr-xr-x 183 root root    0 Apr 28 04:48 proc
drwx------   2 root root 4096 Mar 26 12:00 root
drwxr-xr-x   1 root root 4096 Apr 28 04:48 run
drwxr-xr-x   2 root root 4096 Mar 26 12:00 sbin
drwxr-xr-x   2 root root 4096 Mar 26 12:00 srv
dr-xr-xr-x  13 root root    0 Apr 28 05:08 sys
drwxrwxrwt   1 root root 4096 Apr 16 21:20 tmp
drwxr-xr-x   1 root root 4096 Mar 26 12:00 usr
drwxr-xr-x   1 root root 4096 Mar 26 12:00 var
```

おー...。ってことでindex.htmlを触ってみる。

```sh
$ cd /usr/share/nginx/html
$ vim index.html
bash: vim: command not found
$ vi index.html
bash: vi: command not found
```

なるほど。viも無い。Vimである必要性は無いけど...

```sh
$ apt-get update
$ apt-get install vim
```

でインストールして、index.htmlを編集。タイトルとか本文とかを適当に編集。こんな感じに書き換えた。

```html
<h1>Welcome to Docker!</h1>
<p>If you see this page, the docker and  nginx web server is successfully installed and
working. Further configuration is required.</p>
```

`curl localhost:8080`にアクセスして修正した場所が反映されていればOK。やったね。
とは言え、ファイル修正するのにコンテナにログインしないとダメなの？ってことは開発環境はコンテナの中に作るの？え？Vim？死にそう...ってなる。

### ホストOSののディレクトリをコンテナにマウントしてよしなにやる

「おっ？何言ってるかわからねぇな＾＾」って感じですが、簡単に言うとホストOS（例：Mac）のディレクトリをコンテナのディレクトリ（例：公開ディレクトリ）にしちゃう、的な感じです。コンテナのこのディレクトリはホストOSのこのディレクトリな、以上。って感じです。百聞は一見に如かず、やってみよう。

まずは起動中のコンテナを停止。停止は起動方法により異なる（先述の通り）。

```sh
# バックグラウンド起動時
$ docker stop [name]
# フォアグラウンド起動時
$ (ctrl + c)
```

マウントするディレクトリを作る。

```sh
$ pwd
/Users/[user-name]
$ mkdir sample-docker
$ cd sample-docker/
$ mkdir test-webserver2
```

次にコンテナを作る。さっき作ったコンテナ使えば良いじゃんって思うんですけど、ちょろっと調べた感じrunオプションは変更できないっぽい。コンテナをcommitしてイメージにしてrunする時にオプション追加して...とかはできるっぽい。雰囲気掴むだけの記事だから細かいところは見て見ぬ振り。

```sh
$ docker run -d -p 8080:80 -v (pwd)/sample-docker/test-webserver2:/usr/share/nginx/html --name test-webserver2 nginx
```

**fish環境なので`(pwd)`としていますが、bash環境の方は`$(pwd)`としないとエラーになると思います。**  
-vが先程の「ホストOSののディレクトリをコンテナにマウント」になる。ポート指定と同じ感じ。
早速`/Users/[user-name]/sample-docker/test-webserver2`にindex.htmlを作成する。中身はとりあえず何でも良い。とりあえず`hoge`とか書いておけば良い。curlで`localhost:8080`にアクセス。

```sh
$ curl localhost:8080
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.15.12</center>
</body>
</html>
```

...(´・ω・｀)ｱﾚ????  
`docker exec`で中に入って確認してもindex.htmlができてない。入ったついでに`/usr/share/nginx/html`に移動して、中身は`hage`の4文字のindex.htmlを作成してホストOSの方から`curl localhost:8080`で確認。

```sh
$ curl localhost:8080
hage
```

(´・ω・｀)ははははハゲちゃうわ  
という冗談は置いといて、原因調査。

[Docker for Macでコンテナとのボリュームマウントに苦労した話](https://qiita.com/harukisan/items/31f15780760ab2f3d213)を見つつ`/Users/[user name]/`を参照する時は`~/`で指定しないとダメってことを理解。

`~/sample-docker/test-webserver3`ディレクトリを作成して以下のコマンドでコンテナを起動。

```sh
$ docker run -p 8080:80 -v ~/sample-docker/test-webserver3:/usr/share/nginx/html --name test-webserver3 nginx
```

`curl localhost:8080`でhogeが返ってくることを確認。やったね。

### 複数ディレクトリをコンテナにマウントする

複数マウントする場合は`-v`オプションを複数設定すれば良さそう。

```sh
$ mkdir test-webserver4
$ mkdir test-webserver4-log
$ docker run -p 8080:80 -v ~/sample-docker/test-webserver4:/usr/share/nginx/html -v ~/sample-docker/test-webserver4-log:/var/log/nginx --name test-webserver4 nginx
```

`test-webserver4`にindex.htmlを作って反映、`test-webserver4-log`に`access.log`と`error.log`ができることが確認できる。

# 覚えておくと良いdockerコマンド

## docker search

[search — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/search.html)

Docker Hubにあるイメージを検索できる。とりあえずこれ欲しいなって思ったらsearchで漁る感じになりそう。
Tagの一覧を取得するコマンドは無さそう。`curl https://registry.hub.docker.com/v2/repositories/library/any`で取ってくるかshell script書くかですかね。

## docker pull

[pull — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/pull.html)

Docker Hubからイメージを取得する。タグを指定＝バージョン指定のイメージでOK。

## docker run

[Docker run リファレンス — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/run.html)

コンテナプロセスの起動。  
ディレクトリのマウントとかバックグラウンド起動とかできる。

## docker ps

[ps — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/ps.html)

コンテナ一覧を取得する。オプションを付けないと動いているコンテナ一覧で、`-a`を付けると起動してないコンテナも取得できる。

## docker start [container name] / docker stop [container name]

[start — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/start.html)
[stop — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/stop.html)

コンテナの起動/停止。

## docker exec

[exec — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/exec.html)

コンテナにログインする。terminalを引き続き使う場合は`-it`オプションを付与する。

# 最後に

単独での使い方は何となくわかったので、次は複数コンテナを連携させて遊ぶ。
Dockerfileとかdocker-composeとかは追々。