ちなみに

火曜日の空は僕を押しつぶした。

Dockerコンテナ内でプライベートリポジトリのGemをBundlerでインストールしたい

tl;dr

  • 認証情報をイメージに残さずにGitHubのプライベートリポジトリのGemをインストールしたい
  • ビルド時にインストールする場合は --mount=type=ssh がおすすめ
  • 実行時にインストールする場合には BUNDLE_GITHUB__COM を使うのがおすすめ

やりたいこと

Docker内で bundle install するときに社内で使っているプライベートなGitHubリポジトリのGemが含まれる場合、なんとかして認証情報を渡す必要があります。 イメージのビルド時にインストールするのか、それとも実行時にコンテナ内でインストールするのかでも方法が違うのでそれぞれ方法を探ってみました。

ビルド時にインストールする場合

何も考えずビルド時にSSH秘密鍵をマウントしてみたり、環境変数やビルド時変数としてGitHubの認証情報を渡したりすると、イメージ内に認証情報を残してしまうことになります。 ローカル開発だとまあいのではとも思うのですが、出来るだけリスクは軽減したいです。 この辺りのことが意識できてない人は去年のはてなインターンで出題された Docker Quiz を解いてみると良さそう。

ここで紹介したいのは BuildKitBuild Mounts を使う方法です。

--mount=type=secret

--mount=type=secret を使うとビルド時にだけ秘匿情報をマウントし、イメージレイヤには残さないということが出来ます。 これを使って秘密鍵をマウントすることでプライベートリポジトリにアクセスしようというのが今回の方法です。

# syntax=docker/dockerfile:experimental
FROM alpine
RUN apk add --no-cache openssh-client git
# GitHubの公開鍵を取得しておく必要がある
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa bundle install

bundle install するときに秘密鍵をマウントするようにした Dockerfile を書いておいて、ビルド時にGitHubに登録している公開鍵の対となる秘密鍵を指定します。

$ docker build --secret id=ssh,src=/path/to/private_key .

2点注意があって、

--mount=type=ssh

--mount=type=secretでも目的は達成出来るのですが、パスフレーズを設定していない秘密鍵を扱いたくないという課題が残ります。 これを解決するには --mount=type=ssh を使って ssh-agent 経由でホストの秘密鍵を利用する方法が使えます。

# syntax=docker/dockerfile:experimental
FROM alpine
RUN apk add --no-cache openssh-client git
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh bundle install

先ほどとほとんど同じですが --mount=type=ssh のところが違います。これによってイメージのビルド時に ssh-agent を経由してホストの秘密鍵にアクセス出来ます。もちろんパスフレーズはホストで入力出来るので安心。

$ ssh-add /path/to/private_key
$ docker build --ssh default .

このようにして ssh-add しておいた秘密鍵を利用してプライベートリポジトリにアクセスすることが出来ます。

また、以下のように秘密鍵を指定することも可能です。

$ docker build --ssh default=/path/to/another_private_key .

ここでも注意点があります。何もしていないと uid=0gid=0 でマウントされるのでroot以外のユーザーを使っている場合は意図した動作にならないという点です。 これは以下のようにマウント時に適切なuidとgidを指定することで解決します。

RUN --mount=type=ssh,uid=1000,gui=1000 bundle install

詳しい使い方は リファレンスマニュアル を参照してください。

実行時にインストールする場合

ビルド時にインストール出来ることは確認出来たのですが、普段の開発フローを考えると Gemfile を更新したときに毎回イメージをビルドしなおすのは手間です。 実行時にインストールしなおせるといいのですが、ビルド時に渡した認証情報はどこにも残っていません。ということで実行時に認証情報を渡す方法を探しました。

ちなみに実行時は標準入力にアクセス出来るので1個1個認証情報を入力すればいいという話はありますが、複数のプライベートリポジトリがある場合に毎回入力するのは手間ですよね。

ssh-agent を利用する方法

--mount=type=ssh と同様に ssh-agent を使うのはどうでしょうか。

r7kamura.com

この方法は確立されていて ssh-agent が用意した通信用のソケットをボリュームとしてマウントしつつ、マウントしたパスを SSH_AUTH_SOCK 環境変数に設定してあげるだけです。

