Cloud Load Balancingを使い、Cloud RunサービスにIAPで認証を追加する

今回やりたかったのは Cloud IAP という Google がいい具合に処理してくれる認証用の proxy サーバを Cloud Run の前段に置き、特定の人しかアクセスできないようにすること。

Cloud Run には直接 IAP を設定することができず、必要な準備がいくつかある。今回はこの実現のために必要な準備を確認した。

Cloud IAP, Cloud Load Balancingをおさらい

Cloud Run は Cloud Functions 同様、そもそも認証情報付きでしかアクセスできないようにすることもできるが、Cloud IAP ( Indentity-Aware Proxy ) はアカウント単位で許可する人を登録したり、Google Workspace と組み合わせてドメイン丸ごとに対して設定することで、社内限定公開のようなものをお手軽に実現できるスグレモノだ。ただし Cloud IAP を直接設定できるのは App Engine ( GAE ) だけで、それ以外は Cloud Load Balancing のアプリケーションロードバランサと組み合わせる必要がある。

Cloud IAP を通じて Cloud Run へのアクセスを保護する構成

Cloud Load Balancing には L7 アプリケーションロードバランサ(外部/内部)、L4 ネットワークロードバランサ(外部/内部、プロキシ/パススルー)があるが、今回利用するのは外部アプリケーションロードバランサになる。VPN を使わず、インターネット越しのアクセスに対して特定の人のみアクセスできるようにしたい。

この辺は Load Balancing 側のドキュメントではなく IAP 側のドキュメントから参照していくと寄り道が減って分かりやすい。

外部 HTTP(S) ロードバランサの設定  |  Identity-Aware Proxy  |  Google Cloud

※ 意識が発散しやすい人は各ロードバランサの役割の違いなどが気になるだろうが、グッと我慢しないと帰ってこれないので注意。

まとめ

Cloud Run はよくできてる。欲しいものは service の設定画面からポチポチでだいたい追加できそうな勢い。App Engine と違ってサービス単位で Logging などへの遷移がしやすいようになっているし、とても気が利いている。

IAP を利用するための Load Balancing の設定も 2024-02 時点では preview だが、Integration からサクッと設定できてしまう。

確認したこと

  1. Cloud Run の Integration ( preview ) 機能で Custom domains - Google Cloud Load Balancing を追加
  2. その後別途手作業で Load Balancing ( Frontend + Backend ) + Serverless NEG

両方試した。2 は 加えて Frontend に

  • Custom Domain
  • Google-managed Certificate

を設定し、Backend に

  • Identity-Aware Proxy

を設定した。いずれも手作業であり、自動化はしていない。

分かったこと

  • IAP は Load Balancer の Backend service 単位に設定できる。これは GAE に対する IAP の設定の様子と似ている。GAE は service を複数持つことができ、service ごとに IAP の設定を分割できるが、それと同じと考えることができそうだ。Load Balancer が前に立つので GAE に限定されない。
    • ただし Cloud Storage に対しては IAP をセットできないので静的サイトのアクセス制限は GAE の static_files の設定を利用するなど工夫が必要
  • URL map は host も path もなんでもこい
    • 逆に他の Web サービスのように独自の名前を持たず、ユーザーとの間の単一エンドポイントを提供するための IP アドレスの払い出ししかしないので、ドメインは最初に自分たちで確保が必要(これがネックになるなら Cloud Run などではなく GAE でまかなえないか考えるのが吉)
  • Cloud Run 側の ingress を絞らないと誰でもアクセスできて意味がない
  • 固定 IP が振り出されるので IP アドレス代も掛かってるはず

cf.

思ったこと

  • Serveless NEG だけ作る方法はないのか? (Load Balancing 側の設定項目のように見える)
  • なんで Network Endpoint Group と呼ぶのに group 設定ができるように見えないんだ?

試していないこと

  • 異なるプロジェクトにまたがる Backend を設定すること

