Posts for: #Container

おいしい 🦀 を食べに行く

22時頃に寝てしまって1時に起きて5時に起きて6時過ぎに起きた。とくになにもしていないのにバテている気がする。今週はずっと mongodb のレプリカセットの調査やインフラの移行作業などをやっていたせいか、普段よりもエネルギーを消費しているのかもしれない。朝から疲労困憊でオフィスへ向かった。

docker のコンテナネットワークの調査

docker のコンテナネットワークから解決できる名前がなになのか、よくわかってなくて、その調査のためにサンプルの compose サービスを作った。

myimage から nginx のコンテナの名前解決がどうなるかを試してみる。

c67a5ca94a77:/app# dig +short 00c719491558
192.168.240.3
c67a5ca94a77:/app# dig +short mynginx
192.168.240.3
c67a5ca94a77:/app# dig +short nginx
192.168.240.3
c67a5ca94a77:/app# dig +short yournginx
192.168.240.3

基本的にはサービス名、コンテナ名 (container_name)、コンテナー ID、ホスト名 (hostname) はすべて名前解決できる。hostname があるときはそのコンテナの /etc/hosts にその名前が追加され、ないときはコンテナ ID が追加されていた。

yourcontainer:/app# cat /etc/hosts
127.0.0.1	localhost
...
172.18.0.3	yourcontainer

冬の開発合宿の準備

日程を決めたのが5月末 で、うちの会社のワークスペースに slack のチャンネルを開設したのが10月。現時点で7人の参加者がいる。もうこのメンバーでいいかなと考えている。今回はコミュニティのワーケーションイベントというより、自社の開発合宿という体をとっている。スポンサーとしていくらか会社からお金も出す。その理由の1つは slack チャンネルにログを残したいという意図がある。コミュニティの slack だとフリープランになるので3ヶ月以上過去のログがみえなくなってしまう。それを解消するには自社の有料プランの slack チャンネルに置いておくのがもっともログを制御できて嬉しい。

城崎温泉では11月から 🦀 が解禁となって、今年は冬に行くので 🦀 を食べるというのも目的の1つ。チャンネルで盛り上げようと、たまに城崎温泉の記事を貼り付けたりしていた。そろそろ、メンバーと顔合わせの情報共有の打ち合わせをしようと思って調整さんを作った。他の人たちは、わざわざうちの slack のワークスペースにゲスト参加しているから、あまり無理強いをせずに情報共有できるようにしておきたい。たった1つの、ほとんどやり取りしないチャンネルのために slack のワークスペースをオープンしておかないといけないという用途はなかなか面倒だ。私が逆の立場でもそう思う。どうにか普段使っているワークスペースから、必要なときだけ連携できるような仕組みがないだろうか?

年末・年始の情報共有の打ち合わせへ向けて旅のしおりも準備していく。日々の業務に忙殺されて後回しにしがちなので自分を追い込むためにも予定を入れた。

コンテナイメージの移行

1時に寝て3時に起きて6時半に起きた。スマホで呪術廻戦のゲームを開いたまま寝てた。

サードパーティの mongodb コンテナへの移行

昨日の mongodb のサードパーティのコンテナイメージ調査 の続き。

レプリカセットの削除

基本的に一度作ったレプリカセットを削除することはないせいか、レプリカセットを削除するユーティリティは提供されていない。なんらかの理由でレプリカセットを再作成したいときは、レプリカセットの設定が保存されている local database を削除する。

またレプリカセットの稼働中に local database を削除することはできないため、mongod サーバーを --replSet を指定していない状態で起動させ、そのときに次のようにして local database を削除できる。

test> use admin
admin> db.grantRolesToUser("root", ["__system"]);
{ ok: 1 }
admin> use local
switched to db local
local> db.dropDatabase()
{ ok: 1, dropped: 'local' }
local> use admin
switched to db admin
admin> db.revokeRolesFromUser("root", ["__system"]);
{ ok: 1 }

コンテナを使ったレプリカセットの初期設定

