週刊Railsウォッチ(20190730-2/2後編)Docker 19.03の新機能に注目、ngrokはスゴい、redis-namespaceほか

こんにちは、hachi8833です。Rails 6.0.0 rc2リリースがやっと公式にアナウンスされました。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

週刊Railsウォッチ「公開つっつき会」第13回のお知らせ(無料)

1年目を越えた第13回目公開つっつき会は、明日8月1日(木)19:30〜にBPS会議スペースにて開催されます。引き続き皆さまのお気軽なご参加をお待ちしております🙇。

Ruby

Ruby標準のprivate_constant

参考: instance method Module#private_constant (Ruby 2.6.0)


つっつきボイス:「private_constantね☺️」「Qiita記事書いた人も知らなかったそうです」「これっていつからあるんだろう?🤔」「たしかに、コードの読みやすさのために定数使いたいけど外から呼ばれるのはイヤだっていうケースはありますよね☺️」

後でAPIDockを見るとRuby 2.1.10からだそうです↓。

参考: private_constant (Module) - APIdock

redis-namespace: sidekiqプロセスが1つで足りなくなったら(Hacklinesより)

# 同リポジトリより
require 'redis-namespace'
# => true

redis_connection = Redis.new
# => #<Redis client v3.1.0 for redis://127.0.0.1:6379/0>
namespaced_redis = Redis::Namespace.new(:ns, :redis => redis_connection)
# => #<Redis::Namespace v1.5.0 with client v3.1.0 for redis://127.0.0.1:6379/0/ns>

namespaced_redis.set('foo', 'bar') # redis_connection.set('ns:foo', 'bar')
# => "OK"

# Redis::Namespaceは、redisクライアントに送信する前に
# keyへの名前空間に自動でprependされる

namespaced_redis.get('foo')
# => "bar"
redis_connection.get('ns:foo')
# => "bar"

namespaced_redis.del('foo')
# => 1
namespaced_redis.get('foo')
# => nil
redis_connection.get('ns:foo')
# => nil

つっつきボイス:「Redisのnamespace?Redisにはdatabaseという概念があるけど🤔」「redis-namespace、誰か使ってたな〜: 何かの番号にENVからdevelopmentとかproductionみたいな値を入れるのに使ってた気が」「あそういう感じ?」「そういう類のものだった気がするんですが今思い出せない😅」


redis.ioより

参考: railsでredis-objectsを使う際にはredis-namespaceも使ったほうがいいかも - Qiita

「記事のタイトルは、Sidekiqのプロセスが1個で足りなくなったときにredis-namespaceを使うみたいな話か」「Redisサーバーをみんなでシェアできるということでしょうね☺️」「自分の世界を構築できるというか😆」「複数のSidekiqプロセスが同じRedis namespaceにアクセスするとジョブがグチャるから分けたい、でもRedisサーバーは増やしたくない、というのがやれそう😋」


sidekiq.orgより

その他Ruby


wasmer.ioより


つっつきボイス:「RubyからWebAssemblyを動かせるみたいです」「こういうの流行ってるのかな😆」「WebAssemblyのバイナリをGolangのバイナリみたく使うとか?そんなにやってみたいんかな〜?😆」「まだWebAssemblyをどう使うかみんな見えてないっぽいんですけど、やるだけなら簡単だからやってみてる感じかなと思ったり😆」


つっつきボイス:「そういえばRubyWorld Conferenceから招待来てた」


つっつきボイス:「mrubyでシステムプログラミング、/cが付くmruby/cか、それとも付かない方かな?🤔」「そっか、それぞれあるんですよね」「スライドをざざっと見た感じでは、/cが付かない方のようだ」

参考: mruby/c | しまねソフト研究開発センター
参考: mruby/mruby: Lightweight Ruby

DB

MySQL 8.0.17のCloneプラグイン

-- 同記事より
mysql80 35> create user yoku0825;
Query OK, 0 rows affected (0.01 sec)

mysql80 35> grant backup_admin on *.* TO yoku0825;
Query OK, 0 rows affected (0.00 sec)

mysql80 70> SHOW GRANTS;
+---------------------------------------------+
| Grants for yoku0825@%                       |
+---------------------------------------------+
| GRANT USAGE ON *.* TO `yoku0825`@`%`        |
| GRANT BACKUP_ADMIN ON *.* TO `yoku0825`@`%` |
+---------------------------------------------+
2 rows in set (0.00 sec)

mysql80 70> CLONE LOCAL DATA DIRECTORY '/tmp/clone';
Query OK, 0 rows affected (3.66 sec)