低頻度アクセスサイトのworkerプロセスのコスパが悪いよ問題にSolidQueueが使えるかも

背景

ActiveJob の backend は意外と悩ましい。

ActiveJob は本来 Rails 専用でも ActiveRecord 専用でもないはずだが、いざ adapter を選んでみると Rails + PostgreSQL 前提です、みたいなことが意外にあったりする。また人気のバックエンドだった Redis も近年はクラウドベンダー側と折り合いが悪かったり、意外と扱いやすくない。1 特に Rails 5, 6 が Webpacker をはじめゴテゴテしつつも変化の早い時期で、別にこれくらいなら Rails じゃなくても Hanami でも Sinatra でもいいんじゃないの?と思っていた頃は特に悩ましかった。

2024-02 現在、Rails 7 は十分シンプルになり、素の cold start の遅さがいわゆるサーバレスとイマイチ相性が悪いが、それ以外は概ね Rails でよいかもと思う状況に戻りつつある。

ActiveJobバックエンド選択時の課題

上記のような背景を踏まえ、現時点で自分が感じている ActiveJob 選択時の課題は以下のように整理できる。

  1. Redis 以外の安定したバックエンドが使えないか
    • Resid のホスティングは以前ほどお手軽価格ではなくなっている。特にメガクラウドに寄せようと思うと、中小規模にとってはだいぶコスパが悪い状態
  2. ActiveRecord を使うのであれば PostgreSQL, MySQL など特定の DB にはできれば依存したくない(細かいバージョンの違いなどはあまり気にしたくない)
  3. できれば Worker dyno, Worker コンテナを使わずに済むならその方がありがたい
  4. クラウド独自のツールは development 環境の再現で手間取るので、なんかもっと楽なものはないか

えーと簡単に言うと手間もお金も掛からず ActiveRecord 任せにできるとそれが最高だな、ですね😁

低頻度アクセスのサイトのバックグラウンドジョブの課題

特に上記 3, 4 が課題になってくるのが低頻度アクセスのサイトである。簡単に言うと

めったにジョブを処理しないのにサーバ(コンテナ)2つ分、ずっとリソースをキープしておくのもったいなくない?

という話だ。

基本的に ActiveJob でバックグラウンドジョブを処理する場合、ユーザーからのアクセスを受け付けるプロセスとは別にバックグラウンドジョブ用のプロセス(コンテナ)を用意して、ジョブ用のプロセス(コンテナ)で polling して処理する方法が一般的なのだが、こうなるとめったにアクセスがないのに24時間起きてる人を最低2人用意しなきゃいけない、という話になり、「なんかコスパ悪くない?」という状態になる。2

もちろんジョブの負荷自体がメモリ使用量的にも実行時間的にも軽いものであれば、全部 inline で処理してしまうというのも一つの手ではある。ちゃんと計測してリソースが足りるのであれば問題ないと思う。しかし現実には

  • 頻度は高くないがコストは一定以上大きい

ケースはままあるし、例えば簡単なメール1通送るだけだったはずの仕組みが、関係各所に送ることになりましたとか、コストの嵩むことを往々にしてやりたくなる。そうなると inline や async adapter で処理するのはインフラのリソースの制限上難しくなってくる3

いちばん確実な解決方法は 4 である。Google Cloud で言うところの Cloud Task を利用する4。これは完全にサーバレスで従量課金なので、バックグラウンドジョブが発生しない限り余計なコストは発生しない。

ただ今度は手元で完全に同じ環境を再現するのが難しいという新たな課題が生まれる。

そんなあなたにSolidQueue

SolidQueue は 37 Signals が新たに開発した ActiveRecord を利用した ActiveJob adapter.5

で、なぜ SolidQueue かと言うと SolidQueue には puma plugin があるので、SolidQueue 用に別途プロセス(コンテナ)を用意しなくても puma の worker の一つとして SolidQueue を管理させることができるから。

