Pixelaを使ってはてなブログにPV数の草を生やしてみた

今回のエントリの内容はメモレベルです。

去年のMashupAwards2018で出た作品でFesta(最後のイベント)に参加したときに、githubのような感じででコミットの状態を出すサービスでPixelaというものがあるということを知りました。そのときはおもしろいなと思ってましたが、自分にはあんまり関係ないのかな~という感じでみていました。

ただ、少し前まで使用していた、ブログのPV数をTwitterでつぶやいてくれるサービスがうまく動作してない(多分https化したときに設定が変わったから?)という状況と、最近はTwitterのタイムラインを見る機会がそれほど多くなくなってきたということもあるので、別の手段でなんか見れないかなと思っていました。

んで、ググってみたところPixelaの作者さんのエントリーに当たりました。

pixe.la

blog.a-know.me

このやり方をそのまま進めれば問題ないのですが、設定していたところちょっと躓いたのでメモ。 上記の2つのエントリーを読んでについて書いています。

  1. ユーザの登録
  2. グラフデータの作成の仕方
  3. はてなブログへの貼付け方法

ただ、設定してブログに貼り付けたあとPV数の更新(カウントアップ)がされない状況になります。これだけではなにかが足りないような感じです。グラフの生成はされているので、外部にカウント機能を持った何かが必要なのかなと思っていたのですが、以下のエントリを読み込んでみてわかりました。

blog.a-know.me

ここで、これまでの Pixela を知っている人向けの説明として、今回のバージョンアップで selfSufficient というフィールドが指定できるようになっています。直訳すると自給自足。これはつまり、グラフが見られるごとに自分自身を加算(もしくは減算)していく、ということを指定するための属性になります。

グラフの生成時のJSON"selfSufficient":"increment"のフィールドを追加することでグラフへアクセスするたびにカウントできるということです。これを指定すれば問題は解決します。

ただサンプルにあるコマンド例がcurlのため、Windowsではかなり不安ですw。

そこで作者の方が別途作成されたpiというCLIツールを使用することにします。ここまでやると別途curlをインストールしてもいいんですけどね。

blog.a-know.me

まずはこちらからダウンロードします。 Windows処理系なのでリスト中からpi_v1.0.1_windows_amd64.zipを選んでダウンロードします。 Windows処理系なのでリスト中からpi_v1.0.2_windows_amd64.zipを選んでダウンロードします。 アーカイブを展開するとこんな感じになるので、テキトーな場所に展開します。

f:id:ueponx:20190421182625p:plain

実はこのままだとうまくいかないです。 実行ファイルのpiに拡張子がないので実行しようとしても失敗します。リネームしてpi.exeにします。 念の為githubで作者の方にissueを投げたところ、version 1.0.2にバージョンアップして対応していただきました。超感謝! これで準備完了です。

あとは事前に以下を決めておきます。

  • ユーザーネーム
  • アクセスに必要なAPIトーク
  • グラフ名(URLで使用)
  • グラフ名(人間識別用)

この実行ファイルはAPIトークンを環境変数で使用するのでユーザー登録をしたときのトークンは登録が成功したら環境変数PIXELA_USER_TOKENに登録しておきましょう。

今回は以下の様に決める前提としようと思います。

設定項目 設定値
ユーザーネーム hogepon
APIトーク fuga2019
グラフ名(URLで使用) hatena-pv
グラフ名(人間識別用) "HatenaPV graph"

これを使って実行していきます。

> pi users create --username hogepon --token fuga2019 --agree-terms-of-service yes --not-minor yes
> set PIXELA_USER_TOKEN=fuga2019
> pi graphs create -u hogepon -g hatena-pv -n "HatenaPV graph" -i view -t int -c shibafu -z "Asia/Tokyo" -s increment

f:id:ueponx:20190421143451p:plain

piコマンドは成功すると以下の様なJSONが帰ってくるので判断に使用します。

{"message":"Success.","isSuccess":true}

上記のコマンドが成功すると以下のURLでグラフの状況を見ることができます。 ユーザー名、グラフ名が自分のものになっているかを確認しましょう!

https://pixe.la/v1/users/hogepon/graphs/hatena-pv.html

f:id:ueponx:20190421143749p:plain

これでOKです。

リロードするとちゃんとカウントアップできました。

f:id:ueponx:20190421144231p:plain

あとは

blog.a-know.me

上記のブログ通りに設定すれば問題ありません。あとは引っかかるところはほとんどありませんが、 テストで使用しているURLは作者さんのページなので自分のグラフのURLに書き換えましょう。

おわりに

今回はちょっと引っかかった部分があったのでやってみましたが、REST API経由でこういうグラフが出せるのは便利かも。あとカウンタの値がページ描画完了してからのカウントになっているのではてなブログのアクセスカウンターよりも少なく表示されています。多分、ちゃんとページロードが走った部分だけがカウントされているからだと推測。はてなさんのアクセス数はGoogleさんのBots経由のアクセスも含まれているのかもしれませんね。

以下が設定して配置した結果です。

f:id:ueponx:20190421145502p:plain

これからの草生え具合を楽しみにします。

RaspberryPi3にWindows10 ARM版をインストールする【インストール編】(2019/04/12現在)

前回のエントリに引き続きRaspberryPi3にWindows10 ARM版をインストールするということでやっていこうと思います。 前回のエントリではMicroSDカードメモリにインストールイメージを作成するところまでを行いました。

【前回のエントリ】

uepon.hatenadiary.com

今回のエントリではそのMicroSDカードメモリをRaspberryPi3に挿して起動し、Windows10のARM版を立ち上げる部分となります。 わりとバギーなものなので、なぜそうなるのかということよりも、うまく行った方法みたいなことになりますので、ご注意ください。 うまく行かなかった点もそのうち治ると思いますよw

起動→UEFIっぽい部分

MicroSDカードメモリをRaspberryPi3に挿入します。今回使用したのはRaspberryPi3 Bになります。最近はB+も出ていますが、多分どちらでも大きくは変わらないのではと思います。

起動するとRaspberryPiのロゴが大きくでプログレスバーがその下に出てきます。

f:id:ueponx:20190414080121j:plain

そのままにしているとUEFIのシェルモード画面になってしまいます。

f:id:ueponx:20190414080129j:plain