bitnami/mongodb を使うと、ローカルのシングルノードでレプリカセットを使うには次のような設定になる。

  mongo:
    image: docker.io/bitnami/mongodb:7.0.1
    user: root  # デフォルトは非 root ユーザーで起動するのでローカルの開発環境なら root で実行した方が手間がない
    volumes:
      - ./volumes/mongodb:/bitnami/mongodb
    environment:
      MONGODB_ROOT_USER: "${MONGO_USER}"  # 認証ユーザー
      MONGODB_ROOT_PASSWORD: "${MONGO_PASSWORD}"  # 認証ユーザーのパスワード
      MONGODB_ADVERTISED_HOSTNAME: "mongo-primary"  # レプリカセットのノードを ip アドレスではなくホスト名で指定する
      MONGODB_REPLICA_SET_NAME: "myrs"  # レプリカセットの名前
      MONGODB_REPLICA_SET_MODE: "primary"  # プライマリノードとして設定
      MONGODB_REPLICA_SET_KEY: "my/replication/common/key123"  # キーファイルのコンテンツ (base64 でデコードできる値)
      MONGODB_SYSTEM_LOG_VERBOSITY: 0  # ログレベル
    hostname: mongo-primary  # コンテナの内外から解決できるホスト名を指定
    container_name: mongo  # コンテナ名 (docker container ls で表示される名前)
    ports:
      - 27017:27017  # レプリカセットを運用する場合はポート番号のマッピングを一致させる必要がある
    restart: "always"

この設定でレプリカセットを初期した場合、レプリカセットの initialize 処理は、次のような config/member をもつ。

members: [{ _id: 0, host : "mongo-primary:27017", priority: 5 }]

コンテナの内部からは mongo-primary というホスト名に対して、コンテナネットワーク内のローカル ip アドレスが解決される。

c67a5ca94a77:/app# dig +short mongo-primary
192.168.240.3

ここで host os 上のアプリケーションから mongo コンテナに対してレプリカセット接続をする場合 replicaSet=${レプリカセットの名前} のパラメーターを追加する。

mongodb://root:password@localhost:27017/?authMechanism=DEFAULT&replicaSet=myrs

これは localhost:27017 にレプリカセットの接続を試行し、接続できるとレプリカセットのメンバーが返される。

レプリカセットのメンバーには mongo-primary:27017 という設定が行われているため、mongo-primary というホスト名に対して host os 上で名前解決できる必要がある。そのために /etc/hosts に次の設定を行う。

$ sudo vi /etc/hosts
...
127.0.0.1 	mongo-primary

compass で接続した場合、レプリカセット接続であれば、レプリカセットの名前が接続情報として表示される。

ダイニングテーブル引き取り

実は火曜日にも長机を引き取りに行ってきて、今日はダイニングテーブルを引き取りに行ってきた。この3日間で2つもテーブルが手に入った。いつも目ぼしいと思ったものは、すぐに他の人と取り引きが成立してしまうのに、たまたま続けて私と取り引きが成立した。車で20分ぐらいの距離のマンションまで引き取りに行った。20時の予定を、19時10分には着いてしまって、先方も快く対応してくれた。私よりも見た目すこし年配の方で人当たりのよい感じの方だった。ジモティのやり取りはその人の性格が出るもので、受け渡しだけささっとやって余計な話しはしないパターンもあれば、愛想よく話しながら受け渡しをするパターンもある。先方によると、大事に使っていたテーブルのようにみえるので私も離れのオフィススペースで大事に使おうと思う。

mongodb のサードパーティのコンテナイメージ

23時に寝て3時に起きて寝たかどうか覚えていないうちに6時半になっていて7時半に起きた。

json を介した go の bool 値のバリエーション

go-playground/validator のバリデータには required というバリデーションオプションがある。しかし、このオプションは go のゼロ値でないことをチェックするという仕様になっている。bool のゼロ値は false となるため、リクエストした JSON データに false を設定していたのか、未設定だったのかの違いを検出できない。これはバリデータの問題ではなく、go の json ライブラリの制約のようなもので使い勝手のよい仕様とは言えない。私もこの振る舞いに起因する不具合に遭遇したこともあるし、こういうときにどうしたらよいかも過去に3回ぐらいは調べている気がする。