もちろんメモリ使用量や実行時間がシビアな場合に気にしなければいけないことは変わらないが、少なくとも揮発しないストレージに情報を残しつつ処理できるので、ジョブを細分化するジョブを作って緩和しつつ、万一メモリ不足でプロセスが異常終了するようなことがあってもジョブが失われないという安心感がある。

簡単に試してみた

wtnabe/example-rails7-sqlite3-solid-queue

上のリポジトリは Cloud Run で FUSE を使って SQLite を読み書きするというリポジトリなのでノイズが多いが、キモは

Procfile.dev の

web: mkdir -p storage/sqlite3 && ./bin/rails s

と ( worker なし ) puma の設定の

plugin :solid_queue

だけで6、solid_queue が polling してバックグラウンドジョブを処理できることである。

※ 今回は実験用に SQLite3 で動かしているが、どうも時々エラーが起きたりするので ActiveRecord-backed とは言っているが、基本的には PostgreSQL or MySQL が前提になっているのだと思われる。

メモ

  • 設定が Rails 本体側というか configure 側に断りなしに漏れていて、solid_queue.yml には一部の設定しか書けないのはちゃんとドキュメントにしてほしい
  • 一応 development では SQLite3 でも動くので手元でサクッと動かす分にはよさそう(InlineやThreadだと何らかの外部ストレージを経由する場合と挙動が変わってしまうので)
  • Rails 7 + SQLite 3 + FUSE ( Cloud Storage ) は基本的な機能だけなら動く
  • 同環境だと SolidQueue の動作の何かが FUSE の制限を踏み抜いてしまうのか、必ず SQLite3::BusyException: database is locked (ActiveRecord::StatementInvalid) か SQLite3::CorruptException: database disk image is malformed (ActiveRecord::StatementInvalid) で死ぬので Cloud SQL でないと無理かも
  1. メガクラウドは結局生のサーバを1台使う、みたいな感じになったりしてまったくお手頃価格にならなかったりする。Heroku や Redis 専門の低価格サービスと組み合わせるといった方法はあるが、今度は管理が煩雑になったりする。 

  2. オンプレならリソースさえ足りれば特に問題はないが、そうなると今度はインフラ管理のコストが乗ってくる 

  3. メモリ使用量の制限やWebプロセスの実行時間制限など 

  4. 実際には特定の routing の Web プロセスにジョブを投げる設定の場合、Web プロセスの実行時間制限に引っかかる可能性は残る。 

  5. 実際には恐らく PostgreSQL と MySQL の該当バージョン以降のもの以外は満足に動作検証されていないと思う。 

  6. リポジトリのものはコメントアウトされてしまっているので戻す必要アリ 

Cloud Run + Cloud Storage FUSE試してみた

Cloud Storage FUSE  |  Google Cloud

Cloud Storage FUSEとは

FUSE が何か分かっている人は Cloud Storage FUSE という名前だけでピンと来ると思うが、よく分からない人のために乱暴に言うと

アプリケーションから見えるファイルシステムの中に Cloud Storage を mount できるもの

になる。図にするとこんな感じ。

※ もちろん本物のファイルシステムとまったく同じにはならないが。

Cloud Storage FUSE  |  Google Cloud

これまでのオブジェクトストレージを読み書きするコードの課題

Cloud Storage に限らずオブジェクトストレージは容量を気にする必要がないし、自動でレプリケーションされたり、とても便利な反面、通常はファイルシステムはファイルシステム、オブジェクトストレージはオブジェクトストレージで、それぞれの I/O にそれぞれ異なるコードが必要になる。

ではオブジェクトストレージの読み書きの動作をどう実現してどう確認するかというと、以下のような工夫が必要だった。

  1. emulator を使う(emulator が用意されていて API Client が emulator に対応していれば簡単)
  2. API Client を直接利用せず、いい具合に I/O を pluggable に切り替えてくれるライブラリを利用する
  3. 実際のクラウド環境にコードを deploy する

3 は間違いがないが、何か試すたびにいちいち deploy しないといけないし、クラウドの利用料金が掛かる(微々たるものかもしれないが)。