ロゴが出ているうちに【ESC】キーを押してメニューモードに入りましょう。2019/04/17追記:UEFIのシェルモード画面になった場合にはexitと入力すればメニューモードに行けるようです。このような画面になります。BIOSのような画面のような感じです。

f:id:ueponx:20190414080137j:plain

ここまで来たらBootの順番などの設定を行っていきます。まずは【Boot Maintenance Manager】にカーソルをあわせて【Enter】キーを押して設定を行っていきます。

f:id:ueponx:20190414080145j:plain

Boot Maintenance Managerの画面になったら【Boot Options】を選択し、【Enter】キーを押して進みます。

f:id:ueponx:20190414080154j:plain

Boot Optionsの画面になったら【Change Boot Order】を選択し、【Enter】キーを押して進みます。

f:id:ueponx:20190414080201j:plain

Change Boot Orderの画面にくると【Change the order】で<UEFI Shell>`<SD/MMC on Broadcom SDHOST>にカーソルが来ていると思うので、そのまま【Enter】キーを押します。

f:id:ueponx:20190414080210j:plain

以下のような画面になったら、【UEFI Shell】にカーソルが当たっている状況で【-(マイナス)】キーを押して

f:id:ueponx:20190414080218j:plain

以下のように【SD/MMC on Broadcom SDHOST】(上)と【UEFI Shell】(下)に変化させます。

f:id:ueponx:20190414080237j:plain

設定が終わったら【ESC】キーを押してメニューに戻ります。

f:id:ueponx:20190414080244j:plain

設定を変更したので【Commit Changes and Exit】にカーソルを移動させて【Enter】キーを押します。

f:id:ueponx:20190414080252j:plain

すると、Boot Optionsの画面に戻ります。そのまま、【Go Back To Main Page】にカーソルを合わせて、【Enter】キーを押します。

f:id:ueponx:20190414080302j:plain

Boot Maintenance Managerの画面に戻ります。そのまま、【ESC】キーを押してメインメニューに戻ります。

f:id:ueponx:20190414080310j:plain

メインメニューに来たら今度はカーソルを【Boot Manager】に合わせて【Enter】キーを押します。

f:id:ueponx:20190414080328j:plain

※注意この操作をするとSDカードから起動を行います。

Boot Managerの画面に遷移したら、【SD/MMC on Broadcom SDHOST】にカーソルを合わせて【Enter】キーを押します。これでRaspberryPiは再起動され、Windows10のインストール処理を開始しますので注意してください。

f:id:ueponx:20190414080343j:plain

Windows10のインストール処理

再起動が行われるとWindows10のロゴが表示されインストール処理が開始されます。ここからも時間がかかる処理が多いので30分ぐらいかかると思っていてください。

f:id:ueponx:20190414080353j:plain

時間が経つと以下のような画面になります。住んでいる地域の設定になります。今回はデフォルトだった【日本】にカーソルを合わせて【はい】ボタンをクリックします。(ここからはマウス操作はできます。)

まずはWindows10のインストール作業が進んだということで一安心となるのですが…

f:id:ueponx:20190414080519j:plain

問題が発生しましたと表示されます。画面上にはやり直すことも、今はスキップすることもできます。という優しい言葉が表示されますが、何度【やり直す」ボタンをクリックしても同じ画面にいきつきます。ですので、【スキップ】ボタンをクリックして処理を進めていきます。

OOBEKEYBOARDと表示されているのでキーボードの認識関連でコケているのだと推測。その後の設定でもキーボードが英語キーボードの配列になっているので注意です。

ここで脱落する人もいるかもという罠その1

f:id:ueponx:20190414080528j:plain

そのあと、ネットワークに接続していなければ有線ネットワークの設定などを行う画面が入ったりしますが、事前にEthernetケーブルを指しておけば、セットアップは何もしなくても継続してくれます。

f:id:ueponx:20190414080536j:plain

処理中に、またもや問題が発生しましたと表示されます。OOBEEULAとかかれていますが、こちらは内容がよくわかりませんが、やり直すことができます。と書かれていますというか【やり直す】ボタンしかないので、これをクリックして進めていきます。

f:id:ueponx:20190414080545j:plain

そのまま処理は進めていけました。

f:id:ueponx:20190414080600j:plain

少し時間が経つとWindows10の使用許諾契約の画面が表示されます。【同意】ボタンをクリックします。

f:id:ueponx:20190414080608j:plain

設定する方法を指定してください。と画面に出るので今回は個人用に設定を選び

f:id:ueponx:20190414080615j:plain

【次へ】ボタンをクリックしました。

f:id:ueponx:20190414080624j:plain

Microsoftアカウントでサインインという画面に来ます。 もうこれで大丈夫そうだなという空気が漂います。 アカウントのメールアドレスを入力します。先程もいいましたがキーボードの配列がJISではないので気をつけて入力してください。入力が終わったら【次へ】ボタンをクリックします。

f:id:ueponx:20190414081205j:plain

続いてはパスワードを入力します。入力後に【次へ】ボタンをクリックします。

f:id:ueponx:20190414081251j:plain

するとまたインストール処理が進みます。

f:id:ueponx:20190414081334j:plain

少しすると今度はPINの設定処理になります。ここはスキップはできないようですね…

f:id:ueponx:20190414081359j:plain

好きなものをPINにして処理を進めましょう。入力できたら【OK】ボタンをクリックします。

f:id:ueponx:20190414081421j:plain

アクティビティの履歴を利用してデバイス感でより多くのことを行うという画面が表示されます。ここでは【いいえ】を選択しました。

f:id:ueponx:20190414081453j:plain

AndroidまたはiPhoneをこのPCにリンクするという画面になります。ここは画面左下の【後で処理する】をクリックしてスキップを行います。

f:id:ueponx:20190414081501j:plain

OneDriveの設定になりますが、SDカードの容量などもあるのでこのあたりはやめて画面左下の【このPCにのみファイルを保存する】をクリックしてスキップをしました。

f:id:ueponx:20190414081511j:plain

デジタルアシスタントを利用する画面が表示されます。もうそろそろ完了しそうな雰囲気ですね! 基本的にはデジタルアシスタントはスキップする項目なので【拒否】をクリックして選択するのですが、

f:id:ueponx:20190414081525j:plain

問題が発生しました。(エラーはOOBESETTINGS)となります。やり直すことができますと表示されますが、何度やってもこの画面に戻ってきます。(※でも何度かやることが重要のようです)しかたないので、画面犠打理上の【←(左矢印)】ボタンをクリックして一手順戻します。

f:id:ueponx:20190414081533j:plain

するとデジタルアシスタントを利用する画面に戻ります。今度は【同意】ボタンをクリックします。

f:id:ueponx:20190414081542j:plain

すると、デバイスのプライバシー設定の選択に画面が遷移します。 初回から【同意】ボタンをクリックして進めても実は問題が発生しました。(エラーはOOBESETTINGS)が表示されます。何回か、このエラー画面を表示させて、その後手順を戻さないと何故か進められなかったようです。

ここが結構わかりにくいハマりポイントでした。

ここでは適切に設定して貰もらって、【同意】ボタンをクリックします。(結局同意にしないと進められないということです)

f:id:ueponx:20190414081550j:plain

クリックすると処理が進みます。

f:id:ueponx:20190414081557j:plain

そして、画面の解像度がアップして全画面モードになります!漸くWindowsの設定が完了した様子です。

f:id:ueponx:20190414081605j:plain

数分かかるらしい…

f:id:ueponx:20190414081614j:plain

いよいよインストールが終わりそうです!

f:id:ueponx:20190414081622j:plain

予想より長いらしい…こんな表示初めてみました!

f:id:ueponx:20190414081632j:plain

やっと起動しました!(45分弱経っていたようです)

f:id:ueponx:20190414081640j:plain

Edgeの画面がでるのですが、真っ白。ネットワークの設定が画面右からニューっと出てくるのでその設定をしたら

f:id:ueponx:20190414081650j:plain

Edge言語設定ダイアログが表示されました。

f:id:ueponx:20190414081700j:plain

プルダウンから【日本語】の設定にして、【Get Start】ボタンをクリックします。

f:id:ueponx:20190414081709j:plain

無事に起動できたようです。

f:id:ueponx:20190414081717j:plain

インストールの情報に関して

画面のキャプチャなども通常のWindows同様にできるようなのでやってみました。スピードに関しては全く実用的ではありませんが、Webの閲覧もかなり我慢すればできなくはないと行ったところです。

f:id:ueponx:20190414081924p:plain

コンピュータの情報のキャプチャもとってみました。

f:id:ueponx:20190414081939p:plain

ちゃんとARMベースのプロセッサになっています!

おわりに

なんとかRaspberryPi3にWindows10のARM版をインストールできました。 動作が遅いのはPC資源としては非力なので致し方ないです。ですが、この大きさのものでWindows10も動くのだな~という点では関心しました。

パフォーマンスのチェックはしませんでしたが、一番のネックはストレージでしょうか。 CPUのパワーも100%に近い状態ではありましたが、クロックを600MHzからもう少し上げることができるので、熱対策を行ってそれを行えば割とまだありかな? ストレージに関してはもう100%から下がることはほとんどなかったです。

RaspberryPi 3B+モデルではUSBストレージからの起動もデフォルトで可能なのでSSDUSBメモリなどを接続(電源的な辛さもありそう)すればもう少し動作の改善がみられるかなと思いました。

残りの課題としてはノートPCのVisual Studioで作成したARM処理系のプログラムが動くのかに関しては後日調べてみたいです。

でも最後のトラップは普通だとあきらめるよなあ…

RaspberryPi3にWindows10 ARM版をインストールする【準備編】(2019/04/12現在)

RaspberryPiにWindows10 ARM版がインストールできたという話題が2019年の2月頃にネットに出ていました。

gigazine.net

いよいよ、IoTCoreではなく、通常のWindows10も動作するようになったのか!ということで自分も以前から何回か試していたのですが、 全くインストーラーがブルースクリーンから進行せず。SDカードの相性のことも聞こえてきたのでそのときは諦めることにしました。

最近、Facebookのコミュニティでうまくインストールできた方がいらっしゃってうまく行ったMicroSDカードメモリを教えていただいたので再度チャレンジを行いました。 自分みたいに知りたい方もいるかなと思いますので、自分がうまく行った方法論を記録します。この他の方法で成功するかはわかりませんが自分の成功した 手順だけを記録しておきます。自分も5回ぐらい失敗してわかった感じなので。うまく行かなくても責任は持てません。

あと、全部やろうとすると3-4時間ぐらいかかると思いますのでご注意ください。

自分は以下のエントリーを参考にしています。(最初の記事が出た2月の時点からツールなどの情報が変わっているので注意

【参考】 qiita.com

qiita.com

【2019/04/17追記】 ツールがバージョンアップしたので以下からダウンロードすると以下の手順がほぼなくなるようです github.com


MicroSDカードメモリにインストールイメージを生成する

準備編ではMicroSDカードメモリにインストールイメージを生成するところを行います。この時点ではSDカードの相性などは存在しません。

Facebookで紹介されたMicroSDカードメモリを使用しています。A1仕様のカードでないとインストーラーが起動した段階でブルースクリーンが連発すると思います(多分リードのタイムアウトが原因だと思います。)インストール後はサイズとしては16Gぐらい必要なるようなので、32Gぐらいのサイズでもいいと思いますが、今回は64Gのものを使用しています。SDカードメモリの規格もうすこし少なくならんものなんでしょうかね…

必要になるものとしては

【ハードウエア】

  • RaspberryPi 3B/B+
  • MicroSDカードメモリ

【ソフトウエア】

となります。

Windows on Raspberry imagerのダウンロード

MicroSDカードメモリに、インストールイメージを作成するのがWindows on Raspberry imagerになります。以下のページからダウンロードをします。

https://www.worproject.ml/

ダウンロードページはこちら

こちらのページにも必要なものはかいてありますのでチェックしましょう。 Windows on Raspberry imagerの実行にはbuild 15063以降が必要のようです。

ダウンロードが終わったら、展開しておきます。

f:id:ueponx:20190414135259p:plain

Windows 10 ARM64イメージの取得

つづいては使用するWindows10 のARM64イメージをダウンロードします。以下のサイトから選択すると、ISOイメージを取得するcmdファイルがダウンロードできます。 このcmdファイルを実行することになります。

uup.rg-adguard.net

リンクを開くと以下のような画面になります。

f:id:ueponx:20190414142333p:plain

今回は以下のパラメータで設定しました。

  • Select type: Cumulative Update for Windows 10
  • Select version: [18362.53]2019-04 Cumulative Update for Windows 10 Version 1903 for arm64-based System[arm64]
  • Select language: ja-jp: Japanese
  • Select edition: Windows 10 Professional
  • Select type download: Download ISO complier in OneClick!(run downloaded CMD-file)

パラメーターが設定されると画面の右にダウンロードリンクが表示されるのでそれをクリックします。

f:id:ueponx:20190414144840p:plain

今回はこんな感じのファイル名がでててくるのでこれをダウンロードします。ダウンロードしたらイメージ作成用のフォルダに保存します。

creatingISO_18362.53_ja-jp_arm64_professional.cmd

このcmdファイルを実行するとcmdウインドウが開きます。

f:id:ueponx:20190414150026p:plain

f:id:ueponx:20190414154916p:plain

実行が完了するとPress any key to exit.が表示されるのでウインドウが閉じます。(40分ぐらいかかります) cmdファイルの保存されているフォルダにISOファイルができていると思います。(他にもフォルダができていると思いますが問題有りません)

f:id:ueponx:20190414155033p:plain

これでWindows 10 ARM64イメージの準備はOKです。

Raspberry Pi用のTiano Core UEFIファームウェアの取得

以下のGithubリンクからダウンロードをします。(gitコマンドからも取得できます)

github.com

f:id:ueponx:20190414153704p:plain

こんな感じでZipファイル展開しましょう。実際に使用するのはこのアーカイブ内の RaspberryPiPkg-master\RaspberryPiPkg-master\Binary\prebuilt\2019Feb18-GCC5\DEBUG\RPI_EFI.fdファイルになります。(2019/04/12現在)

また後ほどツールから場所を指定することになります。

f:id:ueponx:20190414154429p:plain

これでRaspberry Pi用のTiano Core UEFIファームウェアの準備はOKです。

デバイスドライバを含むZIPアーカイブの取得

以下のリンクにドライバのアーカイブがあるのでダウンロードします。

https://www.worproject.ml/downloads

f:id:ueponx:20190414154806p:plain

このファイルはZIPファイルのままで大丈夫です。

f:id:ueponx:20190414155431p:plain


インストールイメージをMicroSDカードメモリに書き込む

イメージは先程準備したWindows on Raspberry imagerを使用して行います。 WoR.exeを起動します。

f:id:ueponx:20190414164027p:plain

起動すると以下ウインドウが開きます。言語設定もできるのですが、変えてもほとんどメッセージの内容が変わらないのでEnglishのままで進めます。 【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093904p:plain

【Select device】タブに移動します。ここでは書き込み先のMicroUSBカードメモリのドライブをしていします。予めPCに挿しておいてください。 選択して問題なければ、ウインドウの下部にチェックマークが付きます。【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093909p:plain

【Select image】タブに処理が移ります。ここでは使用するISOイメージを選択することになります。ここで先程ダウンロードしたISOファイル、 今回は18362.53.190401-1814.19H1_RELEASE_SVC_PROD1_CLIENTPRO_OEMRET_A64FRE_JA-JP.ISOが今回使用したISOファイルになります。(2019/04/12現在) 選択し、ウインドウ内にチェックマークがでたら【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093930p:plain

つづいて【Select drivers】タブに処理が移ります。ここではドライバがファイルを選択することになります。先程ダウンロードしたWoA64_Drivers_RPi3_20Feb19.zip(2019/04/12現在)を選択します。ウインドウ内にチェックマークがでたら【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093937p:plain

UEFI Firmware】タブに処理が移ります。ここでは先程準備したUEFIのファームウエアファイルを選択します。今回はアーカイブを展開した中からRaspberryPiPkg-master\RaspberryPiPkg-master\Binary\prebuilt\2019Feb18-GCC5\DEBUG\RPI_EFI.fd(2019/04/12現在)を選択します。この処理ではウインドウ内にチェックマークは 出てなかった感じです。【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093943p:plain

つづいては【Configuration】タブに処理が移ります。開始時点では以下のような画面になっています。ここは選択がいくつかあります細かく説明していきます。

f:id:ueponx:20190413093954p:plain

設定する項目は以下となります。

  • 【Install options】→【Partition scheme】:Master Boot Record(MBR)
  • 【Install options】→【Install image with】:Wimlib
  • 【Install options】→【Enable LZX install compression】:チェックを外す
  • 【WoR options】→【Save this configuration on exit】:ON

ここまで設定したら【Next】ボタンをクリックします。

f:id:ueponx:20190413094003p:plain

【Install】タブに処理が移り、最終確認の画面になります。再度、設定値の確認ができたら【Install】ボタンをクリックします。

f:id:ueponx:20190413094015p:plain

Install処理のプログレスバーが進んでいきます。完了するのに30分程度はかかると思います。

f:id:ueponx:20190413094024p:plain

終了するとThis installation has been finished!と表示されるので、

f:id:ueponx:20190413094044p:plain

【Finish】ボタンをクリックします。これでMicroSDカードメモリにインストーラーのイメージが書き込まれています。

おわりに

続いて実際にRaspberryPiにMicroSDカードメモリを挿入してWindows10をインストールさせていきます。これ以降が割とハマりポイントがあるので注意が必要です。

WebブラウザのGamepadAPIをつかってみる

前々から気になっていたのですが、最近あんまりネットで効かなくなったGamepadAPIを試してみます。

【公式情報】 w3c.github.io

公式のW3Cな情報でもいいのですが、Mozillaのサイトのほうが情報がわかりやすいので以下を参照しながらコーディングをしてみようと思います。

【参考】

developer.mozilla.org

参考をみるとこの様に書かれています。

Gamepad API は開発者とデザイナーに Gamepad やコントローラーへのアクセスを提供するものです。Gamepad API は Window オブジェクトにGamepadとコントローラー(以下、Gamepad)の状態を読み取る新しいイベントをいくつか追加します。

ではこれを見ながら最小限のコーディングをしていきます。

Webに公開できるようにGithubにUPしてみました。ここでもソースコードおいてみますのでご利用ください。

github.com

ソースコード

【index.html】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">

<style>
.buttons, .axes {
  padding: 1em;
}

.axis {
  min-width: 400px;
  margin: 1em;
}

.button {
  padding: 1em;
  border: 2px solid black;
  background-color: rgb(255, 255, 128);
}

.pressed {
  border: 2px solid black;
  background-color: red;
}
</style>
</head>
<body>
<h2 id="start">Gamepadを接続してなにかボタンを押すとスタートします。</h2>
<script type="text/javascript" src="gamepad.js"></script>
</body>
</html>

【gamepad.js】

var haveEvents = 'GamepadEvent' in window;
var controllers = {};
var rAF = window.requestAnimationFrame;

function connectHandler(e) {
    addGamepad(e.gamepad);
}
function addGamepad(gamepad) {
    // gamepadのArrayを作成
    controllers[gamepad.index] = gamepad;
    // HTMLへ接続されたGamepad毎の要素を追加(複数のgamepadにも対応)
    var d = document.createElement("div");
    d.setAttribute("id", "controller" + gamepad.index);//idはpadの番号がついた形式
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("接続Gamepad情報: "));
    d.appendChild(t);
    var info = document.createElement("h1");
    info.appendChild(document.createTextNode(gamepad.id));
    d.appendChild(info);

    //Gamepadコントロール要素(ボタンなど)表示部分
    var b = document.createElement("div");
    b.className = "buttons";
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("ボタンコントロール情報: "));
    b.appendChild(t);
    for (var i = 0; i < gamepad.buttons.length; i++) {
        var e = document.createElement("span");
        e.className = "button";
        //e.id = "b" + i;
        e.innerHTML = i;
        b.appendChild(e);
    }
    d.appendChild(b);

    //Gamepadコントロール要素(アナログジョイなど)表示部分
    var a = document.createElement("div");
    a.className = "axes";
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("アナログコントロール情報: "));
    a.appendChild(t);
    for (i = 0; i < gamepad.axes.length; i++) {
        c = document.createElement("h3");
        c.appendChild(document.createTextNode("axis" + i));
        a.appendChild(c);
        e = document.createElement("meter");
        e.className = "axis";
        //e.id = "a" + i;
        e.setAttribute("min", "-1");
        e.setAttribute("max", "1");
        e.setAttribute("value", "0");
        e.innerHTML = i;
        a.appendChild(e);
    }
    d.appendChild(a);
    document.getElementById("start").style.display = "none";
    document.body.appendChild(d);
    rAF(updateStatus);
}

function disconnectHandler(e) {
    removeGamepad(e.gamepad);
}

function removeGamepad(gamepad) {
    var d = document.getElementById("controller" + gamepad.index);
    document.body.removeChild(d);
    delete controllers[gamepad.index];
}

function updateStatus() {
    scanGamepads();
    for (j in controllers) {
        var controller = controllers[j];
        var d = document.getElementById("controller" + j);
        var buttons = d.getElementsByClassName("button");

        //ボタン情報の状態取得
        for (var i = 0; i < controller.buttons.length; i++) {
            var b = buttons[i];
            var val = controller.buttons[i];
            var pressed = val == 1.0;
            if (typeof (val) == "object") {
                pressed = val.pressed;
                val = val.value;
            }
            var pct = Math.round(val * 100) + "%";
            b.style.backgroundSize = pct + " " + pct;
            if (pressed) {
                b.className = "button pressed";
            } else {
                b.className = "button";
            }
        }

        //アナログコントロール情報の状態取得
        var axes = d.getElementsByClassName("axis");
        for (var i = 0; i < controller.axes.length; i++) {
            var a = axes[i];
            a.innerHTML = i + ": " + controller.axes[i].toFixed(4);
            a.setAttribute("value", controller.axes[i]);
        }
    }
    rAF(updateStatus);
}

function scanGamepads() {
    var gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
    for (var i = 0; i < gamepads.length; i++) {
        if (gamepads[i]) {
            if (!(gamepads[i].index in controllers)) {
                addGamepad(gamepads[i]);
                console.log("a");
            } else {
                controllers[gamepads[i].index] = gamepads[i];
                //console.log("b");
            }
        }
    }
}

if (haveEvents) {
    window.addEventListener("gamepadconnected", connectHandler);
    window.addEventListener("gamepaddisconnected", disconnectHandler);
} else {
    setInterval(scanGamepads, 500);
}

実行させてみる

GithubリポジトリをWeb公開状態に以下においてありますのでそのまま動作させてみてください。

https://ueponx.github.io/gamepadapi/

2つのファイル(index.htmlgamepad.js)をローカルPCの同じディレクトリにおいても同じ様に使用できます。

index.htmlの開くと以下のように表示されますので、

f:id:ueponx:20190330221428p:plain

Gamepadを接続するか、Gamepadのいずれかのボタンを押すと表示が変更されます。

f:id:ueponx:20190330223116p:plain

今回接続したのは以下のUSB接続をゲームパッドを接続していますが、ちゃんと認識してくれているようです。

buffalo.jp

ボタンは物理的には10あるのですが、認識されているのは連射機能とそのOFFを除く8つのボタンでした。 また、方向ボタン(十字ボタン)はアナログスティックとして認識されているようです。ただ動かすとわかるのですが、デジタル的な動きをしているようです。

また複数のゲームパッドを接続しても認識してくれます。

f:id:ueponx:20190330222810p:plain

2つ目に接続したのはXBOX Oneの無線コントローラになります。

詳細は以下の通りです。

f:id:ueponx:20190330222636p:plain

おわりに

Gamepad APIを使ってみました。まだDraft状態のAPIではありますが、現行のモダンブラウザであれば比較的対応しているのでわりといい感じです。 ネットの情報ではブラウザ毎の挙動が微妙に違っているという話もありますが…。そのうち正式な対応されるでしょう。

各ブラウザの対応状況

対応状況をみると、IEは兎も角としてSafari

あと、パッドのおすすめはXBOXなコントローラーをデフォルト扱いとして開発されているようなので、今後コントローラーを購入するのであればXBOX用のものを おすすめします。

できれば、現在あるWebアプリなどにJoy2Keyみたいな感じでこの機能を簡単でアタッチする方法とかがあるといいなあとか思いました。 なにかつかえますかねえ。IotデバイスでWebインターフェースを作るようなパターンであれば行けそうな気もしますが。

今回やってて痛感しましたが、Javascriptスクリプト書くのは問題ないんですけど、HTMLを書くのがもう面倒で厳しいかも。JQueryとかBootstrapにシフトして行きたいです…その他のフレームワークに行ってもいいのかも。

【Live版Ubuntuへ移行】Dockerを公式チュートリアル”Get Started with Docker”で学ぶ【中編】

一連の流れのある【中編】になります。 ここまできてようやくチュートリアルのPart3が進められるような状況になりました。今回からはOSをChromeOSからUbuntu 18.02 LTSに変更して行っていきます。

【参考】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

以前のエントリの内容と重複はありますが、チュートリアルを進めていきます。 ここまで飛ばしていいという部分には【ここまで読み飛ばしていいです】という目印をつけておこうと思います。

Get Started, Part 3: Services

ここではServiceに関して学ぶことになります。

docs.docker.com

事前準備

事前準備としてはDockerのインストールは当然のことながらPart1とPart2を行ってきた環境(コンテナ)があることが必要です。

加えてDocker Composeのインストールが必要になります。Mac用のDockerデスクトップとWindows用のDockerデスクトップにはプレインストールされていますが、Linux系は別途インストールする必要があります。以下のサイトを参考にインストールを行います。

docs.docker.com

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

また、Part2で作成したfriendlyhelloイメージをレジストリにpushして公開することが必須になります。(ここではその共有イメージを使います。) 以下のようにDockerのイメージを実行し、http://localhost:8080/という感じでアクセスできることは確認しておいてください

※原文は4000ポートを使用していますがChromeOSではアクセスがNGなので8080に変更してありますので注意です。

【一般形】

$ docker run -p 8080:80 username/repo:tag

【前回の例で以下のように動作していました(ここでいうhogeは各自のユーザ名に変更してください)】

$ docker run -p 8080:80 hoge/get-started:part2

サービスとは?

このPartではアプリケーションを拡張し負荷分散を行います。そのために分散アプリケーションの階層を1レベル上に上げ、サービスという概念が必要になります。

階層的にはこんな感じ

  • Stack
  • Services (←いまここ)
  • Container (part2(前回)でやった部分)

分散アプリケーションはサービスという概念で構成されていて、例えばビデオ共有サイトでは、データベースサービス、ビデオをトランスコーディングするサービス、フロントエンド用のサービスから構成されているようなイメージになります。

サービスはコンテナから構成されます。その設定でイメージの実行方法、使用するポート、コンテナのレプリカをいくつ実行する必要があるかなどの体系化を行う必要があります。これらの設定を行う場合にはdocker-compose.ymlを記述することでこれらの定義、実行、拡張することが可能になります。

docker-compose.ymlを書いてみる

docker-compose.ymlでコンテナの動作を設定してみます。

以下に記載してymlファイルdocker-compose.ymlとして作成します。 このとき、Part2で作成したイメージをレジストリにpushしていることを確認して、自分の作成した username/repo:tagをイメージの詳細に置き換えてこの.ymlを更新します。 以下の例ではhoge/get-started:part2として設定しています。またポートも4000から8080へ変更しています。

【変更前(原文のまま)】

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

【今回の変更後】

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: hoge/get-started:part2
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "8080:80"
    networks:
      - webnet
networks:
  webnet:

このdocker-compose.ymlでは次のような動きを記述しています。

  1. Part2で作成したイメージをリポジトリから取得。
  2. 取得したイメージから5つのインスタンスを生成して、webと呼ばれるサービスとして名づけます。それぞれに対してCPU資源は10%、50MBのRAMを割当て。
  3. コンテナでエラーがあった場合には再起動。
  4. webサービスの各インスタンスの80ポートはローカルホストからは8080ポート経由からアクセス可能。(オリジナルの記述は4000ポート)
  5. webnetと呼ばれる負荷分散ネットワークを生成し、ポート80を共有するようにwebのコンテナに指示します。 (内部的にはコンテナ自体が一時ポートでwebのポート80に発行)
  6. webnetネットワークをデフォルト設定(負荷分散オーバーレイネットワーク)で定義。

【ここまで読み飛ばしていいです】

負荷分散ネットワークアプリの起動

まずは以下のコマンドを起動します。コマンドの意味はPart4で説明がありますが、これを実行しないとエラーが発生します。

$ docker swarm init

【ログ】

$ docker swarm init
Swarm initialized: current node (nc03uv6m1z1dxgwxdilvh29rj) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1dukwcs4w07qt835cw6o5w0aju191e93be2jtctejrndzj5jyd-25d5b683d7jx4hceptehbtrz9 192.168.0.7:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

つづいて以下のように実行します。この実行ではアプリはgetstartedlabと設定しています。

$ docker stack deploy -c docker-compose.yml getstartedlab

【ログ】

$ docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web

これで動作の確認になります。ここからはChromeOSではうまく動作しなかった部分になりますが… 以下のコマンドで確認します。

$ docker service ls

【ログ】

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
p1dyl3harlzm        getstartedlab_web   replicated          0/5                 hoge/get-started:part2   *:8080->80/tcp

お!あれ?だめなのか?

念の為、コンテナの動作状況を以下のコマンドで確認してみます。

$ docker service ps getstartedlab_web

【ログ】

$ docker service ps getstartedlab_web 
ID                  NAME                  IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
lgz0af823dtz        getstartedlab_web.1   hoge/get-started:part2   ubuntu              Running             Running 50 seconds ago                       
n2bgt0wx11kg        getstartedlab_web.2   hoge/get-started:part2   ubuntu              Running             Running 22 seconds ago                       
0b1v6d8jy5lu        getstartedlab_web.3   hoge/get-started:part2   ubuntu              Running             Running 50 seconds ago                       
sm21dfefpfgw        getstartedlab_web.4   hoge/get-started:part2   ubuntu              Running             Running 32 seconds ago                       
isx43duompwd        getstartedlab_web.5   hoge/get-started:part2   ubuntu              Running             Running 11 seconds ago 

ステータスはRunningになっています!動作しているようです。念の為もう一度Serviceの動作状況の確認を調べてみると…

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
p1dyl3harlzm        getstartedlab_web   replicated          5/5                 hoge/get-started:part2   *:8080->80/tcp

無事に起動しているようです。ちょっとホッとしました。

今回の動作環境ではDockerでaufsを使用していないため、パフォーマンスが劇的に低くなっているため各コンテナの起動に時間がかかってしまったのではないかと考えます。(他の例でも、起動に関するパフォーマンスは明らかに落ちているのはわかります。)

ではブラウザでこの負荷分散サービスへアクセスしていきます。 アクセス先は同様にhttp://localhost:8080/になります。このURLにアクセスするとロードバランスを図ってくれるのでアクセスする度(リロードする度)に 表示されるHostIDが変化していくことを確認してください。

f:id:ueponx:20190322062553p:plain

f:id:ueponx:20190322062602p:plain

f:id:ueponx:20190322062611p:plain

$ docker swarm init
Swarm initialized: current node (nc03uv6m1z1dxgwxdilvh29rj) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1dukwcs4w07qt835cw6o5w0aju191e93be2jtctejrndzj5jyd-25d5b683d7jx4hceptehbtrz9 192.168.0.7:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

$ docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
p1dyl3harlzm        getstartedlab_web   replicated          0/5                 hoge/get-started:part2   *:8080->80/tcp

$ docker service ps getstartedlab_web 
ID                  NAME                  IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
lgz0af823dtz        getstartedlab_web.1   hoge/get-started:part2   ubuntu              Running             Running 50 seconds ago                       
n2bgt0wx11kg        getstartedlab_web.2   hoge/get-started:part2   ubuntu              Running             Running 22 seconds ago                       
0b1v6d8jy5lu        getstartedlab_web.3   hoge/get-started:part2   ubuntu              Running             Running 50 seconds ago                       
sm21dfefpfgw        getstartedlab_web.4   hoge/get-started:part2   ubuntu              Running             Running 32 seconds ago                       
isx43duompwd        getstartedlab_web.5   hoge/get-started:part2   ubuntu              Running             Running 11 seconds ago                       

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
p1dyl3harlzm        getstartedlab_web   replicated          5/5                 hoge/get-started:part2   *:8080->80/tcp

f:id:ueponx:20190324071640p:plain


アプリケーションのスケールをしてみる

スケールをするのは簡単です。 docker-compose.ymlのレプリカの数を変更して保存し、再度docker stack deployコマンドを再実行するだけでアプリを拡張できます。 以下の例ではレプリカ数を5から3へ変更しています。非常にシームレスにスケールするのがわかります。

$ vim docker-compose.yml

$ docker stack deploy -c docker-compose.yml getstartedlab
Updating service getstartedlab_web (id: p1dyl3harlzm5ghawpj04noay)

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
p1dyl3harlzm        getstartedlab_web   replicated          3/3                 hoge/get-started:part2   *:8080->80/tcp

$ docker service ps getstartedlab_web 
ID                  NAME                      IMAGE                      NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
7qeqrcn6etna        getstartedlab_web.1       hoge/get-started:part2   ubuntu              Running             Running 20 seconds ago                        
lgz0af823dtz         \_ getstartedlab_web.1   hoge/get-started:part2   ubuntu              Shutdown            Shutdown 24 seconds ago                       
y52g099pbi4f        getstartedlab_web.2       hoge/get-started:part2   ubuntu              Running             Starting 2 seconds ago                        
n2bgt0wx11kg         \_ getstartedlab_web.2   hoge/get-started:part2   ubuntu              Shutdown            Shutdown 2 seconds ago                        
0b1v6d8jy5lu        getstartedlab_web.3       hoge/get-started:part2   ubuntu              Running             Running 10 minutes ago

負荷分散させるアプリケーションがdocker-comporse.ymlの変更を行ってコマンド一発でスケールできるのは非常に便利です!

後片付け

Serviceの終了を指せる場合には以下のコマンドを使用します。

$ docker stack rm getstartedlab
$ docker swarm leave --force

これで今回の環境は完全に終了します。

【ログ】

$ docker stack rm getstartedlab
Removing service getstartedlab_web
Removing network getstartedlab_webnet

$ docker swarm leave --force
Node left the swarm.

f:id:ueponx:20190322062709p:plain

これでPart3は終了です。

Get Started, Part 4: Swarms

ここからはPart4でSwarmに関する部分になります。(Part3でもやってましたけど) Part4では、Swarmとはどういうものか、Swarm内のノードがマネージャまたはワーカーになる方法、Swarmを作成、その上にアプリをデプロイを行っていきます。 また、その環境下でPart3同様に異なるマシンで構成でDockerの基本機能、ネットワーク機能、負荷分散やスケールできることを実験してみます。

docs.docker.com

前提としてはPart3までが完了していればOKということになるのですが、新たにdocker-machineコマンドが必要になります。 WindowsOSXであればDocker環境をインストールするとすでに入るのですが、Linuxの場合には別途インストールが必要になります。 以下のサイトを見ながら作業となります。

docs.docker.com

抜粋すると以下のコマンドになります。(versionは0.16.0の場合)

f:id:ueponx:20190327055356p:plain

$ base=https://github.com/docker/machine/releases/download/v0.16.0 && curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine

インストール後の動作チェックは以下で大丈夫です。

$ docker-machine version
docker-machine version 0.16.0, build 702c267f

f:id:ueponx:20190327055412p:plain

クラスタの作成

ドキュメントを読んでいくと…

You need a hypervisor that can create virtual machines (VMs), so install Oracle VirtualBox for your machine’s OS.

なんとvirtualboxをインストールしてVMを起動しろと言われます。(ChromeOSではここまで来ると本末転用のような状況…OS環境を変えて正解だったのかも) 仕方ないので、以下のリンクからUbuntu用のUbuntu 18.04 (Bionic) / Ubuntu 18.10 (Cosmic) / Debian Unstableパッケージをダウンロードします。

www.oracle.com

Ubuntuの場合、ブラウザ(Firefox)でダウンロードすると.debファイルを認識してパッケージのインストールを行ってくれますので、 そのままインストールしてしまいましょう。

インストールが完了したら、以下のように2台のVMを起動します。--driverで指定したVM環境が使用されVMが作成されます。

$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2

f:id:ueponx:20190327055425p:plain

f:id:ueponx:20190327055439p:plain

起動したVMmyvm1myvm2という名前で起動しています。このVMIPアドレスは以下のコマンドで調べることができます。

$ docker-machine ls
ubuntu@ubuntu:~$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.3   
myvm2   -        virtualbox   Running   tcp://192.168.99.102:2376           v18.09.3   

f:id:ueponx:20190327055451p:plain

VMIPアドレスがわかったら、2つともIPアドレスを控えておきます。そのうちの1台(今回はmyvm1側)をSwarmのマネージャホストにします。 該当するホストでdocker-machine ssh経由でdocker swarm initコマンドを実行します。実行時に表示されるtokenはメモしておきます。というかコマンドそのものをコピーしておいたほうがいいかもしれません。(docker swarm join ほげほげの部分)

$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
Swarm initialized: current node <node ID> is now a manager.

To add a worker to this swarm, run the following command:

  docker swarm join \
  --token <token> \
  <myvm ip>:<port>

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

f:id:ueponx:20190327055503p:plain

【ログ】

$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.101"
Swarm initialized: current node (76irf1ec7b14xfns1oym7638x) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0hdt9lh014fow8y0yrzw6sruqdzb275sw2ohwhiolzfy0ev05z-42bhd4wxtwd9hu7ndx9prrzzd 192.168.99.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

念の為、Swarmを使用する場合にはポート2377とポート2376を使用する可能性があるので、使用しないように注意が必要です。 また、上記のdocker-machine sshでコマンドを送信できない場合にはホストにネイティブにインストールされているsshコマンドを使用する事もできます その場合には--native-ssh sshオプションを追加設定します。具体的には以下のようになります。

$ docker-machine --native-ssh ssh myvm1  "docker swarm init --advertise-addr <myvm1 ip>"

続いて2台目のVM(今回はmyvm2)をワーカーとして登録します。その際は先程実行したdocker swarm initの戻りでtokenが表示されているので それをオプション指定してdocker swarm joinをホストに送信します。例のは適切なものに変更を行ってください。

$ docker-machine ssh myvm2 "docker swarm join --token <token> <ip>:2377"

f:id:ueponx:20190327055520p:plain

$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-0hdt9lh014fow8y0yrzw6sruqdzb275sw2ohwhiolzfy0ev05z-42bhd4wxtwd9hu7ndx9prrzzd 192.168.99.101:2377"
This node joined a swarm as a worker.

これでSwarmが生成できました。以下のコマンドで生成されたノードを表示してみます。

$ docker-machine ssh myvm1 "docker node ls"

f:id:ueponx:20190327055530p:plain

ここでもし最初からやり直す場合にはdocker swarm leaveを実行するとSwarmが終了し元に戻ります。

アプリのデプロイを行う

Swarmができあがったので、アプリをデプロイしていきます。

これまではdocker-machine sshで実行していましたが、これではいちいちコマンドを実行していく必要があるので結構手間です。そこでdocker-machine envで得られる情報を元にローカルのdocker-compose.ymlファイルを使用してデプロイする方法もあります。今回はそれを使用してみます。

環境変数の設定はdocker-machine envで取得できるので

$ docker-machine env myvm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/home/ubuntu/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell: 
# eval $(docker-machine env myvm1)

この情報をevalで取り込んで有効化します。

$ eval $(docker-machine env myvm1)

f:id:ueponx:20190327055542p:plain

すると、今回作成したmyvm1がアクティブ状態になります。

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   *        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.3   
myvm2   -        virtualbox   Running   tcp://192.168.99.102:2376           v18.09.3   

f:id:ueponx:20190327055552p:plain

Part3と同様にアプリのデプロイして、動作を確認してみます。

【注意】デプロイを行う前にdocker-compose.ymlファイルのあるパスに移動しておいてください。 myvm1のホスト上で以下のコマンドを実行すると

$ cd ./friendlyhello/
$ docker stack deploy -c docker-compose.yml getstartedlab

【ログ】

$ docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web

myvm1myvm2にアプリが分散配置されて起動されます。以下のコマンドで分散の状況を確認することができます。

$ docker stack ps getstartedlab

f:id:ueponx:20190327062929p:plain

$ docker stack ps getstartedlab
ID                  NAME                  IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
886onhvdec3j        getstartedlab_web.1   ueponx/get-started:part2   myvm2               Running             Running 3 minutes ago                        
ukvh7zbk85e8        getstartedlab_web.2   ueponx/get-started:part2   myvm1               Running             Running 3 minutes ago                        
tgvo877hsaox        getstartedlab_web.3   ueponx/get-started:part2   myvm2               Running             Running 3 minutes ago                        
ffzmzokyv6v7        getstartedlab_web.4   ueponx/get-started:part2   myvm1               Running             Running 3 seconds ago                       
jq5q4ukq9w6b        getstartedlab_web.5   ueponx/get-started:part2   myvm1               Running             Running 3 seconds ago

ここまできたらブラウザなどを使ってmyvm1またはmyvm2IPアドレスにアクセスを行います。

【myvm1へのアクセス】

f:id:ueponx:20190327055657p:plain

f:id:ueponx:20190327055708p:plain

f:id:ueponx:20190327055721p:plain

【myvm2へのアクセス】

f:id:ueponx:20190327055612p:plain

f:id:ueponx:20190327055623p:plain

f:id:ueponx:20190327055633p:plain

f:id:ueponx:20190327055646p:plain

この環境でスケールさせる場合にはdocker-compose.ymlを修正し、docker stack deployを実行することでスケールが用意にできます。またノードの追加に関しても今回のmyvm2と同様に追加することでホスト単位のスケールも用意にできるようになります。

stackの終了方法

stackの終了方法は今回の場合は以下のようになります。

$ docker stack rm getstartedlab

環境変数のクリア

docker-machine envで設定した設定は以下のように行うとクリアできます。

$ eval $(docker-machine env -u)

ローカルホストを終了させればdockerのマシンも終了します。状態を確認する場合には以下のコマンドとなります。

$ docker-machine ls

停止したノードを再起動させる場合にはホスト名を指定して以下のように再起動ができます。

$ docker-machine start <machine-name>

おわりに

OSを変更することでようやくPart3とPart4がおわらせられました。しかし、このチュートリアルかなり事前準備の要求が高いですね。あともう少し頑張ってみます。

【参考エントリー】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com