つっつきボイス:「Cloneプラグインのうれしみな部分が気になったので」「『ローカルファイルシステムにほぼノンブロッキングで物理バックアップを吐き出す』と」「MySQLのデータを内部形式のままぶっこ抜くということでしょうね、それこそLVM Snapshotを取るようなノリで」「お〜」「この記事書いてる人、たしかMySQL界の強い人💪」

参考: 論理ボリュームマネージャ(LVM) - Wikipedia

「MySQL本体にこのCloneプラグインがデフォルトで入るようになったのかな?」「どっかからダウンロードしてという感じではなさそうですね」「新しくCloneプラグインというものができたということかな」「追加されたと記事にあるからそれっぽいですね」

INSTALL PLUGIN CLONE SONAME "mysql_clone.so";

「英文マニュアルにも、動いているInnoDBのphysical snapshotを取れるとありますね😋」「それはかなりありがたい!🙏」「こういうこともできるし↓」「ノンブロッキングはうれしい❤️」「MySQL 8.0.17が必要らしいのでAWS Auroraでは使えないかな?まあAuroraには別のスナップショット機能があるからいいけど😆」

CLONE INSTANCE FROM USER@HOST:PORT IDENTIFIED BY 'password' ..

参考: InnoDB - Wikipedia
参考: Amazon Aurora(高性能マネージドリレーショナルデータベース)| AWS

pg_qualstatsとhypopgでPostgreSQLの「automatic index recommendation」をやってみる


つっつきボイス:「Perconaのぽすぐれ記事というのが珍しいなと思って」「pg_qualstatsとhypopg」

「記事タイトルにもあるとおり、automated index recommendationというのをやってくれるんでしょうね: ちゃんと読まないとわからないけど、たぶん計測しながら一番よくヒットする組み合わせを探すとかじゃないかな🤔」

「hypopgのREADMEにある『hypothetical indexは実際には存在しないインデックス』↓ってどういうことなんだろう?」「EXPLAINでチェックするためだけにあるみたいな?」「あぁ、インターフェース上あるだけで実際に参照するわけではないというか」「クエリプランに食わせるとダミーのコストが出せるみたいな?」

「hypothetical(仮説上)またはvirtual(仮想上)のインデックス」は、実際には存在せず、作成でCPUやディスクなどのコストがかからない。問題のあるクエリで特定のインデックス(の組み合わせ)によってパフォーマンスが向上するかどうかを確認するのに有用。PostgreSQLがそれらのインデックスを使うかどうかを、インデック作成のためのリソース抜きで知ることができるからである。
HypoPG/hypopgより大意

参考: SQL Server の仮定のインデックスについてまとめてみる at SE の雑記

「EXPLAINでは使えるけどANALYZEでは使えなさそうかな?」「READMEの続きにも『ANALYZEなしのEXPLAINだけがhypothetical indexを使える』とかあるからそうなんでしょうね」「つまり実際に即したコスト計算はできないと」「統計情報がないのにやれるとしたら不思議😅」「きっとそこをいい感じにダミーにやれるんじゃないかしら、あたかもインデックスがあるかのような統計情報を使うとか」

rjuju=# EXPLAIN ANALYZE SELECT * FROM hypo WHERE id = 1;
                                           QUERY PLAN
-------------------------------------------------------------------------------------------------
 Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13) (actual time=0.036..6.072 rows=1 loops=1)
   Filter: (id = 1)
   Rows Removed by Filter: 9999
 Planning time: 0.109 ms
 Execution time: 6.113 ms
(5 rows)

「これ、精度次第では結構いいものかもしれないっすね😋」「めちゃめちゃ外した結果が出るとかでなければ😆」「恐ろしく巨大なデータベースで普通にインデックス作ろうとすると激重になるから、おそらくhypopgでダミーのインデックスだけ作ってそれに対するクエリプランナー出してみて、明らかに使えないものは除外しつつ考えるとかそういう感じではないかと」「今読みきれないけど、これだけ長い記事ということはそれだけ使いみちがありそうですし😋」「Perconaの別記事↓にもう少し詳しくあるので、これも翻訳してみたいです😍」

参考: Hypothetical Indexes in PostgreSQL - Percona Database Performance Blog

クラウド/コンテナ/インフラ/Linux/Serverless

Docker 19.03のさまざまな新機能

同記事の末尾に元となるスライド↓がありました。


つっつきボイス:「そうそう、Dockerでroot権限なしでもやれるようになった🎉」「ついさっき19.03入れましたし😋」