つまりオブジェクトストレージ(というかクラウドネイティブの機能)の I/O が入ると testability が落ちてしまうという問題を抱えている。

個人的には上の選択肢の 2 を必ず利用するようにしてきた。(自分で書き始めたコードでない場合は 1 もあり得る。)オブジェクトストレージの読み書きのライブラリの選定の際に差し替え可能で安定していそうなものを選ぶところから始め、読み書きの差し替えを行うコードを挟むところから始めるようにしている。

正直面倒ではあるけど、その後何回も結果を確認する際にいちいちクラウド環境で動かさないといけない方が面倒なので仕方がない。

オブジェクトストレージをmountするとはどういうことか

これがオブジェクトストレージをファイルシステムの一部に mount できるということは、インフラ側の設定さえ済めば、アプリケーションコード側からはファイルの読み書きのコードを書けばそれがローカルのファイルシステムに対するものか FUSE を通じたオブジェクトストレージに対するものかは気にする必要がないということを意味する。

ローカルの開発環境で動いている場合はローカルのファイルシステムを読み書きするし、クラウド環境で動いている場合はクラウドのオブジェクトストレージを読み書きしてくれる。

もちろん全部自分で作っているのであればファイルシステムとオブジェクトストレージの切り替えくらい自分でやれば済む、という場合もあると思うが、例えば DBM 的なライブラリを使いたいとか、利用するツールが暗黙のうちにファイルシステムに依存している場合はそうもいかない。以下の GCP 公式の対応状況では Cloud Storage FUSE 自体が AI 向けに売り出しているように見えるが、これにはそういう事情もあるのかもしれない。

GCPでの公式の状況

2024-02-11 時点で

Cloud Storage FUSEとの統合をサポートしている実行環境として挙げられているのは

  • GKE
  • Vertex AI
  • Deep Learning VM Images
  • Deep Learning Containers
  • Batch jobs
  • Cloud Composer

Cloud Storage FUSE と Google Cloud プロダクトの統合

になっているが、Cloud Run 側のドキュメントには

Cloud Storage FUSE と Google Cloud プロダクトの統合

あれもこれも知っていれば使えるよ、という情報がある。

Cloud Runでの利用は実はめちゃくちゃ簡単になっている

公式の GA の状況はまだまだっぽく見えるが、実際には

Cloud Run と Cloud Storage FUSE (GCS FUSE) の基本

にあるように、gcloud SDK では alpha components という扱いだが、

  • --add-volume
  • --add-volume-mount

フラグを利用することで gen2 実行環境1においてはめちゃくちゃ簡単に deploy できる

gcloud alpha run deploy  |  Google Cloud CLI Documentation

し、Cloud Run のコンソール画面では普通に Cloud Storage バケットを Volume に追加する機能がある。

Docker で例えるとホスト OS 側のパスを指定しておくことで Docker 環境からホスト OS のコードを読み込み、ストレージに書き込めるような、あんな感じで利用できる。

自分の感覚では

生のサーバで cron で動作させて、成果や認証の情報なんかをちょろっとファイルに書き出して終わる、みたいな伝統的なツールを Cloud Run に持ってくるとか簡単にできそう

という状態にきている。ようやく VPS を完全に解約してオッケーかも、と考えている。

やってみたこと

以下を組み合わせて試してみた。

  • 実行環境
    • Cloud Run Service gen2
    • Cloud Run Jobs ( gen2 )
  • 試したツール
    • 生 Ruby
    • Rails
    • GDBM
    • RocksDB
    • SQLite

データの整合性のレベルで確認したわけではないし、並列度も全然厳密にテストしていないが、動作するという意味ではどれも問題なく動かすことができた。唯一ダメだったのは

FUSE 上の Cloud Storage に置いた SQLite を利用して Rails で SolidQueue を puma 管理下で動かすこと

だった。これは起動すらしなかった。