現時点での私の最適化は次のコードになる。データ構造として *bool 型にすれば、ポインタ型のゼロ値は nil となるため、true, false, nil の3値でバリデーションできる。しかし、私はこのデータ構造を好ましく思わない。というのは、内部的には true/false の2値でしか管理しないメンバーを、json のバリデーションのためだけに nil も許容する3値にすることがよい設計だと私は思えない。そこでバリデータによるバリデーションは諦めて、json の Unmarshal 処理をフックしてバリデーション相当の処理を自分で実装する。このやり方のデメリットはメンバーが追加されたときに自分で UnmarshalJSON() メソッドを保守する必要がある点になる。しかし、メリットとして内部のデータ構造の型は bool 型で扱える。一概にどちらがよいとは言いにくいかもしれないし、設計上の好みかもしれない。

type reqMyData struct {
	Name       string `json:"name"`
	View       *bool  `json:"view"`
}

type MyData struct {
	Name       string `json:"name"`
	View       bool   `json:"view"`
}

func (d *MyData) UnmarshalJSON(data []byte) error {
	var tmp reqMyData
	if err := json.Unmarshal(data, &tmp); err != nil {
		return fmt.Errorf("failed to unmarshal as reqMyData")
	}
	if tmp.View == nil {
		return fmt.Errorf("required view field")
	}
	d.Name = tmp.Name
	d.View = *tmp.View
	return nil
}

サードパーティの mongodb コンテナイメージ

先日の mongodb のレプリカセット調査 の続き。コードレビューをしていて bitnami/mongodb というサードパーティのコンテナイメージを使った方がよいのではないか?というコメントがあったのでその調査をしてみた。VMware 社が提供しているサードパーティのコンテナイメージらしい。

MongoDB(R) is run and maintained by MongoDB, which is a completely separate project from Bitnami.

まず MongoDB プロジェクトとはまったく別管理であることが書いてある。

Bitnami イメージを使用する理由

  • Bitnamiはアップストリームソースの変更を綿密に追跡し、自動化されたシステムを使用してこのイメージの新しいバージョンを迅速に公開します。
  • Bitnami イメージでは、最新のバグ修正と機能をできるだけ早く利用できます。
  • Bitnamiのコンテナ、仮想マシン、クラウドイメージは、同じコンポーネントと構成アプローチを使用しているため、プロジェクトのニーズに応じて形式を簡単に切り替えることができます。
  • Bitnamiのイメージはすべて、minideb(最小限のDebianベースのコンテナイメージ)またはscratch(明示的に空のイメージ)をベースにしています。
  • Docker Hubで利用可能なすべてのBitnamiイメージは、Docker Content Trust(DCT)で署名されています。DOCKER_CONTENT_TRUST=1 を使用して、イメージの完全性を確認できます。
  • Bitnamiコンテナイメージは定期的にリリースされ、最新のディストリビューションパッケージが利用可能です。

MongoDB®を本番環境で使用したいですか?Bitnami Application Catalogのエンタープライズ版であるVMware Tanzu Application Catalogをお試しください。

mongo の公式イメージは ubuntu をベースイメージにしている。ubuntu よりは minideb の方が軽いのかな?そしてちゃんと upstream にも追随しているみたい。このベースイメージの違いによるものかは定かではないが、結合テストのイメージも移行してみたところ、10-20秒ほど結合テストの実行時間が速くなった。割合にすると10%程度かな。

KubernetesにMongoDB®をデプロイするには?

Bitnami アプリケーションを Helm Chart としてデプロイすることは、Kubernetes 上で当社のアプリケーションを使い始める最も簡単な方法です。インストールの詳細については、Bitnami MongoDB® Chart GitHub リポジトリを参照してください。

Bitnami コンテナは、クラスタへの Helm Charts のデプロイと管理に Kubeapps と一緒に使用できます。

helm chart も提供しているようで、いずれクラウド版を作るときに MongoDB も k8s 上にデプロイする上でこのことは都合がよいように思える。

レプリケーションを前提とした初期設定があり、entrypoint スクリプトもいくつか読んでみた感じだと、きれいに管理されていて保守もちゃんとやってくれそうにみえる。