Rootlessモード

「rootなしでいけました?」「cgroupなしでどうすんの?って思いましたけどっ😆」「実際、リソースコントロールってどうしてるんだろう?🤔」「できないという意味だったりして😆」

Docker 19.03では、非rootユーザでデーモンを実行できるようになりました(Rootlessモード)。 Rootlessモードを有効化することで、万一Dockerに脆弱性や設定ミスがあっても、攻撃者にホストのroot権限を奪取されることを防ぐことが出来ます。ただし、現時点ではcgroupを利用できないなどの制約があります
同記事より(強調は編集部)

参考: cgroups - Wikipedia

「Rootlessモードだとcgroup使えないということは、CPUにリミットかけたりとかもできない?rootが必要だった権限も取れない?」「OS周りでcgroupで制御していた部分についてはそういうことになるでしょうね☺️」「とりあえずrootレスは実現できたから、そこから先はこれから考えるんだったりして😆」「『現時点では』と言ってますけどね☺️」「実際、cgroup触れちゃうとrootと大して変わらないことできますし😎」

「cgroupなくてもやれることはあるからとりあえずはいい、みたいな考えなのかな?」「cgroup必要なものって結構多いと思いますけど😆」「PostgreSQLクライアントのマルチバージョンを使いたいだけ、とか、シェルコマンドの代わりに使う程度のツールぐらいだったら、cgroupとかroot権限は要りませんね☺️」「サーバーを動かすときはさすがにcgroup欲しいです🥺」

「cgroupはリソースを管理するためのものだから、cgroupを許すとリソースを取りに行くことも解除することもできちゃいます🧐」「cgroup経由でCPUにリミットかけるのもできないと」「それ以前に、cgroupがないとデバイスとかの権限をアイソレーションできませんし😆: ユーザー権限でやるということなら、デバイスの隔離は元々そのユーザーの権限でしかさわれませんけど」

参考: RootlessモードでDockerをより安全にする [DockerCon発表レポート] - nttlabs - Medium — とても詳しい記事です

GPU対応強化

「最近のDockerは欲しいものがちょくちょく入ってきてますね❤️」「GPU対応強化とか」

$ docker run --gpus all
$ docker run --gpus 2,driver=nvidia,capabilities=compute

BuildKitモード

「BuildKitモードは18.06から一応入ってたのか」

$ DOCKER_BUILDKIT=1 docker build

参考: Docker 18.09 新機能 (イメージビルド&セキュリティ) - nttlabs - Medium

docker context

docker contextってこの間Webチームミーティングで話してましたね」「AWS CLIのプロファイル機能みたいに、接続先ホストを環境変数じゃなくてcontextで管理できるというヤツ」「お〜」「aws configureで複数のプロファイルを作って--profileで切り替えられるという、それとまさに同じことをDockerでもやれる感じですね↓」「名前つけて切り替えられると!」

「今までだと、同じホストから複数のDockerホストを参照したいときにいちいち環境変数を書き換えないといけなかったのは地味にダルいし、どっちがどっちかわからなくなりがちですし😅: それをcontextで楽に書ける」「おぉ〜な〜るほど!」「記事には『kubectlのcontextと似ている』と書かれてますけど、AWS CLIにも似てると思いますし☺️」

# 同記事より
$ docker context create foo --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file"
foo
Successfully created context "foo"
$ docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT             ...
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
foo                                                           tcp://myserver:2376
$ docker --context=foo run ...

参考: docker context | Docker Documentation
参考: AWS CLI の設定 - AWS Command Line Interface

「Kubernetesとかを使える環境の人にとってはどうでもいいことなんですが😆、BPSのようにDockerホストが社内にいくつも立っているような環境でもcontextを設定すればやれるのがいい❤️」「たしかに〜」「Dockerホストごとにcontextを書いて切り替えれば、たぶんTLSでトンネルする必要はあるにしても、いちいちログインしないでいいし」「ですね!」「その意味でdocker contextは、BPSのように、オーケストレーションまではやってないぐらいの規模でDockerを運用しているところにとってうれしいですね🥰」

CLIプラグインとdocker buildx

「次はDockerコマンドを拡張できるプラグイン、これもよくあるヤツ」「buildxでBuildKitを魔改造できるし🧙‍♀️」

参考: cli/cli_plugins.md at 4d3a76d71e368b7ccff6184d2c65e588b543f293 · docker/cli
参考: docker/buildx: Docker CLI plugin for extended build capabilities with BuildKit