development 環境でもたまに SolidQueue worker プロセスがエラーを吐いて再起動するという現象は起きていたので、SQLite + SolidQueue 自体がそこまで実績がなさそうなのと、それをさらに FUSE の制限上で動かそうとするのが無理だったのかと予想している。

使ったコードは以下。

Rails については SolidQueue 云々より FUSE + SQLite というだけで cold start に 15s くらい掛かるので、これはちょっとさすがになんか別な方法考えた方がいいかも。

RocksDB についてはそこそこのサイズのデータベースを作ってもある程度(64MBとか)のサイズの chunk に分割されるので、key-value ストアとして Cloud Run のリソースの制限 ( 512 MB ) 内で利用するにはなかなかよいかも、と思った。当然速さは出ないけど、それでも十分機能します、みたいなシーンはそれなりにありそう。

  1. 2023年に GA になった Cloud Run Jobs は最初から gen2 で、従来からある service の方はオプション –execution-environment gen2 を与えると gen2 になる。 

Cloud Native Buildpacksのextension完全に理解した

Cloud Native Buildpacksでextensionを諦めつつrun-imageを拡張する (2023-12-31) | あーありがち の続き。

確認環境

2024-01-28 時点

  • macOS ( arm64 )
  • colima 0.6.7
  • Docker
    • Client 25.0.0
    • Server 24.0.7
  • pack 0.32.1 および main ブランチ HEAD
  • gcr.io/buildpacks/builder:google-22 Builder
  • Google Cloud Run

で確認。

この時点の pack CLI が suggest してくる trusted builder はどうも –extension オプションを受け取って意図通りに動作することはなさそうだった。

やりたかったこと / 実現したこと

Cloud Native Buildpacks の build image, run image に用意されていないパッケージを独自に追加し、それを利用する rubygems をインストールし、クラウドインフラ(Cloud Run)上で実行する。

image の拡張の部分は具体的には

  • build image に対しては pack コマンドの –pre-buildpack オプションと –extension オプションを用いてパッケージの追加を行う
  • run image に対しては 前回 同様、事前に build しておいた image を –run-image で与える

方法になった。この辺り何をしたかは 成果物 の sh script にまとめてあるので参考になれば幸い。

目指さなかったこと

オリジナル Builder の作成。

分かったこと

ゼロから Builder を作らなくてもなんとか既存の image を拡張して必要な機能を追加することができる。

一方でそのためにはある程度以上の Docker の知識と Cloud Native Buildpacks の知識が必要になる

特に

  • Dockerfile を自分で書ける
  • Builder, Buildpack, Extension に対する理解が整理できている
  • docker build 中の USER と Cloud Native Buildpacks の USER について理解できている

辺りは必須になる。「Dockerfile を書かずに Docker image を作れる」という謳い文句からは急に遠くなり、正直言うと少々ハードルが高い気がする。Buildpack という言葉がすでに長い歴史を持ち、調べ方によっては正しい情報に辿り着くことも難しい。

こうなると逆にゼロから Builder を作る経験はあった方がよいかもしれない1し、むしろ Docker と配布 Docker image に対する知識、multi-stage build に対する知識があるなら素直に自分で Dockerfile を書いた方が楽かもしれない。

Cloud Native Buildpacksを導入しやすいパターン

  • development 環境の再現に際し docker compose を前提としない
    • ツールのインストール、複数バージョンの切り替え以外については Procfile でプロセスを管理すれば問題ない
  • 開発開始時に最終的な実行環境に必要な Docker 周りの準備を決めきっておく必要がない
    • 特殊な拡張が必要かどうかの決断は先送りしてよい

いわゆる普通の Web アプリだと比較的この構成に近い気がする。どうしても開発機の OS が混ざるのでコンテナに閉じ込めておきたいということでなければ、それほど導入は苦しくないように思う。

