Azure Container RegistryへDockerイメージを登録する

Dockerのイメージを登録・管理できるAzure Container Registryを使ってみたので手順をまとめます。

流れは次の通りです。

  1. Docker for Windowsをインストールする
  2. Azure Container Registryでレジストリを作成する
  3. WindowsでDockerイメージを作成する
  4. Container Registryへ作成したDockerイメージを登録する

PCはWindows 10 Pro (64bit)です。

※注意:記事作成時点ではAzure Conteiner Registryに登録したDockerイメージを削除できないようです。

Docker for Windowsのインストー

Docker for WindowsHyper-Vを使うのでWindows 10(64bit)のProfessionalエディションなどが必要(https://docs.docker.com/docker-for-windows/install/#what-to-know-before-you-install)ですが、Docker Toolbox(https://docs.docker.com/toolbox/overview/)を使えばその他WindowsでもDockerを使えるようです。

インストールはDocker公式ページのドキュメントに従って行います。

Install Docker for Windows | Docker Documentation

Docker for WindowsにはStableチャンネルやEdgeチャンネルがあるようですが、今回はStableチャンネルのインストーラーをダウンロードしてインストールしました。

インストーラーの指示に従ってインストールをした後、Hyper-Vが無効の状態の場合はDockerを起動するとダイアログが表示されるようです。

f:id:LocaQ:20170528230819p:plain:w500

ダイアログに書かれているようにHyper-Vを有効にするとVirtualBoxが使えなくなります。それで問題なければOKボタンをクリックするとHyper-Vが有効になりPCが再起動します。

再起動したらdockerコマンドが使えるか確認します。

コマンドプロンプトPowershellを開いて次のコマンドを実行します。

> docker --version
Docker version 17.03.1-ce, build c6d412e
> docker-compose --version
docker-compose version 1.11.2, build f963d76f
> docker-machine --version
docker-machine.exe version 0.10.0, build 76ed2a6

またはVisual Studio Codeで端末ウィンドウを開いても確認できます。

f:id:LocaQ:20170528231251p:plain:w600

各コマンドでバージョンが表示されればOKです。

コンテナーレジストリの作成

Azure Container Registryのドキュメントの手順に沿って作成します。

プライベート Docker レジストリの作成 - Azure Portal | Microsoft Docs

  1. Azure Portalを開く
  2. Marketplaceで「Azure コンテナー レジストリ」を検索する
  3. 発行元がMicrosoftの[Azure コンテナー レジストリ」を選択する
  4. [作成]をクリックする
  5. コンテナーレジストリ名などを入力して[作成]をクリックする

f:id:LocaQ:20170528230512p:plain:w350

レジストリ名には英数字しか使えないようです。

また、ここで管理ユーザーを有効にするとdockerコマンドでContainer Registryへログインする時に、ユーザー名にレジストリ名を、パスワードにアクセスキーを使えるようになります。今回はPCで作成したイメージをdockerコマンドでContainer Registryに登録したいので有効にします。

Dockerイメージの作成

Dockerイメージを作成するにはDockerfileが必要ですが、MonoをインストールしたUbuntuのコンテナを作成するDockerfileが既にあるのでそれを例に使います。Dockerfileの内容は次の通り。

FROM ubuntu:xenial-20161010
RUN apt-get update
RUN apt-get install -y mono-complete

任意のフォルダにこのDockerfileを保存します。

次はコマンドプロンプトまたはPowershellを開き、Dockerfileを保存したフォルダに移動後、Dockerイメージをビルドします。

> cd [Dockerfileのあるフォルダ]
> docker build -t [レジストリ名].azurecr.io/mono .

[レジストリ名]はContainer Registryを作成したときに指定した名前です。"-t"オプションの値は一定のフォーマットでなければなりません(次の章で説明します)。また、最後に" .“(ピリオドの前に空白あり)があります。

ビルドが終わったらイメージが作成できているか確認します。

> docker images
REPOSITORY                        TAG       IMAGE ID        CREATED        SIZE
[レジストリ名].azurecr.io/mono    latest    a5c78a372b93    6 hours ago    747 MB

Container RegistryへのDockerイメージの登録

Dockerイメージのリポジトリ名のフォーマット

Dockerイメージのリポジトリ名は次のフォーマットになっている必要があります。

[レジストリ名].azurecr.io/[Dockerイメージ名]

[Dockerイメージ名]は名前空間付きDockerイメージの名前です。名前空間はDockerイメージが属するグループのことで、"/“で区切って複数レベルの階層を構成できます。詳しくは次のドキュメントの[主な概念]のリポジトリとイメージを参照してください。

Azure のプライベート Docker コンテナー レジストリ | Microsoft Docs

“docker build"の時の”-t"オプションに指定した値はこのフォーマットになっています。

もし上記のフォーマットになっていなかったり、名前を変えたい場合はdockerコマンドで変更できます。

> docker tag [現在のリポジトリ名] [新しいリポジトリ名]

Container Registryへの登録

Container RegistryへのDockerイメージの登録は次のドキュメントを参考にします。

Docker イメージをプライベート Azure レジストリにプッシュする | Microsoft Docs

まずはdockerコマンドでContainer Registryへログインします。

> docker login [レジストリ名].azurecr.io/ -u [ユーザー名] -p [パスワード]
Login Succeeded

上記ドキュメントではAzure Active DirectoryのサービスプリンシパルというもののIDとパスワードを使っていますが、Container Registry作成時に管理ユーザーを有効にしているので別途ユーザーとパスワードが作成されています。そのユーザーとパスワードは、

  1. Azure Portalを開く
  2. 作成したContainer Registoryを選択
  3. [アクセスキー]をクリックする

で確認できます。

f:id:LocaQ:20170529003751p:plain:w600

ログイン後、Container RegistryへDockerイメージをプッシュします。

> docker push [レジストリ名].azurecr.io/mono
The push refers to a repository [[レジストリ名].azurecr.io/mono]
...
latest: digest: sha256:6e9a312338c88dcfb10fede48e5f0ff0d423ff15ed387510842d2945cd3633c9 size: 1782

プッシュが終わったら、

  1. Azure Portal
  2. 作成したContainer Registoryを選択
  3. [リポジトリ]をクリック

と操作してプッシュしたDockerイメージが表示されるか確認します。

f:id:LocaQ:20170529003247p:plain:w400

リポジトリ一覧に"mono"があれば登録ができています。

3Dプリンタでボックス止めを作った

洗面所にバスタオルを入れてるボックスがあるんですが、引き出すと滑って前に出てくる上に落下して不便でした。で、せっかく3Dプリンタがあるので固定具を作ってみました。

f:id:LocaQ:20170220221949j:plain:w400

Fusion360モデリング3Dプリンタで試作を2回くらいして形が決まったものがこれです。

f:id:LocaQ:20170220224759p:plain:w370

これを4組み分作ります。2枚目の手前の2列の部品が3つずつなのは試作で既に1つずつ出来てるためです。

f:id:LocaQ:20170220220938p:plain:w400 f:id:LocaQ:20170220221008j:plain:w400 f:id:LocaQ:20170220221633j:plain:w400

3Dプリンタで印刷してサポートを取り、ミニルーターでバリを取りました。

f:id:LocaQ:20170220221937j:plain:w400

これをボックスの手前下側と奥の上側にはめ込みます。

f:id:LocaQ:20170220222003j:plain:w400 f:id:LocaQ:20170220222015j:plain:w400

これでバスタオルを出す時に引き出しを目いっぱい出しても滑ることも落ちることも無くなりました。

f:id:LocaQ:20170220222024j:plain:w400

形を考えるのとモデリングが15~20分、印刷が8時間(試作を除く)くらいでした。印刷は朝に始めて仕事に言ったので8時間でも長く感じません。こういう部品が簡単に作れるのが3Dプリンタの面白いところです。

ダヴィンチMini wの印刷精度を検証

ダヴィンチMini wで印刷したネジ穴の直径がちょっと小さい気がしたのでどの程度の正確に印刷できるのか検証してみました。

下は検証に使う3Dモデルで、左上が水平な穴が開いたモデル、左下が正方形の面を押し出したモデル、右が垂直な穴が開いたモデルです。

f:id:LocaQ:20170210235129p:plain:w500

この3つのモデルを印刷してノギスで実寸を測ります。印刷設定は次の通りです。

項目
品質 非常に良い
材料 PLA
ラフト なし
底辺 なし
サポート なし
内部充填密度 中(30%)
インフィルタイプ 格子
シェル 普通
レイヤの高さ 0.1
印刷速度 普通

水平な穴のサイズ

印刷したものと各穴のモデル上のサイズです。

f:id:LocaQ:20170211123334j:plain:w500

この穴の直径の実寸は次のようになりました。

モデルの直径(mm) 直径の実寸(mm) 誤差(mm)
0.5 - -
1.0 - -
1.5 - -
2.0 1.7 -0.3
2.5 2.2 -0.3
3.0 2.7 -0.3
3.5 3.2 -0.3
4.0 3.8 -0.2
4.5 4.2 -0.3
5.0 4.8 -0.2
5.5 5.1 -0.4
6.0 5.7 -0.3
6.5 6.2 -0.3
7.0 6.8 -0.2
7.5 7.3 -0.2

水平な穴を空けるとだいたい0.2~0.3mmほど直径が小さくなるようです。0.5mmの穴は完全に埋まっています。1.0mmと1.5mmの穴はほぼ埋まっていて直径を計測できませんでしたが一応表から裏までの穴は開いていたので、ピンバイスで穴を空けることができます。また、穴は見た目真円ではなくちょっと歪です。

正方形のサイズ

印刷したものと各直方体のモデル上のサイズです。バリがあって真上からの写真だと小さいサイズが分かりにくいので斜めからの写真も載せます。

f:id:LocaQ:20170209205745j:plain:w500 f:id:LocaQ:20170209210038j:plain:w500

各直方体の縦と横の長さの実寸は次のようになりました。

モデルの1辺の長さ(mm) 縦の実寸(mm) 横の実寸(mm) 縦の誤差(mm) 横の誤差(mm)
0.5 0.8 - +0.3 -
1.0 1.1 1.1 +0.1 +0.1
1.5 1.5 1.5 0.0 0.0
2.0 2.1 2.2 +0.1 +0.2
2.5 2.6 2.6 +0.1 +0.1
3.0 3.0 3.0 0.0 0.0
3.5 3.5 3.6 0.0 +0.1
4.0 4.0 4.0 0.0 0.0
4.5 4.5 4.6 0.0 +0.1
5.0 5.0 5.1 0.0 +0.1
5.5 5.5 5.5 0.0 0.0
6.0 6.1 6.1 +0.1 +0.1
6.5 6.5 6.6 0.0 +0.1
7.0 7.0 7.1 0.0 +0.1
7.5 7.4 7.5 -0.1 0.0

誤差の範囲は-0.1mm~+0.3mmですがほぼ0.0mm~+0.1mmの範囲に収まっています。円よりも正確に印刷できるようです。0.5mm四方のものはバリと太さがほぼ一緒のためあまり正確に計測できません。一応直方体部分も印刷されているのでバリが出なければこのサイズでも印刷できそうです。

垂直な穴のサイズ

印刷したものと各直方体のモデル上のサイズです。印刷時は2枚目のように立てた状態になっています。

f:id:LocaQ:20170209234110j:plain:w500 f:id:LocaQ:20170209210253j:plain:w500

この穴の直径の実寸は次のようになりました。

モデルの直径(mm) 水平方向の直径の実寸(mm) 垂直方向の直径の実寸(mm) 水平方向の直径の誤差(mm) 垂直方向の直径の誤差(mm)
0.5 - - - -
1.0 - - - -
1.5 1.2 1.0 -0.3 -0.5
2.0 1.6 1.7 -0.4 -0.3
2.5 2.1 2.4 -0.4 -0.1
3.0 2.7 2.6 -0.3 -0.4
3.5 3.2 3.1 -0.3 -0.4
4.0 3.7 3.5 -0.3 -0.5
4.5 4.0 4.2 -0.5 -0.3
5.0 4.7 4.6 -0.3 -0.4
5.5 5.2 5.2 -0.3 -0.3
6.0 5.6 5.3 -0.4 -0.7
6.5 6.0 6.4 -0.5 -0.1
7.0 6.4 6.4 -0.6 -0.6
7.5 6.9 6.9 -0.6 -0.6

誤差は-0.7mm~-0.1mmと大きめでした。縦方向の穴をサポートなしで印刷しているので誤差が大きくなるのは当然ですが、意外なのは幅も誤差が大きいことです。高さは重力があるのでサポートがなければその影響を受けますが幅はサポートの有無や重力は影響しない(と思う)ので理由はよく分かりません。

ダヴィンチMini wを購入

Raspberry PiArduinoで作ったデバイスを納めるケースを作るために3Dプリンタを買ってみました。

買ったのはXYZプリンティング社のダヴィンチMini wでAmazonで41,000円、合わせてブラックとホワイトのフィラメントも約3,200円と約44,000円で購入しました。

https://jp.xyzprinting.com/jp_ja/Product/da-Vinci-Minijp.xyzprinting.com

組み立て&テスト印刷

ほぼできた状態で来ますが少しだけ組み立てが必要です。

f:id:LocaQ:20170122234218j:plain:w300

組み立てといっても最初に内部の固定材を取り、プリントモジュールとフィラメントを装着するだけですが、付属していた紙の組み立てマニュアルが白黒かつ粗い印刷で写真に何が写ってるか分からない状態だったので、少し苦労しつつ組み立てました。ただ後で気付いたんですが、XYZプリンティングのサイトからカラーのマニュアルをダウンロードできるので、先にダウンロードしておくといいと思います。一緒にXYZwareというアプリもダウンロードしてインストールしておきます。

組み立てが終わったら電源入れてUSBケーブルをPCに繋いでXYZwareを起動します。

f:id:LocaQ:20170123000518p:plain:w300

起動したらマニュアルに印刷の手順が書いてある(画面が実際と違ったりしますが)のでその通りにやってみます。

が、左上の"↓"というアイコンをクリックするとダイアログが表示されてサンプルデータが6つ表示されますが全て別のダヴィンチシリーズのプリンタ用のファイルらしく、開けますがダヴィンチMini wで印刷できません。意味が分からない。
[2017/1/31 追記]
XYZwareのメニューの設定ボタンをクリックするとダイアログが開き、そこの"プリンター"というタブにある"サンプルファイルを開く"というボタンがあります。そのボタンをクリックするとちゃんと印刷可能なデータがありました。

幸いXYZプリンティングのサイトにたくさんデータが公開されているので小さめの物を選んでダウンロードします。私はこれを選びました。

サンプルデータを開いたらフィラメントのロードを行ってから印刷をします。最初なので品質は普通(3つの内一番低い品質)にしました。

印刷中はそこそこ音がします。

だいたい15分くらいで出来上がりました。

f:id:LocaQ:20170123002351j:plain:w300 f:id:LocaQ:20170123002929j:plain:w300

文字の輪郭部分が所々崩れてたり全体が反ってたりしますが印刷品質設定を普通にしたからなのかは分かりません。質感は硬いプラスチックで手で折れないくらい硬く、重さは軽い感じです。

次は印刷品質を非常に良い、レイヤの高さ(層の厚さ)を最も薄い0.1mmに設定して印刷してみます。

f:id:LocaQ:20170123003855j:plain:w300

時間は約30分でさっきの倍の時間がかかりましたがさっきより文字の輪郭部分が崩れてます。層は確かに薄くなっていて、さらに全体的に角がしっかりしている(品質が普通のやつは角に少し丸みがある)ので、何か他の設定に原因があるのかもしれません。

Wifiの設定

ダヴィンチMini wにはWifi機能が付いているので設定してみましたが仕様がかなり不便です。

まずダヴィンチMini wのWifiの設定をするにはUSBケーブルをつなぐ必要があり、その状態でXYZwareからSSIDとパスワードを設定します。その後USBケーブルを抜ていもWifiで繋がっているので印刷ができます。

ただしWifiの設定はプリンタの電源を切ると消えてしまうようで、Wifi設定をした後に電源を抜いて移動させることができません。なのでPCとUSBケーブルがつながる範囲に設置することになります(もしかしたら別のノートPCでWifi設定をすれば離れた場所のPCから使えるかもしれませんが未検証です)。これが結構不便で、せめてスマホUSBメモリを使ってプリンタのWifi設定ができればWifi機能が活きるんじゃないかと思いました。

最後に

思ってたほどうまく印刷できなかったので色々検証する必要がありそうでした。

廊下の電灯を自動でOn / OffするデバイスのプログラムをF#で書き直した

前にRaspberry Piで動くデバイスのプログラムをF#で書き直した。

locaq.hatenablog.com

locaq.hatenablog.com

ソースコードは上の記事にリンクがあるのでそこから見られる。

理由

自分はどうも動的型付け言語は苦手みたいで中々モチベーションが湧かなくて静的型付け言語で書き直したくなったのが理由で、F#を選んだのは関数型言語を勉強したかったのと、Visual Studioで開発ができるから。

.NETからGPIOを扱うためのライブラリもいくつかあるので要求は今のところ満たせてる。

GitHub - locatw/WiringPi.Net: A simple C# wrapper for Gordon's WiringPi library.

raspberry-sharp (Raspberry#) · GitHub

Raspberry#はオブジェクト指向な設計になっていてC#と馴染む感じだけれど開発があまり活発でないのが気になる。raspberry-sharp-ioはPWMをまだサポートしていない(将来される予定らしい)ので自分がやりたいことができるか確認してから使うのがいい。raspberry-sharp-systemはRaspberry Piのモデルの種類やファームウェアのバージョンなんかのシステム情報が取得できるので、ライブラリを作るときに便利なんじゃないかと思う。

自分が作ったデバイスはサーボを動かすのにPWMを使っているので今回はWiringPi.Netを使った。ただ、こっちも開発がほぼ止まっていて(最近のissueに返信はあったけど)ビルドエラーが出て使えない状態だったので、フォークして修正したものを公開した。

Qiitaに記事を書いたので詳しくはそっちを参照。

qiita.com

感想

GPIOなんかのRaspberry Piに依存する部分以外はWindowsで実行できるので、Intellisenseやデバッグが快適で気に入ってる。(PythonVisual Studio用の拡張があって状況は同じはずなんだけど、いまいちうまく動かなくてあまり快適ではなかった。)

気になるのは、数あるセンサーを使うときに.NET用のライブラリが提供されるのは少なそうなところ。C言語用のライブラリがあればラッパーを書けるので.NETからでも使えるけど、ラッパーを書く分の手間はかかるので、そこはPythonとかの方が有利かなぁと思う。

あと、F#はまだ身についたわけではないから正しいか分からないけれど、デバイス用のプログラムを書くのに適しているかというと内容によるかなーという感じ。デバイスの状態を扱うならオブジェクト指向言語の方が適しているかもしれない。ただ、F#でも当然状態は扱える(クラスも書ける)し、関数型言語はロジックを書くのに適してる(と現時点では思ってる)ので、その比重が高くなれば特徴が生かせるんじゃないかと思う。

とはいえF#とC#だったらできないことの差はないので好きな方を使うのが一番快適だと思う。

それとPythonについては自分は使うのをやめることにしたけど、言語の優劣ではなく自分との相性と開発環境周りが理由なのでPython好きな人は気を悪くしないでほしい。自分でもこんなに相性や開発環境の影響があるとは思ってなかったのでびっくりしてる。

今後

F#で書き直したので今度はAzureのIoT Hubを使ってみようかと思って今勉強中&構成を考えてる。Azureなので.NET系言語との相性は良さそう。