「buildxの事例としてマルチプルアーキテクチャに対応したビルドとか、なるほどと思うし: こういうのはDocker本体にあってもね〜😆」「複数アーキテクチャのエミュレーション!」「しかもQEMUエミュレーション!これいいわ〜😍」「複数アーキテクチャのエミューレーションがこんなに簡単に使えて、コンテナのテストも走らせられるようになれば、AWSのARMインスタンス(ろくに使ってないけどっ😆)のコンテナテストなんかもやれますし」「おぉ〜な〜るほど!」

参考: 新機能 – EC2 A1インスタンス – ARMベースのAWS Gravitonプロセッサーを搭載 | Amazon Web Services ブログ

「AWSのARMインスタンスは実はお安くないんですが💰、実は最近ラズパイみたいな組み込みのARM環境でDockerを動かすのが微妙に流行ってるんですよ」「へぇ〜?!😳」「つまり、そういうラズパイ環境で動くDockerコンテナイメージをローカルで簡単にビルドできるようになるだろうなって😋」「テストも同時にできるようになればさらにデプロイしやすくなりますし☺️」

docker appプラグイン

「次はdocker app」「何これ!docker-composeしたものをプッシュできるんだ!」「これ知らなかった〜😳」「docker-composeしたものをひとつのアプリのように運用するって、最近自分たちがやっていることそのものですし😆」「😆」「これがやれるということは、たとえば『このアプリケーションバンドルでデプロイする』ことができるということですし」「コンテナの集合をデプロイできると」「docker app、他にもいろいろやれるっぽい!」

# 同記事より
$ cat ./example-voting-app.dockerapp/docker-compose.yml
version: "3.6"
services:
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
  db:
    image: postgres:9.4
    ports:
      - "5432:5432"
  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - "${vote.port}:80"
    deploy:
      replicas: ${vote.replicas}
  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - "${result.port}:80"
  worker:
    image: dockersamples/examplevotingapp_worker
$ docker app push ./example-voting-app.dockerapp --platform linux/amd64 -t example.com/foo.dockerapp

参考: docker/app: Make your Docker Compose applications reusable, and share them on Docker Hub
参考: CNAB: Cloud Native Application Bundles


cnabo.ioより

「お、こんなこともできる〜↓」「つまりdocker appにしておくとKubernetesでも動かせると😋」「最近流行ってないけどDocker Swarmでもできると😆」「みんなKubernetesに慣れちゃったし😆」

$ docker app install --orchestrator kubernetes example.com/foo.dockerapp

docker exposeプラグインとngrok

「ngrokが使えるdocker exposeプラグイン、お〜これもありがたい!🙏」「これエングロックって読むんですか!NGINXみたくエンジンロックかと思ってた😅」「ngrokはかなり神サービス⛩: 動かしたいホストの任意のポートをURL公開できて、しかもHTTPS(SSL)対応しているというのが素晴らしい❤️」「おぉ〜」「たとえばローカルで動くRailsアプリを、ngrokを実行するだけで速攻で公開できますし😋」「Dockerのプラグインになるくらいにngrokって使われてるんですね😳」

$ docker run --name nginx -d nginx 
$ docker expose nginx 80
...
https://deadbeef.ngrok.io
...

後で探すと、en-grokと発音するそうです。

参考: ngrok - secure introspectable tunnels to localhost
参考: inconshreveable/ngrok: Introspected tunnels to localhost


ngrok.comより

ngrokは神ツール

「たとえばまだstagingもないような状態でアプリをちょっと顧客に見せたいときとか、ngrokでやると超ラク!」「そういえばこの間どっかで使ってましたね😆」「特にスマホの画面を見せるときとか、同じネットワークに置いてIP調べてみたいなのを全部スキップできますし、HTTPSじゃないとアクセスできないAPIも使えますし😋」「たしかにスマホこそそういうの使いたいですね☺️」「ngrokはかなり有能ツール💪」

docker microscanとEnterprise Editionのプラグイン

「docker microscanプラグインで脆弱性スキャンもできるし」

参考: clip/clips/microscan at master · lukaszlach/clip

「Enterprise Editionのプラグインも」「Enterprise Edition使ったことないな〜😆」「docker assembledocker templatedocker clusterdocker gmsadocker registry、まあ使うことはなさそうかな🤣」「そもそもEnterprise Editionだと何ができるんでしたっけ?」「チェックしたこともない🤣」「値段設定って難しいですね😅」「これだけ標準化が進んでくるとそうかも😆」

よもやま話

