一つのgithubリポジトリで複数のdockerhubリポジトリ用Dockerfileを管理する方法

dockerhubへimageをpushしただけではdockerfileが表示されないため、どうすれば？
というところが出発点でした。

ま、dockerhub側でコンパイルしないと信用できんということでしょう。。。
github(or,bitbucket)にDockerfileをおいてbuildすればdockerhubにDockerfileが表示される。

でも、それって…dockerhubのリポジトリごとにgithubのリポジトリを作るの？
管理、メンドクサくね？
ってことで、githubは１リポジトリで複数dockerhubリポジトリ対応する方法を考えました。

## github側構成
1. githubには一つのリポジトリを作成（例えば、dockerfilesリポジトリ）
2. dockerのリポジトリごとにフォルダを掘る
3. あとは、バージョン管理の仕方によってイロイロ

## dockerhub側
こちらはリポジトリを分けますが、Autobuildの設定をブランチでやると関係ないときにも反応してしまうため
gitのTagをSourceTypeに設定にします。
実験用はBranchをSourceTypeに設定し、AutobuildをOFFにしておきます（手動でキックできるのはブランチ対象だけなので）

リポジトリ>BuildsでConfigure Automated Buildsをクリックし設定

用途|Source Type|Source|Docker Tag|Dockerfile location|Build Context|Autobuild|
---|---|---|---|---|---|---|---|
自動設定|Tag|/^docker_repo_name$/|latest|Dockerfile|/docker_repo_name|✓|
実験用|Branche|master|test|Dockerfile|/docker_repo_name|×|

## バージョン管理パターン別設定
### Dockerfileは１パターンのみ
#### github側

```
├─dockerfiles
│  ├─docker_repo_name
│  │  │  Dockerfile
│  │  │  LICENSE
│  │  │  README.md
```
tagは「docker_repo_name」または「docker_repo_name-v1.0.0」等
dockerhub側の設定で正規表現で引っ掛けるので、引っかかる名前でtagを付けます。


#### dockerhub側（latestのみ）

|Source Type|Source|Docker Tag|Dockerfile location|Build Context|
|---|---|---|---|---|---|
|Tag|/^docker_repo_name*/|latest|Dockerfile|/docker_repo_name|

* gitで「docker_repo_name」tagがpushされたときのbuild対象
    + dockerfiles/docker_repo_name/latest/Dockerfile
        - docker tag　→　:latest

#### dockerhub側（バージョン＋latest）
最後にbuildしたバージョンのimageをlatestとしてもtagつけます