ただしこの方法には問題があって macOS 上では動作しません。

https://github.com/docker/for-mac/issues/410 によると /run/host-services/ssh-auth.sock を指定することで回避出来るようなので以下のようにすることでやりたいことは実現できます。

$ docker run -v /run/host-services/ssh-auth.sock:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent bundle install

詳しい仕組みについてはざっくりと読み飛ばしてしまったので理解出来てなくて、詳しい人いたら教えて欲しいです。 macOS 上で SSH_AUTH_SOCK に指定されているソケットが特殊なもの?みたいな雑な理解です。

BUNDLE_GITHUB__COM を使う方法

ssh-agent を利用しても実現出来ることは分かったのですが、これだと環境依存が発生してしまいます。 もう少しうまい方法はないでしょうか。

Bundler ではGitHubの認証情報渡すのに BUNDLE_GITHUB__COM 環境変数を使うことが出来ます。 これを使うのはどうでしょうか。

この環境変数には user:pass 形式の認証情報も渡せますが、Personal Access Token (PAT) を渡す方が管理しやすいでしょう。 プライベートリポジトリにアクセスしたいので repo 権限をもったPATを生成して以下のようにして渡すことで無事にプライベートリポジトリのGemもインストール出来ました。

$ docker run --rm -e BUNDLE_GITHUB__COM=<YOUR PAT> container bundle install

これまではソースとして SSH プロトコルの形式でURLを指定していましたが、今回はGitHubの認証を使うため HTTP(S) プロトコルで指定する必要がある点が注意です。

Slackのサイドバーを隠す

Cmd+Shilft+D でサイドバーが開閉出来るので、All unreads を表示しておくことでRSSリーダーかのように未読だけを好きなタイミングで読むことが出来る。 サイドバーが出ていると未読が残っているチャネルがハイライトされるので気が散ってしまっていたので快適が訪れました。

f:id:Sixeight:20210429154349p:plain

モザイクだらけで何も分からない様子です。

blog.nishimu.land

Discordをミュートにし忘れていることに気付くために

皆さんはちゃんとミュートにしてますか。

DiscordはKrispを使ったノイズキャンセリングが優秀でマイクをいちいちミュートにしていなくても相手に生活音が伝わらずに快適に会話が出来る。 作業しながら同僚とつないでいて、何か思いついたときにはすぐに発音出来るように常にマイクをオンにしているのが常態化している。

しかし、これがに慣れてくるとマイクが音になっていることを忘れてしまうことがある。 そうなるとBGMに聴いていた曲のサビで熱唱したのを聞かれてしまったり、家族と話している雑な会話がブロードキャストされてしまうという悲劇が起きてしまう。

Discordはよく出来ていてメニューバーにアイコンを出してくれて、マイクがオンになっているときはそれと分かるようになっている。 しかし、たくさん出ているメニューの中の1つの見た目が変わったところでノイズにしかならなくてなかなか気づけない。

先日 Bartender を導入したのだけれど、これを使うと不要なアイコンをメニューバーから消すことが出来る。 これで他のアイコンを削ることで気付きやすくなるかと思ったのだけれど、意外と気付かない。 常に存在するものの見た目がちょっと変わったところで認知外になってしまうらしい。

どうすればいいかと考えていたけど最高のソリューションを思いついた。

Bartender ではメニューバーのメニューを特定の条件でのみ表示することが出来る。 条件として最初に保存していて画像と見た目が変わったら表示というのがあるので、これを使ってマイクがオンになっているときだけアイコンを表示するようにする これで、ミュートにしているときは何も表示されていないが、マイクがオンになっているときだけアイコンが現れるので、あ、今は駄目そうとすぐに気づけるようになった。

f:id:Sixeight:20210428232617p:plain

これが普段の様子

f:id:Sixeight:20210428232701p:plain

これがマイクがオンの時の様子

大変快適なのでお試しください。

blog.nishimu.land

元気

さいきん仕事が終わるとぐったりしていることがあって夜に何も出来ないことが多い。 体力が落ちているというのもあるのだけれど、力の配分が下手というのもありそう。