「ところでngrokのサンプルにdeadbeefってあるのを見てついニヤニヤしちゃいますし😆」「deadbeefって?」「これはバイナリを扱うバイナリアンたちがよく使う文字列で、8つの文字が全部16進数の文字で構成されていて、しかもゼロ埋めでも1埋めでもないので、deadbeefdeadbeefdeadbeef...みたいに埋めておくと改変されたところが見つけやすいんですよ😆」「あ〜なるほど!」「deadbeefはゼロ埋めや1埋めと違って、ほどほどにビットが分散していて乱れがわかりやすいとか、バイナリエディタで可視化モードで見るときにも色でわかりやすいという😆」

参考: Hexspeak - Wikipediadeadbeef以外にもいろいろ載っています


grokはSF作家ロバート・A・ハインラインが「異星の客(Stranger in a Strange Land)」という長編小説で生み出した造語で、「真に認識する」など複数の意味があります。異星の客は1960年代にヒッピーの聖典として祭り上げられて大人気を博し、grokもそのときに流行しました。手元にはありませんが、私の大好きな小説のひとつです。そういえばトールキンの「The Lord of the Rings」も同じ頃にヒッピーが熱狂した本で、後にウィザードリィやウルティマといったRPGに大きな影響を与えたとよく言われていますね。

参考: Grok - Wikipedia
参考: 異星の客 - Wikipedia

その他

経過時間の10%

記事は以下ですが、引用部分の方が気になりました。


つっつきボイス:「『最終更新日時からの経過時間の10%を、キャッシュの寿命に設定するHTTPクライアント』、こういうのが前からあるのか」「これって何か普通じゃないところがあったりするんでしょうか?」「HTTPクライアントをこう設定する気持ちはちょっとわかるかも: キャッシュが長期間更新されていないんだったらこれからも更新しなくていい可能性が高いよね、というスタンスというか」「そういう戦略でしたか!」「逆にキャッシュが直近で更新されていれば、今後も更新したい可能性があると☺️」

「ちょw、『ファイルの最終更新日時から約19年経っているので』↓って🤣」「『最悪1.9年の間は更新が反映されません』ってつらすぎだろうって🤣」

ファイルの最終更新日時から約19年経っているので、キャッシュの寿命として約1.9年が設定されます。 この間クライアントはキャッシュを利用するので、 ファイルに更新あったとしても最悪1.9年の間は更新が反映されません・・・! このことを知ったときは「そんなことするクライアントいるの?」と疑問だったのですが、 このキャッシュアルゴリズムはRFCやMDNにも記述があり、実際そのような挙動をするクライアントがあるようです。
同記事より

「この設定を変な踏み方するとどハマリしそう: ほら、たまに固定値のlast modifiedが返ってきたりすると死ぬみたいな🤣」「upper limitぐらいは定義しておいてもらわないときっと心がつらい😭」

番外

マクスウェルの悪魔


同記事より


つっつきボイス:「お、NTTの研究😋」「熱を選り分けて発電って、思考実験ならできても実際にコストに見合うのかどうかとても気になりました」「エネルギーがないところからエネルギーを作るというか😆」「たとえば運動量が大きい分子は通して運動量の小さい分子は通さない巧妙なゲートを作れれば、極端に言うと水を氷と熱湯に分けられるはずだという😆」「でもエネルギー保存の法則は破ってないと😆」

参考: マクスウェルの悪魔 - Wikipedia

以下は運動エネルギーを回転に変える版の動画です。惜しくもURLにアンスコが2つ入っていて埋め込めませんでした😢。

https://www.youtube.com/watch?v=LkYljJ__-Cs


たまに忘れそうになりますが、マクスウェルの悪魔は「demon」で、Unixでおなじみのアレは「daemon」(守護神)ですね。マクスウェルの悪魔を最初に知ったのは「物理の世界」という相当昔の新書で、同書の悪魔は手にラケットを持っていました🏓。

参考: デーモン (ソフトウェア) - Wikipedia
参考: ダイモーン - Wikipedia
参考: 『物理の世界』(湯川 秀樹,片山 泰久,山田 英二):講談社現代新書|講談社BOOK倶楽部


後半は以上です。公開つっつき会でお会いしましょう!

おたより発掘

バックナンバー(2019年度第3四半期)

週刊Railsウォッチ(20190729-1/2前編)Rails 6のリリースは近そう?、Evil MartiansのRails+Docker記事、Railsパフォーマンス測定ほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSなど)です。

Rails公式ニュース

Ruby Weekly

Hacklines

Hacklines

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

夏のTechRachoフェア2019

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