extensionを利用してまで既存のbuilderを利用するメリット

  • 開発者がインフラに詳しくなくてもまずはそのまま動くものを作ってもらうことができる
  • docker image の選定などは先送りにできる
  • ある程度以上の期間使うようになると Docker image のメンテナンスはそれなりに面倒になるので、クラウドベンダーの準備してくれる Docker image の上に乗れるのは、長期的には考えることが減って助かる

ハマったこと / 注意点

  • project.toml の schema-version をちゃんと “0.2” にしないと exclude は機能しない。schema-version は optional なので無指定でもエラーにならない(これは正しい動作)が、0.1 で対応していない exclude を指定してもやはりエラーにならない
  • 今のところ自分が動作を確認できた Builder は gcr.io/buildpacks/builder:google-22 のみ。例えば同じ手法で heroku/builder:22 に extension でパッケージを追加することはできなかった。また今後対応 builder が増えるのかどうなのかもよく分からない。(そういうプランを見つけることはできなかった。)
  • Google のリファレンス Configure your build and run images  |  Buildpacks  |  Google Cloud によると builder image はもっとカジュアルに Dockerfile で拡張できそうに見えるのだが、実際に試すとできあがった builder image は “could not parse reference” と言われて使えない

考えると schema-version に限らず、Buildpack API などのバージョン情報も意味がよく分からない。どのバージョンにどのような schema 情報が紐づくのか、分かりやすい資料がない。これはぜひ改善してほしい。

おまけ - Cloud Native Buildpacksのextensionとは

Cloud Foundry / Heroku 時代の buildpack と違い、登場人物が多くてややこしいが、公式ドキュメントのサンプルのコードを読み、実際に動かしてみての自分の理解は、こんな感じになった。

ちょっと分かりにくいが、

  • Extension は image に何らかの機能、役割を provide するもの
  • Extension も Buildpack のように detect, generate というフェーズで image に改変を加える
    • この際、公式ドキュメントとサンプルコードを読むに build image にも run image にも改変を加えられそうだったのだが、自分が試したところ build image にしか上手く改変を加えることはできなかった
    • run image は 前回と同じ手法 を採用することにした
  • ただし、provide したものを require する Buildpack が必要
  • Buildpack は本来 Builder image に含まれるものだが、pack コマンド 0.32.1 には –pre-buildpack / –post-buildpack というオプションで image 化していない生ファイルの Buildpack を追加することができる
    • 今回は rubygems のインストール前に必要なパッケージを追加したいので –pre-buildpack を利用した

成果物

wtnabe/example-cnbp-builder-extension-and-extended-run-image

参考

  1. 自分は Heroku / Cloud Foundry 時代の古い buildpack の知識を援用してごまかした。 

annoy-rbで初めてのベクトル検索をめちゃくちゃ手軽に試す

背景

ベクトル検索は興味あるけど、ベクトル化するところでいつもつまずく1ので、「いちばん簡単なの緯度経度ちゃうの?」と思って探してみたら実は意外と緯度経度情報をベクトル検索するという話題がない2のでやってみた。

今回の成果

データベースも使わず、embedding などの技法も何も要らない、めちゃくちゃ素朴なベクトル検索ができた。

ベクトル検索に関する各要素についてなんとなくの理解だったが、この素朴なものができたおかげで理解がよりクリアになった。(理解したとは言っていない)

おさらい

準備

今回は例によって Ruby でやるので、Ruby 用の binding を探すと以下のような感じ。

AI 関係調べるとよく出てくる安定の ankane さんと洋食さんなので安心でしょう。

ベクトルの類似度、近似度についてイチから学習する気は今回はないので、どっちも軽く触ってみて、なんとなく分かりやすそうな annoy の方を使ってみる。インデックス方式の違いがよく分からん。

作ったもの

  • 日本の各都道府県の人口上位3都市とその緯度経度(たぶん普通は庁舎のある地点だとオム)を ChatGPT 3.5 さんで適当に生成
  • その ID と緯度経度情報(ベクトル)だけを annoy-rb に与えてビルド
  • 緯度経度を与えたらそれを検索するだけの CLI アプリ