昨日、導入したばかりの公式イメージ + 自作スクリプトによるレプリケーション設定を廃止して、Bitnami のコンテナイメージを使うことに決めた。

owner/permission の違うファイルとリポジトリ管理

23時に寝て2時に起きて6時に起きて7時過ぎに起きた。なんか微妙な寝方をした。

先日の mongodb のレプリカセットの調査 の整理をしてマージリクエストを作成した。共通鍵の keyFile をどう扱えばいいのか、わからなくて、一旦コンテナ内の tmp 領域にコピーして、それを entrypoint スクリプトでコピーしてから owner/permission を変更するというやり方で、リポジトリ管理で共有しやすいようにしてみた。entrypoint スクリプトは root 権限で実行されることも理解した。

volumes:
  - ./mongo/keyfile:/var/tmp/keyfile.orig
command:
  - mongod
  - --keyFile
  - /data/keyfile
  - --replSet
  - "myrs"
entrypoint:
  - bash
  - -c
  - |
    if [[ ! -f /data/keyfile ]]; then
      cp /var/tmp/keyfile.orig /data/keyfile
      chmod 400 /data/keyfile
      chown mongodb:mongodb /data/keyfile

    fi
    exec docker-entrypoint.sh $$@    

テックブログを読む会

昨日、西原さんに教えてもらった テックブログを読むイベント を探したら毎週月曜日に行われているようだった。早速 テックブログ一気読み選手権20231211杯 に参加した。HackMD で読んだメモを管理している。記事を選択して、読んで、所感をまとめて、他の人たちと共有する。ただそれだけのイベント。ちょうど30分で終わって、自分の勉強にもなったし、他の人の話しも聞いて参考になった。たった30分でも、なにもやらないよりずっとよい。1ヶ月ほど参加してやり方を学んだらチームにも展開してみようかと考えている。

mongodb のレプリカセットのデプロイ調査

4時前に寝て6時半に起きた。1時過ぎまで作業して、帰って少しゲームして、うまく眠れなくてだらだらしていた。

mongodb のレプリカセットの調査

以前 mongodb でトランザクションを使うときにレプリカセットが必要 なことがわかった。他機能の開発途中だったので一旦後回しにしていたものを回収している。状況によってはメンバーに委譲してもよかったんだけど、私が遊撃で出張ってみることにした。実際に調べてみてコンテナの運用も考慮するとけっこう難しいことがわかってきた。

mongosh からは Replication Methods を使ってレプリカセットの操作ができる。これはユーティリティのようなもので mongodb としての低レベルのコマンド操作は Replication Commands になる。mongo-go-driver はレプリカセット向けのユーティリティを提供していないため、Replication Commands を RunCommand() の低レベル API を使って自分で実装しないといけない。

例えば、レプリカセットの初期化をするときは次のように replSetInitiate というコマンドを適切なパラメーターで呼び出す。あまりドキュメントで丁寧に説明されていないので試行錯誤でエラーメッセージをみながら実装することになる。とくにはまるのが mongod のサーバーは --replSet myrs のようにレプリカセットを指定して起動させるものの、初期化コマンドを実行するときはまだレプリカセットを設定していないため、レプリカセットを指定せず、且つ direct パラメーターをセットしないと mongod サーバーに接続できない。この微妙な設定を把握するのにはまった。これが正しい手順かどうかもわからないが、ググったりしているとフォーラムでそういったコメントが散見されたりする。おそらく mongosh の Replication Methods を使うと、クライアントからサーバー接続は裏方でよしなにやってくれるのでそっちの方が簡単ではある。

func (r *ReplicaSet) Initiate(ctx context.Context, config bson.M) error {
	client, err := r.connectDirect(ctx)
	if err != nil {
		return fmt.Errorf("failed to connect with direct: %w", err)
	}
	defer client.Disconnect(ctx)

	var result bson.M
	cmd := bson.D{{Key: "replSetInitiate", Value: config}}
	if err := client.Database(r.db).RunCommand(ctx, cmd).Decode(&result); err != nil {
		return fmt.Errorf("failed to run replSetInitiate(): %w", err)
	}
	log.PrettyPrint("completed to initiate", result)
	return nil
}

