【学習メモ】Dockerコマンド(17個)を、コンテナにApacheをインストールする流れでおさらい

#はじめに
Docker Engineのコマンドを覚えるための学習メモです。
apacheをコンテナにインストールし動かす流れでおさらいします。
流れは、イメージのダウンロード、Apacheをインストールしてビルド、コンテナの起動とビルドと削除です。
おさらいできるdockerコマンドは以下の通りです。

```sh:イメージ操作
search, pull, images, build, rmi, image prune
```
```sh:コンテナ操作
run, exec, attach, stop, start, restart, commit, rm, container prune
```
```sh:コンテナ確認
history, ps
```
```sh:ログ確認
logs
```

回線速度にもよりますが、10分あればおさらいできます。
ApacheをインストールするコンテナはCentos7を想定しています。
Dockerは17.05.0-ce, Build 89658beです。
間違いの指摘や、学習の上で○○したほうが良いというような
改善のコメント大歓迎です。

また、初めてDockerを学ぶうえではこちらの記事が参考になりました。
[Dockerハンズオン基礎編：コンテナとイメージのライフサイクルを理解](http://qiita.com/zembutsu/items/ca0fa7b874c8375be8a4)

同じように流れで覚える記事がありました。
[Docker pull commit push Dockerfile Apache Tomcat環境をつくる](http://qiita.com/cyberblack28/items/f026394919099c744462)
こちらの方がやりごたえあります。

#イメージのダウンロード
##docker search
公式docker hubからイメージがあるか検索します。

```sh:公式イメージの検索
docker search -f "is-official=true" centos
```
##docker pull
公式docker hubからイメージ+タグを指定してローカル環境にダウンロードします。
Tags一覧の取得方法は以下のリンクをご覧ください。
[DockerHubのイメージのタグ一覧をコマンドで取得する](http://www.mazn.net/blog/2015/12/26/1548.html)

Dockerリンク : [explorer](https://hub.docker.com/explore/)、[centos](https://hub.docker.com/_/centos/)、[ubuntu](https://hub.docker.com/_/ubuntu/)

```sh:コロンで区切ってバージョンを指定。latestが最新。バージョン指定も可。
docker pull centos:latest
docker pull centos:7.3.1611
docker pull php:apache
```
##docker image
ローカル環境に保存されたイメージを確認します。

```sh:イメージ確認、どれも同じ動作
docker images
docker image list
docker image ls
```
#ビルド
##Dockerfileの作成
runコマンドでレイヤーを重ねていくのは大変なので
Dockerfileを作成し、レイヤーをまとめて重ねます。

Centos6/7でDockerfileのコメントを分けています。
from行は```docker pull```で取得したイメージを使用するので、同じように[REPOSITORY]:[TAG]と記述します。

```sh:コメント行以外は1度は手打ちしても良いかも
tee Dockerfile <<- 'EOF'
```
```sh:Dockerfileの中身
## -------------- ##
#FROM centos:latest
FROM centos:7.3.1611
#FROM centos:6.9
## -------------- ##

RUN sed -ie 's@^gpgcheck=1@#gpgcheck=1\ngpgcheck=0@g' /etc/yum.conf
RUN yum install -y httpd
RUN echo "It Works, maybe" >> /var/www/html/index.html

## -----------------------------------##
### centos 7
###RUN systemctl start httpd.service
RUN systemctl enable httpd.service

### centos 6.9
#RUN service httpd start
#RUN chkconfig --level 345 httpd on
## -----------------------------------##
```
```yum install```でsignature: NOKEYが出ますので、キーは入れずyumのgpgcheckを無効にして対応しています。
Proxy環境下の人はyumコマンドの前に以下を入れます。

```sh:Dockerfileでyum.confにproxy設定を追加する
RUN echo "proxy=http://[proxy]:[port]/" >> /etc/yum.conf
```
##docker build
イメージを新しく作成します。
カレントディレクトリに作成したDockerfileを使用します。
コマンドの[末尾のドット](http://docs.docker.jp/engine/reference/commandline/build.html?highlight=build#path)や[ハイフン](http://docs.docker.jp/engine/reference/commandline/build.html?highlight=build#build-with)を忘れずに。
[Docker-docs-ja 1.13.RC コマンドラインリファレンス>build](http://docs.docker.jp/engine/reference/commandline/build.html)

```sh:Dockerfileをつかう
docker build -t [new-image-name] .
```
```sh:Dockerfile以外をリダイレクトしてつかう
docker build -t [new-image-name] - < Dockerfile-dev
```

これでapacheがインストールされたベースイメージが完成します。

```sh:コンテナが生成されたか確認
docker images
```
##docker history
コンテナにどんなレイヤーが積み重なっているのか確認します。

```sh:Dockerfileの履歴が適用されているか確認
docker history [new-image-name]
```
DockerfileでRUNコマンドを4つ動かしているので、
historyの最新部分はその4層が表示されます。


#コンテナの起動とビルドと削除
##docker run
コンテナを起動(レイヤーを追加)します。
DockerfileにあるRUNコマンドと同じです。
runはコンテナを起動するときに使います。

```sh:ホスト側ポート8080とコンテナ側ポート80を結合
docker run --privileged \ #特権。SElinuxが有効なときに必要。
           -h httpd2 \    #ホスト名
           -d \           #デタッチした状態
           -p 8080:80 \   #ポートの指定、ホスト側:コンテナ側
           --name [new-container-name] \ #新しく作るコンテナ名
           [new-image-name] \ #コンテナの元にするイメージ
            /sbin/init \  #コンテナで起動するプログラム
```
```sh:コピペのためのワンライナー
docker run --privileged -h [host-name] -d -p 8080:80 --name [container-name] [image-name] /sbin/init
```
```sh:公式のapacheイメージを使ってコンテナ起動
docker run -d -p 8080:80 httpd
249808a3abd5da227e7d2a7a176107d07c41392fab4c1eba38a5bb01dabc637e
```
```sh:公式のphp-apacheイメージを使ってコンテナ起動
docker run -d -p 8080:80 php:apache                                                                 
cdb3f19a74ca0a9810aa3dddb97aa79a8dc79aaa746ecf035a4848bc7ef523ba
```
- 公式のhttpdやphp:apacheイメージはコンテナを立ち上げるときにコマンドを入れる必要がありません。

一読すると良い記事
[CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動する]
(http://qiita.com/yunano/items/9637ee21a71eba197345)


##docker ps
起動中のコンテナ一覧を表示します。
起動したコンテナが一覧に表示されるか確認します。

```sh:起動中コンテナの一覧
docker ps
```
```sh:停止中のコンテナも含めた一覧
docker ps -a
```
リストに[new-container-name]があるか確認します。
名前があればコンテナが起動している状態です。
コンテナ内のapacheが起動しているので、ローカル環境からdockerホストの8080ポートへhttp接続できるか確認します。

```sh:wgetで確認
wget localhost:8080
cat index.html
```
```sh:curlで確認
curl localhost:8080
curl localhost:8081
```
Dockerfileのindex.htmlに追記した内容が表示されているはずです。
apacheの公式コンテナは```<html><body><h1>It works!</h1></body></html>```が表示されるはずです。
php-apacheの公式コンテナはルートディレクトリを表示できないと返ってきます。

## docker logs
実行中のコンテナのログを確認します。
上記で公式コンテナを使った場合、アクセスログは以下のコマンドで取得します。

```sh:logsコマンド
docker logs 2498
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Tue Feb 06 10:09:37.438655 2018] [mpm_event:notice] [pid 1:tid 140545174194048] AH00489: Apache/2.4.29 (Unix) configured -- resuming normal operations
[Tue Feb 06 10:09:37.441405 2018] [core:notice] [pid 1:tid 140545174194048] AH00094: Command line: 'httpd -D FOREGROUND'
172.17.0.1 - - [06/Feb/2018:10:09:46 +0000] "GET / HTTP/1.1" 200 45
172.17.0.1 - - [06/Feb/2018:10:10:06 +0000] "GET / HTTP/1.1" 200 45
```
- ```2498```は、コンテナを起動したときに出る文字列で、立ち上げたコンテナのIDの先頭4文字です。コマンド上でコンテナを指定するときは、立ち上げのときに```--name```で付けたコンテナ名か、コンテナIDを使います。コンテナIDは全桁入力せず、先頭の数桁を指定するだけで指定できます。
- コンテナ内のLogfileの多くは、```./access.log -> /dev/stdout```のように記述されています。

参考資料
[docker logs(docs.docker.com)](https://docs.docker.com/engine/reference/commandline/logs/)
[dockerのlog周りの対応(christina04.hatenablog.com)](http://christina04.hatenablog.com/entry/2016/10/27/001717)

##docker exec / docker attach
実行中のコンテナにコマンドを実行させます。
runはコンテナ起動＋コマンドを実行させるときに使いますが、
execは起動中のコンテナにコマンドを実行させるときに使います。
[docker runとdocker execの違いの解説](http://www.memotansu.jp/2017/04/docker/852/)

```sh:コマンドを実行させてみる
docker exec [new-container-name] sleep 180 &
```
シェルを起動し、接続します。

```sh:コンテナ内シェルを起動して接続
docker exec -it [new-container-name] /bin/bash
```
httpdやsleepが起動しているか確認します。

```:コンテナ内でhttpdやsleepが起動しているか確認
# ps aux | grep -e "httpd" -e "sleep"
```

```docker exec -it [new-container-name] /bin/bash```でコンテナに入ったときは```exit```で抜けますが、
```docker attach```で入ったときはCtrl + P -> Ctrl + Qで抜ける必要があり、注意が必要です。

```sh:attachで入る
docker attach [new-container-name]
```

[Dockerコンテナ内で操作 attachとexecの違い](http://qiita.com/RyoMa_0923/items/9b5d2c4a97205692a560)

docker exec で公式コンテナに入って、apacheのログファイルの実体を確認します。

```
docker exec -it cdb /bin/bash
root@cdb3f19a74ca:/var/www/html# ls -l /var/log/apache2/           
total 0
lrwxrwxrwx. 1 root root 11 Feb 16  2018 access.log -> /dev/stdout
lrwxrwxrwx. 1 root root 11 Feb 16  2018 error.log -> /dev/stderr
lrwxrwxrwx. 1 root root 11 Feb 16  2018 other_vhosts_access.log -> /dev/stdout
```


##docker stop / docker start
コンテナを停止させます。

```sh:コンテナを停止
docker stop [new-container-name]
```
```sh:コンテナを再開
docker start [new-container-name]
```
```sh:コンテナを停止して再開
docker restart [new-container-name]
```
```docker start```しても、Exited(0)などですぐ止まってしまうときは、初めてコンテナを起動(run)したときのCOMMANDが終了しているからだと思われます。
```docker run -it [image-name] /bin/bash```で起動すれば、```exit```で抜けても```docker start```で起動できます。

##docker commit
コンテナをイメージに変換します。
runで重ねたイメージレイヤーを結合し、イメージにします。

```sh:コンテナをイメージ[new-image-name2]へ変換
docker commit [new-container-name] [new-image-name2]
```


##docker rm / docker container prune
停止しているコンテナを削除します。

```sh:コンテナをローカル環境から削除
docker rm [new-container-name]
```
起動していないコンテナをすべてローカル環境から削除します。

```sh:停止中のコンテナをすべてローカルから削除
docker container prune
```
##docker rmi / docker image prune
ローカル環境に保存されたイメージを削除します。

```sh:ローカル環境に保存されたイメージを削除
docker rmi [new-image-name]
```
コンテナに利用されていないイメージをすべてローカル環境から削除します。

```sh:使用していないイメージをローカル環境からすべて削除
docker image prune
```


あとはDockerfileを削除すれば、環境はきれいになるはずです。
以上でおさらいは終了です。
お付き合いありがとうございました。