QNAPのContainer Station用private registryとimage作成

QNAP上でちょっとした個人的なDockerコンテナを動かしたいなと思ったので、それらの記録です。
あまりDockerに詳しくはないので、もっと良いやり方があるかもしれません。

# 目標
- QNAP上で独自にbuildしたコンテナを動かす
- イメージは公開しない状態で使えるようにする
    - QNAP上にprivate registryを立てて、そこにイメージを置く

# 前提
使用した機器はTS-231Pです。もうちょっと新しい良いものが欲しかったのですが、予算の都合的に。
また、ひとまず動作させるまでの記録なので、細かいセキュリティ的な設定等については触れません。

# private registryの稼働
QNAPのContainer Station自体の設定については他にも書かれている方がいますので、特に触れません。
Container Stationを開いて、「作成」ページから "registry" で検索すればDocker Hub公式のイメージが見つかると思います。
今回は特にこだわりとかもないので、これを単純な形で使います。検索したところはこんな感じですね。
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/07d3a085-7adc-6791-6926-232c5a081152.png)

このイメージをインストールして起動すると、こんな感じで「概要」ページに表示されます。
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/ea0d2241-2e86-a5c6-0e65-d2910089c798.png)

上のスクリーンショットで黄色でマークしてあるコンテナ名をクリックすると、private registryのURLとポートが表示されます。
後ほど開発環境で作成したイメージをここにpushすることになります。
![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/2a62c7a7-eb0e-90a7-dbba-02e2dd4d8383.png)

# 独自イメージの作成
さて、次に独自のイメージを開発環境で作成します。
これもまた、基本的にはコードを書いたりエントリポイントを用意して、Dockerfileからbuildするという基本的な所は他にも書かれてる方が沢山いるので割愛。

# ARM版のイメージ作成
今回使用した機器のCPUは、cortex-a15です。要は32bitのARMアーキテクチャですね。
開発機にはx86_64を使っている人が大半でしょうから、先に作ったDockerfileでbuildしたイメージは普通に考えたらQNAP上に持っていっても動かないわけです。
ということで、ARMアーキテクチャベースのイメージを元に、イメージを作り直します。

この辺りについては[こちらの記事](https://tech-blog.abeja.asia/entry/environment-of-building-docker-image-for-jetson)を参考にさせていただきました。"binfmt_misc のセットアップ" の所と "build" の箇所ですね。

## 1. ベースイメージの選択
上記の記事と基本的に同じ内容になってしまうのですが、見やすさの為に記述しておきます。

[multiarch](https://github.com/multiarch)というリポジトリで、qemu-user-staticが組み込み済みのイメージを色々と公開されています。
今回自分は[alpine](https://github.com/multiarch/alpine)を選択したので、そちらのディレクトリを開きます。

## 2. binfmt-supportの設定
Usageに書いてありますが、まずはbinfmt-supportの設定をdocker hostにするため、コマンドを実行。

```
$ docker run --rm --privileged multiarch/qemu-user-static:register --reset
```

## 3. build
続いて、同様にこちらで公開されいてるARM用のイメージを元にbuildします。このbuildについてはUsageには載っていませんが、先に触れた参考にさせてもらったblogでその様な事をしてますね。
DockerfileのFROMをこんな感じで書き換えてやります

```
- FROM python:3.8.2-alpine
+ FROM multiarch/alpine:armhf-edge
```

この例だと、とりあえず諸々Dockerfileを作り込む時は `python:3.8.2-alpine` で作っておいて、ARM版イメージを作るときは `multiarch/alpine:mrmhf-edge` に置き換えたということですね。
まあ、この例だと後者にpython周りをインストールするための設定が追加で必要になりますが。

ともあれ、buildします。

```
$ docker build . -f Dockerfile --tag 192.xxx.yyy.zzz:nnnn/my-private-image
```

tagには `(private registryのホスト:port)/(イメージ名)` の形で設定します。イメージ名はお好きなように。
これが無事に完了すればQNAP上で動くイメージの完成です。

## 4. insecure_registry
最初の方で見たとおり、private registryのURLはhttpとなってますので、pushする前にinsecure_registryの設定をします。
`/etc/docker/daemon.json` に下記のような設定を加えます。

```
{
  "insecure-registries": ["192.xxx.yyy.zzz:nnnn"]
}
```

既に他の設定のオブジェクトがある場合は、そのオブジェクト内に追加してやる形で大丈夫です。

## 5. push for private registry
諸々準備ができたので、作成したイメージをprivate registryにpushします。

```
$ docker push 192.xxx.yyy.zzz:nnnn/my-private-image
```

こんな感じですね。

# 作成したコンテナの起動

## 1. pull
QNAPのContainer Stationに戻りまして左のメニューから「画像」を開きます。これは「image」を訳した結果、そうなってしまったんでしょうね…。要はイメージの管理ページがここです。
右上にある「プル」を開きます。
![04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/53dfb588-2124-12d5-9c36-cb37b4a77aa4.png)

pullしてくる対象のレジストリを選択出来るようになっているので、ここでprivate registryを追加します
![05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/01b11d0b-0bcd-010c-7910-a817b1a330d2.png)

名前とURLを記入します。ユーザー名とパスワードについては特に認証とかつけてないので、今回は不要です。
![06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/69fc453f-0a00-a266-9f18-3b1a32cc8ba2.png)

追加したら、レジストリをprivate registryに設定し、画像名（イメージ名）を入力します。先の例でいくと、 `my-private-image` ですね。
![09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/e23d7a05-e474-08e3-3f1b-09e83a44546b.png)

右上のバックグラウンドタスクが終われば、pullは完了です。
![07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/c75b8e04-f838-0f8c-a81c-e73d3c20d82f.png)

## 2. コンテナの作成
メニューの「作成」から検索しても出来ますが、よりお手軽な方法として、pullしたイメージのアクション列にある「＋」ボタンからもコンテナを作成できます。
![08.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33502/f076c2bd-5eb6-3026-5f56-05f320cff0aa.png)

ホストとボリュームを共有したい場合などの設定は、詳細設定からできるようになっています。

概要ページに戻って、無事に起動されていれば完了です。

# 今後の課題
とりあえず最初の要件は満たせましたので、次はホストとコンテナとの共有フォルダをどうにかしてNASユーザーのディレクトリにすることですかね。
あと、もっとスマートな方法があればそちらに切り替えるとか。
ひとまずはこれで好き勝手出来そうなので、色々動かしてみようかと。

binfmt_misc辺りがちゃんとわかってないので、そこら辺を理解しておく。

# 後記
書き終わってから気づいたんですが、無理にx86_64の開発環境でbuildしなくても、QNAPにsshでログインして、そこでbuildすれば普通にARM環境でそのままbuild出来たんじゃないだろうか。dockerも既に入っている訳だし。
多分、これが今回の目的では一番楽な方法だった気がする。