func (r *ReplicaSet) connectDirect(ctx context.Context) (*mongo.Client, error) {
	opts := options.Client().
		SetAuth(options.Credential{
			Username: r.config.User,
			Password: r.config.Passwd.String(),
		}).
		SetHosts(r.config.Hosts).
		SetDirect(true) // must be true
	return mongo.Connect(ctx, opts)
}

func InitSingleReplicaSet(
	ctx context.Context, cfg *config.MongoDB,
) error {
	rs := NewReplicaSet(cfg)
	initConfig := bson.M{
		"_id": cfg.ReplicaSet,
		"members": []bson.M{
			{"_id": 0, "host": "localhost:27017"},
		},
	}
	return rs.Initiate(ctx, initConfig)
}

さらに mongod サーバーを起動するときに --replSet--keyFile (認証が必要な場合のみ?) という2つのパラメーターを指定する必要がある。--replSet はレプリカセットの識別子を指定する。そして --keyFile は共通鍵を指定する。この共通鍵を生成するには次のようにする。

$ openssl rand -base64 756 > my-mongo-keyfile
$ chown mongodb:mongodb my-mongo-keyfile
$ chmod 400 my-mongo-keyfile

普通のサーバーインスタンスならすぐできることだが、コンテナの運用において面倒なのが owner とパーミッションを設定しないといけないところ。mongo のコンテナは mongodb ユーザーで起動するため、root でマウントされたファイルシステムには書き込みできなかったりして keyFile の配置をどう扱えばよいのかが難しい。docker hub の mongo の issues でもどうやって設定したらいいの?って議論が発散している。mongo 本体が公式のスクリプトや仕組みを提供していれば済む話しだけど、どうもそうではないみたい。だから泥臭い方法で自分でなんとかしないといけないようにみえる。

dockertest でもレプリカセットの設定について次の issue として登録されている。mongo のコンテナを使ったテストの場合、dockertest のレイヤーが挟まるのでさらにわかりにくくなっている。テストを動かすためにどういった設定が必要かは把握できたのでなにかよい方法を考えてコントリビュートしたい。

インフラの式年遷宮

1時に寝て何度か起きて5時に起きた。それからだらだらして寝てまた7時に起きた。

テスト環境の再整備と rootless コンテナ

インフラの式年遷宮のようなことをしていて、テスト環境をリファクタリングして再整備していた。これまで root でコンテナを実行していたが、最近は rootless コンテナがセキュリティ強化の観点から望ましいということで次のドキュメントをみながら設定した。

設定はとくに難しくないが、dockerd や containerd の起動を systemd のユーザーインスタンスに依存することになる。systemd のユーザーインスタンスは基本的にユーザーがログインしたときに生成されるものなので OS が再起動したときなどに困る。OS 再起動時にも systemd のユーザーインスタンスを生成するには linger という仕組みを有効にすればよいらしい。systemd –user の扱いと linger のことまで理解していれば、たぶん大丈夫なのかな?これで運用がうまくいくことを祈りたい。

$ sudo loginctl enable-linger ucidm

コンテナー間のデータ通信と named pipe

22時頃から寝ていて2回起きて3時に起き出して、4時までネットみたりしていて、また寝て6時に起きた。生活のリズムがおかしい。

コンテナー間のデータのやり取り

昨日 モジュール分割 したことにより、いままで1つのモジュールで管理していたが、モジュールを分割したのでそれぞれのバージョンを取得できるとよいという話題が出た。コンテナー内にアプリケーションのバイナリがあり、バイナリを実行するとバージョン情報を取得できる。それぞれのモジュールは独立したコンテナで動いてるため、コンテナー間でその情報を受け渡す方法が必要になる。ググってみると次の so がヒットして named pipe がプラクティスだという。

ホスト os 上の named pipe をコンテナーの volumes でマウントして、それぞれのコンテナーが読み書きすればよい。構築時に named pipe さえ作ったらコンテナー内での読み書きでデータ通信を実現できるため、シンプルでよいんじゃないかと思えた。