wtnabe/example-simple-vector-search-with-annoy-rb

分かったこと

  • annoy-rb は DBM っぽい何かのように使える
  • ベクトルの次元と距離計算の方法を先に決める必要がある
  • データを入れたらビルドが必要
  • ベクトル検索はベクトルしか持っていないので ID で元データと突き合わせが必要
    • 逆に言うと突き合わせさえできるなら別に専用の大掛かりなベクトル検索の仕組みがなくてもベクトル化、embedding さえなんとかなれば、意外と導入はローコストにできるのかも3
  • 単純に緯度経度で検索する場合、コサイン類似度などではなく、ユークリッド距離で比較しないと直感に反した結果になります(そりゃそうだ)
  1. 興味が発散しすぎて帰ってこれない 

  2. たぶん簡単すぎるんでしょう 

  3. ただし、ファイルシステムベースのものはクラウド環境とあまり相性がよくないので、そこは考える必要がある 

Cloud Native Buildpacksでextensionを諦めつつrun-imageを拡張する

要望

Cloud Native Buildpacks の Builder が提供するイメージに含まれないツールを使いたい

例えば ImageMagick. いや ImageMagick くらい入っているか。例えば ffmpeg. さすがに普通入ってなさそう。

今回はそういうツールを使いたいと思った場合の対処方法を調べてみた。

まとめ

  1. 利用したい Builder の Run image の base image に対してDockerfile で追加設定を行い、docker build
  2. pack build --run-image <1でできたイメージ> でコンテナイメージを作る

Cloud Native BuildpacksのBuild imageとRun image

まず前提として押さえておくべき知識について。

今回考えているのは

実行時に、標準的でないツールを導入したい

ということなので、

Build · Cloud Native Buildpacks

で言うところの app image の中に「標準的でないツール」を導入したい、という要望である。

すると工夫が必要なのは Run imageということになる。

Run imageに変更を加える手順

run imageの拡張については非常にコンパクトだが、以下がまとまっている。

ビルドと実行のイメージを構成する  |  Buildpacks  |  Google Cloud

1. run imageのbase imageからdocker buildで拡張する

  • Builder の提供している run-image 用の base image を FROM に持つ Dockerfile を書いて、そこに必要な変更を加える
  • USER の切り替えに注意。例えば Heroku Builder を使う場合は USER root で変更を加えたあと、USER heroku に戻す必要があった。
  • run-image の base は Builder ごとに違うのでそれぞれで確認すること

で、docker build を実行する。

例えば Heroku Builder の Heroku-22 イメージに対して ffmpeg を追加したい場合は以下のような Dockerfile になる

FROM heroku/heroku:22-cnb

USER root

RUN apt-get update && \
  apt-get install -y ffmpeg

USER heroku

2. できたimageをpack build時に利用する

こうゆうこと

$ pack build -B <builder> --run-image <さっき作ったimage>

あれ、結局Dockerfile書いてない?

そうなんです。

ということは想定外の入力が入る可能性のある実行環境でこの run-image を利用する場合は、常にフレッシュで安全な状態を保つように独自に CI/CD で build し続けておく必要があります。

諦めたImage Extension

実は最初

Create an extension · Cloud Native Buildpacks

を参考に CNB image extensions という考え方でなんとかなるんじゃないかと思ったんだけど、全然情報はないし、サンプルのリポジトリを見ても分からないしで、諦めました。

Heroku の Builder を利用したところ、

failed to build: executing lifecycle: builder has an order for extensions which is not supported when using the creator

と言われて、調べてもさっぱり情報が見つからず、Google の Builder はどうも無視してるっぽいので、

今回は諦めです。

Gemfile.lockでRubyのversionを指定する方法

まとめ

Gemfile.lock に利用する Ruby のバージョンをセットする方法

  • Gemfile に ruby でバージョンを指定
  • bundle update --ruby を実行

きっかけ

HerokuのCloud Native Buildpacksを使ってCloud RunでSinatraアプリを動かしてみた (2023-12-16) | あーありがち