例えば、こんな感じです。
[github](https://github.com/coneyware/dockerfiles/tree/master/schemaspy_jp)
[dockerhub](https://hub.docker.com/r/coneyware/schemaspy_jp)

* github側にhook設定を入れておきます。

```
├─dockerfiles
│  ├─docker_repo_name
│  │  │   Dockerfile
│  │  │   README.md
│  │  │
│  │  └─hooks
│  │       post_push
```

push後に呼ばれるバッチ設定

```bash:hooks/post_push
#! /bin/bash
docker tag $IMAGE_NAME $DOCKER_REPO:latest
docker push $DOCKER_REPO:latest
```


|Source Type|Source|Docker Tag|Dockerfile location|Build Context|
|---|---|---|---|---|---|
|Tag|/^docker_repo_name-(v[0-9.]+)/|{\1}|Dockerfile|/docker_repo_name|

* gitで「docker_repo_name-v1.0.0」tagがpushされたときのbuild対象
    + dockerfiles/docker_repo_name/Dockerfile
        - docker tag　→　:v1.0.0
    + hook設定により上記imageをコピー
        - docker tag　→　:latest

### Dockerfileがlatestとバージョンの２ファイル
例えば、こんな感じです。
[github](https://github.com/coneyware/dockerfiles/tree/master/elixir_jp)
[dockerhub](https://hub.docker.com/r/coneyware/elixir_jp)

#### github側

READMEは最後にbuildされたものがdockerhubに反映されるようなので
同じファイルをそれぞれ用意しておいたほうが良さげ。

```
├─dockerfiles
│  ├─docker_repo_name
│  │  │  Dockerfile
│  │  │  LICENSE
│  │  │  README.md
│  │  │
│  │  └─latest
│  │          Dockerfile
│  │          README.md
```

* tagの付け方
  + latestの修正時は「docker_repo_name」
  + バージョン修正時は「docker_repo_name-v1.0.0」等

dockerhub側の設定で正規表現で引っ掛けるので、引っかかる名前でtagを付けます。

#### dockerhub側（バージョン＋latest、バージョンtag時にもlatestを作りたい）

|Source Type|Source|Docker Tag|Dockerfile location|Build Context|
|---|---|---|---|---|---|
|Tag|/^docker_repo_name*/|latest|Dockerfile|/docker_repo_name/latest|
|Tag|/^docker_repo_name-(v[0-9.]+)/|{\1}|Dockerfile|/docker_repo_name|

* gitで「docker_repo_name」tagがpushされたときのbuild対象
    + dockerfiles/docker_repo_name/latest/Dockerfile
        - docker tag　→　:latest
* gitで「docker_repo_name-v1.0.0」tagがpushされたときのbuild対象
    + dockerfiles/docker_repo_name/Dockerfile
        - docker tag　→　:v1.0.0
    + dockerfiles/docker_repo_name/latest/Dockerfile
        - docker tag　→　:latest

### latestのbuild時に違うバージョンもbuildしたい
例えば、フル機能版と縮小版の２パターンbuildしたいとき
例えば、こんな感じです。
[github](https://github.com/coneyware/dockerfiles/tree/master/novnc)
[dockerhub](https://hub.docker.com/r/coneyware/novnc)

#### github側

READMEは最後にbuildされたものがdockerhubに反映されるようなので
同じファイルをそれぞれ用意しておいたほうが良さげ。

```
├─dockerfiles
│  ├─novnc
│  │  │  Dockerfile
│  │  │  README.md
│  │  │
│  │  ├─hooks
│  │  │      pre_build
│  │  │
│  │  ├─min
│  │  │      Dockerfile
│  │  │      README.md
│  │  │
│  │  └─version
│  │          Dockerfile
│  │          README.md
```

build前に呼ばれるバッチ設定

```bash:hooks/pre_build
#! /bin/bash
cd min
echo $(pwd)
echo docker build -f $DOCKERFILE_PATH -t $DOCKER_REPO:min .
docker build -f $DOCKERFILE_PATH -t $DOCKER_REPO:min .
docker push $DOCKER_REPO:min
cd ..
```

#### dockerhub側（バージョンとlatest、同時に動かしたくはない）

|Source Type|Source|Docker Tag|Dockerfile location|Build Context|
|---|---|---|---|---|---|
|Tag|/^docker_repo_name$/|latest|Dockerfile|/docker_repo_name/latest|
|Tag|/^docker_repo_name-(v[0-9.]+)/|{\1}|Dockerfile|/docker_repo_name/version|

* gitで「docker_repo_name」tagがpushされたときのbuild対象
    + hook設定により、先に機能縮小版をbuild
        - dockerfiles/docker_repo_name/min/Dockerfile
            - docker tag　→　:min
    + dockerfiles/docker_repo_name/latest/Dockerfile
        - docker tag　→　:latest
* gitで「docker_repo_name-v1.0.0」tagがpushされたときのbuild対象
    + dockerfiles/docker_repo_name/version/Dockerfile
        - docker tag　→　:v1.0.0

## おまけ
### autobuildのカスタマイズ（詳しくは[docker docs](https://docs.docker.com/docker-hub/builds/advanced/)）
hookの設定はDockerfileのあるフォルダに`hooks`フォルダを作成し、以下のようなファイルを作ればOK
中身は`#! /bin/bash`を先頭行にいれたbashのシェルスクリプトです。

* post_checkout
    + githubからのcheckout後
* pre_build
    + docker build前
* post_build
    + docker build後
* pre_test
    + 実験していないのでよくわからないけど、テスト前
* post_test
    + 実験していないのでよくわからないけど、テスト後
* pre_push
    + docker push前
* post_push
    + docker push後

### tigのタグ操作設定
gitの操作にtigを使っているので、タグ操作を簡単にできるよう設定してます。
Docker連携用以外でつかうとリモートの強制付替が簡単にできるのはまずそうですが。。。

```.tigrc
# t に割り当てられている view-tree を T に変更
bind generic T      view-tree

# t で tag 作成（強制付替）
bind main    t      ?git tag -f "%(prompt Enter tag name: )" %(commit)
bind refs    t      ?git tag -f "%(prompt Enter tag name: )" %(branch)
# Esc-T で tag 削除（ローカルとリモートの両方）
bind main    <Esc>t ?sh -c "git tag -d %(tag) && git push -d %(remote) %(tag)"
bind refs    <Esc>t ?sh -c "git tag -d %(tag) && git push -d %(remote) %(tag)"
# Ctrl-t で remote への push（強制付替）
bind main    <Ctrl-t> ?git push -f %(remote) %(tag)
bind refs    <Ctrl-t> ?git push -f %(remote) %(tag)

```