mypipe という named pipe を作る。

$ mkfifo mypipe

読み込み用コンテナーのための read-Dockerfile を作る。tail コマンドで named pipe を読む。

$ vi read-Dockerfile
From bash:latest

ENTRYPOINT [ "tail", "-f", "/app/mypipe" ]
$ docker build -t mypipe-read:latest -f read-Dockerfile .

named pipe をマウントして読み込み用コンテナーを起動する。

$ docker run --rm --mount type=bind,source="$(pwd)"/mypipe,target=/app/mypipe,readonly mypipe-read

書き込み用のエントリーポイントのスクリプトはちょっと工夫がいる。おそらく Dockerfile 内で直接リダイレクトの操作ができない (やり方がわからなかった) 。シェルスクリプトを呼び出す形にして、シェルスクリプト内部でリダイレクトにより、named pipe に書き込みする。

エントリーポイントのスクリプトは次のような感じ。eval "$@" で任意のコード実行できるようにちょっと細工。

$ vi myentrypoint.sh
#!/bin/sh

cleanup() {
    echo "cleanup ..."
    exit 0
}

trap cleanup INT TERM

while true
do
    echo "$(date)"
    eval "$@"
    sleep 1
done

書き込み用コンテナーのための write-Dockerfile を作る。先の myentrypoint.sh を ENTRYPOINT として起動させる。

$ vi write-Dockerfile
From bash:latest

COPY myentrypoint.sh /app/
RUN chmod +x /app/myentrypoint.sh

ENTRYPOINT [ "/app/myentrypoint.sh" ]
$ docker build -t mypipe-write:latest -f write-Dockerfile .

適当に乱数を生成する cli を eval 実行させる。

$ docker run --rm --mount type=bind,source="$(pwd)"/mypipe,target=/app/mypipe mypipe-write "tr -dc 0-9 < /dev/urandom | fold -w 8 | head -1  > /app/mypipe"

読み込み用コンテナーで乱数を表示できるはず。

なにも難しくなく、linux の標準の機能を使ってコンテナー間のデータ通信を実現できたことにちょっと驚いた。

go で named pipe を読むときは linux ならば syscall.O_NONBLOCK を指定することで書き込みしていなくてもブロックせずに読める。値を取得できない可能性はあるけど、それが許される要件ならこれで済む。またテックブログにまとめたい。

func readNamedPipe(path string) ([]byte, error) {
	flag := os.O_RDONLY | syscall.O_NONBLOCK
	pipe, err := os.OpenFile(path, flag, os.ModeNamedPipe)
	if err != nil {
		return nil, fmt.Errorf("failed to open path: %w", err)
	}
	defer pipe.Close()
	reader := bufio.NewReader(pipe)
	b, _, err := reader.ReadLine()
	if err != nil {
		return nil, fmt.Errorf("failed to read line: %w", err)
	}
	return b, err
}

issue を作るとストレスが軽減する

お酒飲んで新幹線乗ったせいか、新幹線の中であまり寝られなくて暑くていつもより移動に疲れた。その後1時に寝て何度か起きて7時に起きた。2日酔いではないが、寝起きの気分はよくなかった。

issue を作ることによるストレス軽減

昨日の打ち合わせのメモから議事録を作ったり、そこから新しい issue を作ったりしながら来週の打ち合わせの資料作りをしていた。資料を作っている途中、割り込みでメンバーのコードレビューが入ったりして、あまり資料作りは進捗しなかった。

打ち合わせした内容から issue を作る作業を、私は好きだったりする。何をやってよいかわからない状況というのは苦しい。issue を作ること、要件を言語化したり、背景を調べたり、他の issue との関連付けしたり、そういった手を動かすことがきっかけになって、その issue を明確化していく作業を積み重ねれば時間の経過とともに課題が解決するということを経験的に理解しているからだ。

大雑把に言えば、私にとって、issue さえ作れればその課題解決は優先順位付けと (解決までの) 時間の問題に置き換えられる。あれやらなきゃ、これもやらなきゃ、なにか抜け・漏れがあるんじゃないかと頭の中でもやもやしているものを issue という概念に変換することで考えなくて済むようになっていく過程がストレスを軽減している気もする。

