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公式のイメージが見つかると思います。
今回は特にこだわりとかもないので、これを単純な形で使います。検索したところはこんな感じですね。

このイメージをインストールして起動すると、こんな感じで「概要」ページに表示されます。

上のスクリーンショットで黄色でマークしてあるコンテナ名をクリックすると、private registryのURLとポートが表示されます。
後ほど開発環境で作成したイメージをここにpushすることになります。

独自イメージの作成

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

ARM版のイメージ作成

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

この辺りについてはこちらの記事を参考にさせていただきました。"binfmt_misc のセットアップ" の所と "build" の箇所ですね。

1. ベースイメージの選択

上記の記事と基本的に同じ内容になってしまうのですが、見やすさの為に記述しておきます。

multiarchというリポジトリで、qemu-user-staticが組み込み済みのイメージを色々と公開されています。
今回自分は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」を訳した結果、そうなってしまったんでしょうね…。要はイメージの管理ページがここです。
右上にある「プル」を開きます。

pullしてくる対象のレジストリを選択出来るようになっているので、ここでprivate registryを追加します

名前とURLを記入します。ユーザー名とパスワードについては特に認証とかつけてないので、今回は不要です。

追加したら、レジストリをprivate registryに設定し、画像名(イメージ名)を入力します。先の例でいくと、 my-private-image ですね。

右上のバックグラウンドタスクが終われば、pullは完了です。

2. コンテナの作成

メニューの「作成」から検索しても出来ますが、よりお手軽な方法として、pullしたイメージのアクション列にある「+」ボタンからもコンテナを作成できます。

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

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

今後の課題

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

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

後記

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