で初めて経験したんだけど、なんかどうもこの方面は Gemfile.lock でのバージョン指定は普通っぽいので、整理しておいた。

注意

Google の Buildpack だったか、.ruby-version に改行が含まれてたら Gemfile, Gemfile.lock 側のバージョン指定と矛盾しているという警告が出た。いやもう、そんくらいいい具合に処理してくれよ。なんでみんなそんな繊細なのよ。

そういう意味では、この辺はまだまだ発展途上なのかも。ただあんまりフィードバックしてる人いなさそう(自分も含め)

Creative Stage SE miniを買ってた

背景

以前からたまに Bluetooth イヤホンがうまく充電されていないことがあり、ミーティングの際にイヤホンが使えずに PC 本体のスピーカーで対応することがあったのだが、ノート PC をクラムシェルモードで使っているため、音がこもってとても聞き取りにくく、困っていた。ということでなんとなくスピーカーあった方がいいかなぁ、とは思ってはいたものの、選ぶのが面倒くさくて先送りにしていたのだが、たまたまブラックフライデーのタイミングで同じことが起きたため、頑張って調べてみた。

判断基準

とりあえずぶわっと眺めたうえで自分なりの判断基準を整理。

  • USB で接続でき、別途電源を必要としないこと
    • 現在ノート PC 本体へは Thunderbolt 4 ( Type-C ) ケーブル 1本で給電、AV 出力、Ether すべてをまかなっているので、スピーカーもここにそのまま加えたい
  • 人の声の聞き取りを重視、別に本格的な音楽や映画などでの迫力は考えていない、ってゆーかドンシャリはきらい
  • あまり存在感が強くないこと。つまりゲーミング系は自動的に除外されるし、できれば高さがあまりないこと

を前提に、

  • サウンドーバーの価格はけっこう極端で、2000 円くらいのものがあるかと思えば普通に1万円超えたりする。音についてはレビュー動画なんかもあるが、結局のところ買ってみないとほぼ分からないので、失敗の可能性を考慮し、中間くらいの価格帯を検討
  • ブラックフライデーの割引がないものは慌てて買う必要がない
    • これを踏まえるとだいたい本当に良い高いものとものすごく安いものは除外される

という考え方でざっくり探した。

するとちょうどよい価格帯で Creative Stage SE mini が見つかった。ただし、もう Type-C ポートが空いていなかったので増やすために Belkin の USB ハブも追加で購入することになった。(USB-C ハブは割引対象外。)

おまけ - 現在の構成

使ってみて

  • USB 1本で繋がるのはやはりとても快適。PC 本体側は何も変わらない
  • 音が入らないと自動的に接続が切れるっぽく、再接続にやや時間が掛かる(スタンバイからの復帰時などは特に)
  • ボリュームの調整を物理ダイヤルでできるようになったので、これがけっこうありがたい
    • ノート PC 本体のキーボードを使っている場合はともかく、クラムシェルモードではボリューム調整に難儀していたのでマジ助かる
  • 当たり前だがやや距離のあるクラムシェルモードのノート PC スピーカーよりは目の前に置いたサウンドバーは格段に聞きやすい。ただし、なんとなくこもった感じはする1
  • まだミーティングはしていないので肝心の部分の評価はできていないが、YouTube のニュース、音楽、ゲーム実況などを本体スピーカーと聴き比べる限りはまぁ心配なさそう。男性の低い声はちょっと聞き取りにくいかもしれないけど、まぁブラウザ拡張にイコライザありそうだし、どーしても困ったらそういうのも考えるか。

USB-C ハブの方が高かったことを除けば、とてもよい買い物をしたと思う。

  1. まったくの主観だが、自分はこのこもった感じが気になりやすい方だと思う。ただ https://av.watch.impress.co.jp/docs/series/zooma/1536312.html レビュー記事でも同様の評価なので、まぁそんなもんなんだと思う 

About

例によって個人のなんちゃらです