コンテナ勉強会

先日公開したテックブログ とプラスアルファで勉強会をした。コンテナという汎用的な話題だったので CTO から社内向けにアナウンスされて (半業務命令っぽい雰囲気で) いつもより参加者は多かったように思える。10人前後は参加されていた。40分ぐらいで話し終えて20分ほど雑談の時間をとって盛り上がりは微妙だったけど、いくつか意見や質問が出たのでよかったのではないかと思う。

チームのメンバーが発表するときは私がモデレーターの役割をしている。私が発表するときはモデレーター兼発表者になってしまう。モデレーターと発表者を兼任するのはとても難しい。おそらく脳の集中力を向ける先が異なるからではないかと思う。モデレーターは質問者の質問を広げたり、コミュニケーションがうまくいくように手伝ったりする。回答から次の質問を考えたりもする。一方で発表者は自分の調べたことや伝えたいことを聴衆にわかりやすく伝えることのみに注力する。

モデレーターと発表者が同じになってしまうと、自分の説明のどこが伝わっていないのか、質問者の意図を組むにはどうすればいいかといったモデレーターの視点がなくなってしまう。以前 tenntenn さんの個人カンファレンス に参加したときに1人2役でパネルディスカッションをされていて、そのときに同僚からあまりやり過ぎると人格崩壊するから気をつけた方よいといった忠告を受けたと冗談で話されていた意味が理解できた。役者が他人になりきるように、これは兼任じゃなくて1人で2つの人格を演じないといけない。そんな器用なことはそうそうできない。

出張の中日

0時に寝て何度か起きて5時半に起きてテレビで朝のニュースを聞き流しながら7時に起きた。

資料作成

今日はメンバーの1人が休暇だったため、打ち合わせはなしで資料ばかり作っていた。今週のチーム勉強会の発表は私が担当するのでその資料を作ったり、リリースを終えて社内向けにプロダクトの説明のための資料を準備したりしていた。これまでたくさんの資料を作ってきてるので改めて作るというよりは、過去に作ったものを洗練させたり、集めてきて補足する程度の作業になりそうな雰囲気だけわかってきた。

aws app runner の情報収集

App Runner Night !! にオンラインで参加した。AWS Startup Community というコミュニティがあることも知らなかった。顧問のはらさんが LT 発表すると聞いていたのでそれをみようと思ってながらで聞いていたので他の発表はあまりちゃんとみていてない。特別に目新しいことはなかったし、発表の中でもいくつかちょっとそこ怪しいんじゃない?とか思いながら他の作業をしていた。

私も余裕があれば app runner でサービスを動かしてみてその勘所を把握しておきたい。ecs がやりたいことに比べて使いにくいという印象は私もずっと思っていた。実質 k8s 以外のコンテナプラットフォームは aws しかないので app runner がよいものかどうかに関心をもっている。

コワーキングのオンラインイベント

月例のカフーツさんのオンラインイベントに参加した。先月の所感はここ 。今日は「移動」というテーマでいつも通りいとうさんがわーっと話をしていた。この2ヶ月に新しい官民の取り組みが始まったらしい。なんか空気だけでダメそうにみえる。

このサイトでは次の2つの用語を定義している。ブレジャーを初めて知ったけど、発音しにくくて語呂が悪いだろとか思えた。

  • ワーケーション (Work + Vacation)
  • ブレジャー (Business + Leisure)

このサイトにあるワーケーションの実施形態には共感するところもあって次の4つに分類している。IT 業界で多いのは合宿型とサテライトオフィス型かな。

  • 福利厚生型
  • 地域課題解決型
  • 合宿型
  • サテライトオフィス型

あとどういう文脈だったか忘れてしまったが、身体感覚で「芭蕉」を読みなおす。 『おくのほそ道』謎解きの旅 という本を紹介された。能の探求者が書いた独特の視点から松尾芭蕉を取り上げた本らしくて、なんかおもしろそうにみえたのですぐに購入してみた。紙の文庫本しかなかった。読んでみる。