大事なこともそうでないことも全部で頑張ってしまうので疲れるうえにアウトカムにもつながりにくい。 大事じゃないことはうまく手を抜いて、大事なところを頑張って結果を出しつつ元気にやりたい。

今日はぎりぎり夜も活動できました。

そういえば睡眠の質が崩壊しているのも関係ありそう。

Bartender 4 を導入した

f:id:Sixeight:20210425192356p:plain

メニューバーにいろいろ置きたいのですが、いろいろ置いてあると気になって生産性が下がるという矛盾を抱えていました。 常に見たいのは一部だけのはずなので隠したいという気持ちになってきます。 しかし、macOSはメニューバーを柔軟にカスタマイズすることは出来ないので諦めていました。

一応 Bartender というアプリで実現出来るといことは知っていたのですが、どんくらい効果があるのか疑っていました。

最近、ふと思い立ってえいやと導入してみたところめちゃくちゃ快適だったので常用するようになりました。 記事の先頭に貼ったようにメニューバーがめちゃんこりすっきりします。

隠れているアイテムはメニューバーにカーソルをもっていくと即座に表示されるので使いにくくなることもなくて、見た目と使い勝手が両立されていて快適です。 ショートカットキーで出し入れも出来るので、通知系を見たい場合もキーボードだけでささっと確認できます。 また、トリガーが指定出来るので、例えば通知が来たときだと15秒だけメニューを出すとかも出来てかなり柔軟です。

これは個人的な好みですが、アイコンがダサすぎてメニューバーには出したくないけど設定でメニューバーから消せないものも非表示に出来るのが地味に助かっています。

www.macbartender.com

キーボード2台使い

Holy Panda を潤滑したので The Mark: 65 を組み立てた。 セパレートスペースバーにしようと思っていたけど2uのスタビライザーが足りなかったので6.25uの一般的な形に。

最近は D60 の7uに慣れつつあったので逆に入力がおぼつかなくなっていまっていた。

GMK HENNESSEY をつけたり唯一もっているアルチザンキーキャップをつけたりしたらこういう感じになった。 シンプル!

試しに2台並べて疑似セパレートとしてみたら思ったより快適だった。 まあしかし左手がタクタイルで、右手がリニアなのでかなり不思議な感じではあるのだけれど。

しかし、なぜか Karabiner-Elements が入っていても Modifier Flag Sync が効かなくて困っている。 情報持っている人いたら教えてほしいです。

追記

f:id:Sixeight:20210425013445p:plain

Devicesの設定で同名のキーボードが出ていたがこれを変更すると Modifier flag sync が有効になって無事に2台同時に使えるようになった。

zshのキーバインディング

社内でVSCodeのターミナルで ^A^A^A みたいになって困るみたいな話があって気になったので調べてみた。

In addition to these names, either ‘emacs’ or ‘viins’ is also linked to the name ‘main’. If one of the VISUAL or EDITOR environment variables contain the string ‘vi’ when the shell starts up then it will be ‘viins’, otherwise it will be ‘emacs’. bindkey’s -e and -v options provide a convenient way to override this default choice.

zsh.sourceforge.net

知らなかったけど zleEDITOR 環境変数を読んで良い感じにキーバインディングを判定してくれるらしい。

つまり EDITOR=vim だけ書いておいて、 bindkey -e を書いてないと、ログインシェル以外を起動したときに Emacs キーバンドが使えなくて ^A^H^H みたいな文字列を眺めることになる。 エディターだと Vim キーバインドなのにそれ以外は Emacs キーバインドなのが悪いんだけれど、そういう人は多そう。

具体的にはログインシェルから別プロセスで zsh を起動すると急にバインディングが変わって困る。 他にもVSCodeのターミナルで困る。VSCode環境変数(起動方法によってどこから引き継ぐかは変わる)を引き継いでくれるので EDITOR を設定していると bindkey -v 相当で zle が起動してしまう。

blog.nishimu.land

これをやっているときに一瞬ハマってしまったが深追いしなかったので今回調べてみてやっとすっきりした。