Docker 奮闘記 ～開発・テスト・リリースへの応用編～

# docker 実践
docker を用いた開発・テスト・リリースをできるようにしたい。

## 要件
* CGI アプリケーションを Docker コンテナ上で動かす
* テストを Docker コンテナ上で行う
* 本番用イメージと同じイメージでテストを実施する
* バージョン管理は git で行う

## 構成
完成形は以下になった。

* release  : 本番イメージ同梱用ファイル群
* share    : データ永続化用ディレクトリ
* unittest : 単体テスト用ソースコード群

```console
# tree -a
.
├── .git
│     :
├── .gitignore
├── Dockerfile
├── makefile
├── release
│   ├── html
│   │   ├── add_rec.cgi
│   │   ├── index.cgi
│   │   └── lib
│   │       ├── __init__.py
│   │       ├── __init__.pyc
│   │       ├── business.py
│   │       ├── business.pyc
│   │       ├── master.py
│   │       ├── master.pyc
│   │       ├── study_log.py
│   │       └── study_log.pyc
│   └── httpd.conf
├── share
│   └── var
│       └── study
│           ├── master.txt
│           └── study_log.txt
└── unittest
    ├── __init__.py
    ├── __init__.pyc
    ├── lib
    │   ├── __init__.py
    │   ├── __init__.pyc
    │   ├── test_business.py
    │   ├── test_business.pyc
    │   ├── test_master.py
    │   ├── test_master.pyc
    │   ├── test_study_log.py
    │   └── test_study_log.pyc
    └── test
```

```makefile:makefile

PORT = 8081
IMAGE = study:latest
CONTAINER = study
CONTAINER_TEST = study_test

run:
        @make build
        @docker run -d --name $(CONTAINER) -p $(PORT):80 -v `pwd`/share/var/study:/var/study --restart=always $(IMAGE)
test:
        @make build
        @docker run -it --name $(CONTAINER_TEST) --rm -v `pwd`/unittest:/var/www/html/test $(IMAGE) python -m unittest discover -t "/var/www/html" -s "/var/www/html/test" -p "test*.py" -v
build:
        @docker build -t $(IMAGE) ./
start:
        @docker start $(CONTAINER)
stop:
        @docker stop $(CONTAINER)
rm:
        -@make stop
        @docker rm $(CONTAINER)
clean:
        -@make rm
        @docker image prune -y
```

```Dockerfile:Dockerfile
FROM rhel:latest
RUN /bin/bash -c "yum clean all; yum install httpd -y; yum clean all"
COPY ./release/html /var/www/html/
COPY ./release/httpd.conf /etc/httpd/conf/httpd.conf
EXPOSE 80
Volume /var/study
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
```

```:.gitignore
*.pyc
share/*
```


## 使い方
make コマンドで、イメージの作成、コンテナの作成、コンテナ内でのテストの実施ができる。

イメージ作成

```console
# make build
Sending build context to Docker daemon 218.6 kB
Step 1/7 : FROM rhel:latest
 ---> 31cd91012c57
Step 2/7 : RUN /bin/bash -c "yum clean all; yum install httpd -y; yum clean all"
 ---> Using cache
 ---> d33e0b7ad1f7
Step 3/7 : COPY ./release/html /var/www/html/
 ---> Using cache
 ---> 52b679e0b2bc
Step 4/7 : COPY ./release/httpd.conf /etc/httpd/conf/httpd.conf
 ---> Using cache
 ---> 548bd8af5c93
Step 5/7 : EXPOSE 80
 ---> Using cache
 ---> 687cf42ff225
Step 6/7 : VOLUME /var/study
 ---> Using cache
 ---> f149cdcf57cc
Step 7/7 : CMD /usr/sbin/httpd -D FOREGROUND
 ---> Using cache
 ---> f20cbb485ce4
Successfully built f20cbb485ce4
```

テストの実施

```console
# make test
test1_todaysTheme (test.lib.test_business.TestBusiness) ... ok
test1_getAll (test.lib.test_master.TestMaster) ... ok
test1_getAll (test.lib.test_study_log.TestStudyLog) ... ok
test1_getAll_WithoutPass (test.lib.test_study_log.TestStudyLog) ... ok
test1_insert (test.lib.test_study_log.TestStudyLog) ... ok
test1_insertPass (test.lib.test_study_log.TestStudyLog) ... ok
test2_getAll (test.lib.test_study_log.TestStudyLog) ... ok
test2_insert (test.lib.test_study_log.TestStudyLog) ... ok

----------------------------------------------------------------------
Ran 8 tests in 0.033s

OK
```

本番用コンテナ作成

```console
# make run
b980c52ed5884e3458fcd4ba5eb7e52280e786ab58e97e218b0d1a036bbcfd4e

# curl http://localhost:8081
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>勉強スケジュール</title>
</head>
<body>
  :
  :
```

## 感想
まさに Infrastructure as Code。
これで開発・テスト・リリースはホスト環境を選ばず独立に実施可能に。

CI、CD までやりたいなあ。

kubernetes、OpenShift もやりたいけど、検証環境の構築が大変……。

## 参考
https://www.rhoboro.com/2018/09/07/docker-exclude-tests.html
https://qiita.com/petitviolet/items/a1da23221968ee86193b