■ - masawadaの日記 を読んで触発され、記録の目的も兼ねて書きます。
一時期、半年ほど1人でリモートワークをしていた時期がありますが、精神に異常をきたしたりしておりません。
— うなすけ (@yu\_suke1994) April 6, 2020
僕自身、一時期半年近くリモートワークをしていたのですが、特に閉塞感がどうこう、というのはありませんでした。(他の要因もあります) ただ昨今の外出自粛な状況になって同様のメンタルを保っていられるかはまた別の話だと思います。
とりあえず最近の状況についてまとめていきます。
「リモートワーク力」というのがあると思います。これは筋力のような身体的なものというよりは、自宅の設備などの話であったり、仕事のスタイルであったりを指して言っています。
僕自身、新卒入社したところでリモートワークが盛んに行われていたこともあり、また将来の展望から、自宅での作業環境についてはそれなりに投資してきています。それはベッドに寝ながら作業をできるようにしたり、身体にあったオフィスチェアを買ったりなどです。これらは数年かけて整えてきたものなので、ここ数ヶ月でいきなりリモートに切り替えるとなると、どうしてもパフォーマンスが落ちたり身体を痛めたり、チームでの仕事がうまくいかなかったり、ということが起こるでしょう。
現時点での作業環境は冒頭画像のようになっています。このPCで通話をしたり、Slackやコラボレーションツールを表示したりして、実際の作業は支給されたマシンを机や膝に置いて行っています。 (手頃な箱を卓上に置いて、その上にマシンを置くことでスタンディングデスクもできます)
この環境のためにベッド上のディスプレイを流用したので、寝ながらの作業はもうできなくなっています。
現在、契約関係にあるのは3社です。このうち1社については感染症の流行以前から完全なリモートワークになっていました。 2社目は、あまり出社しなくてもよい状態だったのが、完全に出社しなくてもよくなりました。 そして3社目(以下A社)では、ここは基本的に出社をしていたのですが、東京都のロックダウン宣言の噂が出た時期あたりから原則としてリモートワークに切り替わりました。
これにより、契約関係のある全ての会社でリモートワークをすることになりました。
一番混乱が大きかったのはA社です。突然リモートワークに切り替わったので、masawadaさんのように家での作業環境が整っていないメンバーがそこそこ居たり、コミュニケーションの方法を検討し直さざるを得なかったりと、多分まだ落ち着いてはいないのかな、という様子を感じています。一番厄介なのがインターネット回線の問題だと思っています。
具体的に起こった問題を挙げます。
A社で、僕が発熱し(COVID-19ではありません)、解熱してから感染防止のため1週間ほどリモートワークをしたときは、ビデオ通話をつけっぱなしにして作業をしていました。これはオフィスのメンバーはオフィスの回線で繋いでいたので問題がなかったのですが、全員自宅勤務に変わってからは、回線の太さやそもそも容量制限のかかっている回線しかなかったりして、ビデオ通話を接続したままということが難しくなってしまいました。いわゆる「空気感」の共有が難しくなったような気がします。
僕も長時間のビデオ会議ということはこれまでやったことがなく、常用のヘッドホンは長時間つけていると耳が痛くなるという問題が発生しました。ひとまず社内でリモートワークにおすすめの機材を教えてもらい、良さそうなものを購入しました。
また、おやつどうする問題があると思います。出社すればおやつが用意してあった環境だと、家で作業するときに口さみしいとか糖分が欲しいのになにもないという状況になりがちです。あとは、用意してあっても飽きるとかですね。 なので、たまたまTwitterでみかけた、スナックミーというサービスを契約してみました。
おやつ体験BOX https://t.co/7oS7mgoJBY のプレミアムドライパイン #うなすけのおやつ #異常独身男性の菓子 #もちぷにゃGET #スナックミー pic.twitter.com/iQnID04uPR
— うなすけ (@yu\_suke1994) April 3, 2020
おやつの好みを選べるし、小分けになってて食べすぎず、美味しいのでオススメです。
全てがつらい。怒っているひとがあまりに多すぎる。特にTwitter。
同感です。これについては、身内しかいないSlackやDiscordでうまいこと発散することで心を穏やかに保つようにしています。公に怒りを増幅させたり、いわゆる冷笑とかをしたりせず、自分自身は普段通りの発言を日々続けていこうと考えています。これは東日本大震災のときの経験が大きいのかもしれません。
ここ最近、食事についてはほとんどUberEatsやChompyなどの出前に頼るか、最寄りのコンビニで済ますようになっています。コンビニ食ばかりだとさすがに飽きがくるので出前を頼りがちですが、それだとどうしても高額になってしまい、これがずっと続くのがよくないことは感じています。
ただ料理をしようにも、コンロが1口しかない狭いキッチンなので、あまり手の込んだものを作ることができません。ホットクックなどを導入するか、キッチンが整った物件に引っ越すこともうっすら考えています。
外に出られない鬱憤については、いわゆる「引きこもり耐性」のある側の人間だと思っているのでそこまで苦ではないですが、イベントが中止になったり中止したりすることがあり、昨今の情勢と重なって気分が沈みがちかもしれません。なので最近は配信をするというていでDJをして楽しんでいます。
圧倒的な実力、この仕事はこの人にお願いしたいという立場になり、リモートワークを認めてもらうことを当初は考えていたが、そういう能力によって待遇に勾配をつけるのもよろしくないように思えてきて、つまり普通にみんながリモートワークを認めてもらえる社会になればいいのに、もしくはそういう会社に勤めればいいという考えに変わってきた。
とある場所でこのような意見を書きました。この、リモートワークが実は可能だったということが判明していき、もっとリモートワークへの障壁が低くなっていくのは、僕にとってはありがたいことです。
また、これを見据えていることもあり、masawadaさんが感じている、終わりが見えないことへの閉塞感というものは、リモートワークに関してはずっと続くことを覚悟していたのであまり感じてはいません。外に出られないのはしんどいですが。
一度引っ越しをしてから地元に戻るのか、今の物件のままでUターンの時期を見計らうかが若干迷いどころですが、いずれは戻りたいです。(実家に、ではない)
完全リモートワークに慣れてから出社生活に切り替わると、通勤の過程がつらくなります。家から出る勇気が必要になります。満員電車は本当にしんどいです。
触発されたといいつつ、書き出してみると「自分は大丈夫ですけど?」みたいな感じになってしまいました。まあ個人差があるということで……
以前、udzuraさんがOCI Runtime Specを簡単にまとめた以下のようなブログを書かれていました。
OCI Runtime Specification を読む - ローファイ日記
この記事にてまとめられているのは 95a6ecf であり、このrevisionから一番近いreleaseはpre-releaseである v1.0.0-rc2 です。
さて、 v1.0.2 のリリースがそろそろということもあり、ここでは簡単のため、v1.0.0-rc2からv1.0.2までの間に入った変更について見てみようと思います。ただし全部は取り上げません。
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc3
rcの間は駆け足で行きます。 Windowsについての記述が追加されています。 #565, #573 それに関してか?consoleのサイズについての情報を格納するfiledが #563 で追加されています。これらはMicrosoftの人によるcommitですね。
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc4
いくつかのresouceに負の値を指定できるようになっています。でもmemory usage limitとかに負を指定できて嬉しいんだろうか? #648
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc5
platformについての記述がREQUIEDに指定されています。 #695 それに関連してWindowsやSolarisについての記述が追加されたり修正されたり。 #673
あ、rc4 で負の値を指定できるようになったいくつかのfieldで、またunsignedに戻されていますね。#704
libseccompのバージョンが v2.3.0からv2.3.2に上がっています。 #705
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc6
最後のrc release。 WindowsでのCPU使用率についての記述がperecnt指定からmaximum指定になっていたり。#777 指定したいパーセントに100を掛けた値を設定するように読めますけども。
やっぱりmemory usageに負の値を指定できるようになりました。-1
を指定するとunlimitedの意味になるようですね。 #876
platformについてのfiledが削除されました。runcでは使用されておらず、image-specのみが気にすることだろうということで? #850
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0
first release!
disableOOMKiller
がmemory section配下に移動しました。#896
breaking chnageとされているのはこれだけ。
https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.1
ほぼほぼwordingやtypo fixですね。当然ですけど。
https://github.com/opencontainers/runtime-spec/pull/1037
v1.0.1に比べるとたくさんあります。 差分は(多分)これ https://github.com/opencontainers/runtime-spec/compare/v1.0.1…c4ee7d1
hookが追加されました。 createContainer
, startContainer
, createRuntime
の3つです。代わりにprestart
がdeprecatedに指定されています。LXCと同じ名前だとか。 #1008
memoryに関してcgroupのuse_hierarchyが使用できるようになっています。 #985 第3回 Linuxカーネルのコンテナ機能[2] ─cgroupとは?(その1):LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社
WindowsにおいてDeviceをschemaに含められるようになっています。 #976
libseccompが v2.4.0になり、SMCP_ACT_LOG
が使用できるようになっています。#1019
syscallのlogを残すようにする設定? http://man7.org/linux/man-pages/man3/seccomp_init.3.html
また、実装の一覧にgVisor、kara-container、crunが追加されています。crunはOCIのC実装で、runcより高速に動作するようです。元々はRedHatのgiuseppe氏による個人project?がContainers org配下に移動しています。 https://github.com/containers/crun
取り上げられていない変更がめちゃくちゃあるので気になった人は直接見てください。
適当なWindowsが動いているEC2インスタンスがあり、それにリモートデスクトップしてもらいたいということが皆さんにもあるかと思います。そういう時、冒頭の画像にあるように、AWSコンソールからEC2インスタンスを作成し、「接続」からの「リモートデスクトップファイルのダウンロード」からダウンロードしたファイルを開くことで、ユーザーのパスワードを入力すればもう接続できる、というお手軽便利機能があります。
しかし、ざっとaws-sdkを眺めてみましたが、このファイルをAPI経由で取得する方法が見当りませんでした。
では、リモートデスクトップで作業してもらう人にAWSのコンソールには入ってほしくない、というときにはどうすればよいでしょう。
ところで、ダウンロードしたRDPファイルを見てみると、中身はテキストになっていました。
auto connect:i:1
full address:s:ec2-192-0-2-1.ap-northeast-1.compute.amazonaws.com
username:s:Administrator
なんとなく自動で生成できそうに見えます。そして、それぞれがどのような値なのかがここに記載されていました。
サポートされるリモート デスクトップ RDP ファイルの設定 | Microsoft Docs
auto connect:i:1
についてはこのドキュメントに記載がないので触らないようにして、full address:s:
には いわゆるPublic DNS (IPv4)
を設定してやればよさそうです。
また接続するユーザーも、 username:s:
で自由に設定できそうですね。
パスワードだけは別で伝えないといけないのは仕方ありませんが、作業のおまかせが手軽にできそうでよかったです。
C96で友人のサークルをお手伝いしているとき、「サークル参加申込書買ってくるけど、どうする?」と聞かれ、勢いで「僕のぶんもお願い!」と言ったのが全ての始まりでした。 この時、そもそもサークルが存在しない状態であり、その上、何を同人誌として頒布するのかなどは何一つ決まっていませんでした。
その後、直近にあった出来事からサークル名を「キリンセル」とし、まずは日々更新しているpixivFANBOXのまとめを冊子にし、余力があればその他にも技術的なことをまとめて本にしようということになりました。
何なんだマジで pic.twitter.com/DeuNKCpVl3
— うなすけ(C97火曜日南リ17a) (@yu_suke1994) July 16, 2019
結果としては余力などなく。
正直なところ、楽観視していました。というのも、本にする内容は既に大量に存在しているからです。
実際にはログインしないと読めない秘密のコンテンツをどのようにローカルにdumpし、組版ツールに流し込むかなどの部分で大幅にてこずりました。
組版自体はRe:VIEWを使うことにし、TechBooster/ReVIEW-Template の構成をベースにしました。ここで大分楽ができました、ありがとうございます。
このとき、印刷会社の入稿締め切りスケジュールを見ながら作業していたのですが、できあがった原稿が200ページを超えることがまだわかっていませんでした。そしていざ入稿しようとすると、「そのページ数では入稿できない」という事態になり、あわてて別の印刷会社を探すことになったりもしました。
入稿締め切りのギリギリまで表紙のデザイン作業をすることになったりもして、余裕をもったスケジュールがどれだけ大切かを思い知らされました。 (ページ数的に背表紙が存在することが判明したのが結構遅かった)
ファンブックは、主体として動いていたのは蜘蛛糸まなさんなので僕はされるがまま、という感じではありましたが、まれに進捗をつついたり、インタビューの文字起こしをしたりなどのお手伝いをやっていました。これも結構ギリギリまで作業することになってしまい、朝5時くらいまで手を動かす日もありました。
上記の作業と平行して、当日必要なさまざまなものの準備をしていました。
当初、交通系ICカードが使えることからCoineyを申請したのですが、審査が通らずSquareの導入となりました。また、審査に必要であることからサークルWebサイトの作成も平行して行っていました。 (このカード決済用端末に使えるので、iPad Proを買ったり……)
他にも、会計用のコインケース、サークルクロス、お品書き用のポスタースタンドなどなどの購入、当日売り子として手伝ってくれる友人(コミケ初参加)のためにどのようなことをすべきか、どのようなスケジュールでの行動かなどをまとめたものの作成、両替など、様々なタスクにずっと追われていました。
あと、告知配信とか。
キャッシュレス決済は、事前告知配信に来ていただいた(であろう)方々や、同業の方々はすぐクレジットカードを出してくださいました。が、イベント全体としてはやはり現金決済が主流なので、はじめは現金で支払おうとした方も多かった印象です。
単純な決済にかかる時間としては、EMV Contactless = pixiv PAY < 現金決済 < Squareカード決済(要サイン) の順で所要時間が短い(早い)印象でした。
このあたりは、iDやQUICPayが使用できるようになるとまた変わるかもしれないですね。
売上げの管理は、クレジットカードと現金による決済はSquareにて一元管理するようにしました。これだと、レポート画面でどの時間帯にどれだけ売上げがあったのかなどの詳細な情報が入手できてとても便利でした。
事前決済はpixiv PAYによるものを、FANBOXまとめのほうでだけ受け付けていました。利用があってよかったです。
当日、ファンカードによるディスカウントはありませんでした。みんな電子書籍で欲しいのか、それとも来れなかったのか…… ただ、事前決済リンクからの購入であればファンカード提示はなくてもよいので、それも若干あるかもしれません。
ほぼ立ちっぱなしの6時間でした。自分のサークルに居たい気持ちとあちこちに挨拶&買い出しに行きたい気持ちとの戦いで、簡単な挨拶でそそくさ退散してしまったブースがいくつもあります。サークル出展って大変ですね。 当日、差し入れを下さった皆さんありがとうございました。全て美味しく頂きました。
コミックマーケット 97 4日目(2019-12-31 火曜) 南リ17a サークル名「キリンセル」にて、以下3冊の同人誌を頒布します。
この同人誌は、僕がpixivFANBOXに投稿しているOSS watchをまとめて時系列順に読めるように編集したものになります。01では 2018年05月から2018年9月末まで、02では2018年10月から2019年3月末までの投稿を集録しています。
(01には、少しだけでしたがpixivFANBOXには投稿していない、社内にだけ公開していた頃のものも収録しています)
また、どちらにも付録として、pixivFANBOXへの投稿をどのようにRe:VIEW形式によるテキストにまとめなおしたかを書き下ろしとして集録しています。
価格は1冊2,000円となります。pixivFANBOXにて支援していただいている方々には、特別に値引きがあります。当日はファンカードを売り子に提示できるようにしてください。詳しくはFANBOXの投稿をご確認ください。
また、物理本が売れ残ったらBOOTHにて販売します。電子書籍版もBOOTHにて販売する予定です。
FANBOXにて支援して頂いている方々には、電子版のPDFを後日配布させていただきますが、500円プラン以上 とさせていただきます。
当日の支払い方法ですが、Squareによるクレジットカード決済 (VISA・Mastercard・American Express・JCB・Diners Club・Discover) またはpixiv PAY、または現金でのお支払いを受け付けております。
なるべくクレジットカードもしくはpixiv PAYでの決済をお願いします
(回線状況によっては現金しか使用できない可能性があります)
取り置きとして、pixiv PAYでの事前決済を受け付けています。以下のQRコードを読み取ってください。当日は受け取りの際にpixiv PAYアプリの購入履歴画面を提示して前払い済みであることを証明してください。
ほとんどの内容を無料で公開しているので、物理の冊子はあまり買われないかも?という予測をし、あまり数を用意していません。どうしても冊子として欲しい!という場合は取り置きをおすすめします。
(もし取り置きのみで用意している分がなくなってしまったら、pixivFANBOXで支援していただいている方のぶんを優先で確保します)
詳しくは28日の配信にて明らかになります!!!!!!
長々と書きましたが、当日、会場でお会いできることを楽しみにしています!
平成Ruby会議01に、発表者として、また当日スタッフとして参加しました。
資料はこれです。
もともと平成.rbのメンバーの一員であったということもあり、平成Ruby会議で何かしらお手伝いできればなと思ってはいたのですが、仕事、プライベート(原稿)などの兼ね合いで当日のみのお手伝いとなりました。 (スタッフ用のchat roomにも参加していましたが、トーク採択には関わっていません)
また別件で、発表内にもあるようにWindows環境でのテストに悪戦苦闘していたこともあり、これで何か話せそうだということでCfPに応募したところ採択されたので、発表者としても参加することができました。
懇親会で、このような会に参加するのが初めての方や学生の方が多く、「平成」の名を冠することが良い方向に働いたようでとてもよかったです。
また個人的には、Re:VIEWについて高橋会長にご挨拶できたこと、 #unasukefm まだですかという声を沢山頂けたことが、もう、たまらなく嬉しかったです。
あ、あとこれ。
エモ散らかしてて限界なんだが #heiseirubykaigi https://t.co/SgSXIRv1bp
— うなすけ(C97火曜日南リ17a) (@yu_suke1994) December 14, 2019
ChromeがNative lazy loadingをサポートするようになったので、僕のblogでもこれを使おうと作ってみたgemになります。
Chrome v76から、Native lazy loadingがサポートされるようになりました。
Native lazy-loading for the web
ところで僕のblogは、本文をMarkdownで記述したものをHTMLに変換しています。Markdown記法で画像を挿入した場合に、どのようにloading属性を付与すればいいのでしょうか。Markdown内にHTMLを記述した場合、それはそのまま出力されるので、手でタグを書くことで実現できますが、果たしてそのようなことをしたいでしょうか。面倒です。
なので、Markdownの変換過程に介入することで解決できないだろうかと思い、調べてみました。
僕のblogでは、Markdown engineとしてRedcarpet gemを使用しています。そして、RedcarpetにはCustom Rendererという仕組みがあります。これで、
の変換に介入します。
Railsでカスタムmarkdownを実装する - k0kubun’s blog
class CustomRenderer < ::Redcarpet::Render::HTML
def image(link, title, alt_text)
"<img loading=\"lazy\" src=\"#{link}\" alt=\"#{alt_text}\" />"
end
end
上記のようなコードで、 に loading attrを付与することができます。そして、それをgemにしたのがこれです。
実際には loading 属性には lazyの他にも autoとeagerを指定できるので、gemでもRendererをそれぞれ使い分けることでlazy以外を指定できます。 (なのでgem名にlazyと入れたのはちょっと失敗だったかもしれない)
ここまでが表参道.rb #51 での発表内容になります。
ところで、この手法は上手くいきませんでした。実際にこのgemを使用してblogをdeployすると、画像が全てリンク切れとなってしまったので、急いでrevertしてdeployをし直しました。
この原因は、Middleman側の設定である asset_hash
を有効にしていたためです。この設定によって尊重されるべきMiddleman側のCustom Rendererを自分のgemで上書いてしまっていたために、画像のsrcが正しくないものになってしまっていました。
asset_hash
を有効にしたまま loading="lazy"
をするには、もう変換後のHTMLを編集するMIddleman pluginを作成するしかなさそうです。
という訳で、after_build
のタイミングで以下のようなコードを実行するようなgemを作成しました。
def after_build(builder)
files = Dir.glob(File.join(app.config[:build_dir], "**", "*.html"))
files.each do |file|
contents = File.read(file)
replaced = contents.gsub(%r[<img], "<img loading=\"#{options[:loading]}\"")
File.open(file, 'w') do |f|
f.write replaced
end
end
end
このコードは、build directory 以下に存在する .html
ファイルについて、全ての <img>
タグに対して loading 属性を付けて上書き保存します。
ここまでが表参道.rb #52 での発表内容になります。
<img>
を除外するこの実装では、 pre や code の内部の img にも loading 属性を付与してしまいます。これはどうやって解決するか悩んだのですが、Nokogiriによって親に pre 、 code 、blockquote がある img に関しては属性を編集しない、というように処理を変更しました。
これで、ようやく僕のblogでlazy image loadingが実現できました。といってもChrome v76以降のみですが。
ということで、Starやpull reqなど頂けると大変ありがたいです。
スーツケースを持っていなかった(Dockercon 2016のときに使っていたのは帰国時に壊れた )ので、RubyKaigiや帰省などの遠出のときには、少し大きいトートバッグ のなかに全部詰めこんでいました。
ふつうの帰省時にはこれで問題なかったのですが、冠婚葬祭で礼服も持ち帰らないといけないときに、このスタイルだと礼服だけ別で持つ必要があり、移動がとても大変でした。
さすがにスーツケースが欲しいなと思いはじめたのは、まつもとりーさんのnoteを読んでからでした。
これを見て、REMOWAのスーツケースよさそう、とはなったのですが、新規に購入するとなると思ったより高価なので、とりあえずレンタルしてRubyKaigi 2019で使ってみました。
また、そのときにhmskさんが使っていたスーツケースを見て、これもいいなと思って調べたところ、REMOWAほど高価でなく手が届きそうなので迷いがでてきました。デカいスーツケース、荷物をたくさん入れられて便利!!!!!!!!!!!!!!!!!!!!!!!!!!!!
— うなすけ (@yu_suke1994) April 14, 2019
これから結婚式など礼服が必要になるイベントが増えることを考えると、スーツケースは確実に必要なので、現時点で手が届くAwayのものを買うことに来めました。機内持ち込めてバッテリーとラップトップ用のスリーブが付いたAway届いた。かわいい。 https://t.co/M8XUZU0nYL pic.twitter.com/IciROgwXMC
— Kengo Hamasaki (@hmsk) March 27, 2019
スーツケース、まつもとりーさんオススメのREMOWAはちょっと高価が過ぎるのでhmskさんの使ってるAwayにしようと思ったが日本に発送できなそうでア
— うなすけ (@yu_suke1994) May 31, 2019
ただ公式では日本への発送はしておらず、BUYMAを利用して代理購入 → 日本への発送 という手続を踏みました。
https://www.awaytravel.com/suitcases/bigger-carry-on-pocket/asphalt
これです。
大きすぎず、小さすぎずちょうどいいサイズで気に入ってます。
Container Runtime Meetup #1 - connpass に参加して NOTIFY_SOCKET
について調べたことを話してきました。
この記事ではその内容の書き起こしと、その場で行われた会話についてのメモについて書きます。
@udzuraさんにそそのかされたことがきっかけです。
@yu_suke1994 情報です https://t.co/U5zsvUlz30
— Uchio KONDO 🔫 (@udzura) August 27, 2019
あまりよくないExecuteをすると、普段はRails APIを運用していてRubyしか書いておらず、Goも数年前にCLI toolを作った程度で、GoやLinuxのコンテナ回りに詳しいという訳ではありません。
connpassのイベント概要に
少人数の輪読形式です。「参加枠1」の方々にはあらかじめ「runc run」周辺のコードをざっと読んできてもらい、当日、それに関連するトピックをそれぞれ発表して頂きます。「聴講のみ」の方々は、発表の必要はありません。
とあったので、その時点での最新リリースである v1.0.0-rc8 を対象に読むことにしました。
https://github.com/opencontainers/runc/releases/tag/v1.0.0-rc8
runc run
が実行されたとき、呼び出される実体は run.go だろうとアタリをつけ、周辺を読んでいきます。
status, err := startContainer(context, spec, CT_ACT_RUN, nil)
if err == nil {
// exit with the container's exit status so any external supervisor is
// notified of the exit with the correct exit status.
os.Exit(status)
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/run.go#L76
まずここで startContainer
によりContainerがstartするものと思われます。中を見ていきます。
func startContainer(context *cli.Context, spec *specs.Spec, action CtAct, criuOpts *libcontainer.CriuOpts) (int, error) {
id := context.Args().First()
if id == "" {
return -1, errEmptyID
}
notifySocket := newNotifySocket(context, os.Getenv("NOTIFY_SOCKET"), id)
if notifySocket != nil {
notifySocket.setupSpec(context, spec)
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/utils_linux.go#L405-L414
startContainer
内部、 411行目にて os.Getenv("NOTIFY_SOCKET")
としている部分があります。この環境変数は何でしょう?気になったので、ここを掘っていきました。
この時点で僕の NOTIFY_SOCKET
に対する認識は、
「環境変数がある状態で起動させると色々な通知が飛んでくるのだろうか?」
くらいのものでした。
では、 newNotifySocket
で何が行われているかを見ていきます。
func newNotifySocket(context *cli.Context, notifySocketHost string, id string) *notifySocket {
if notifySocketHost == "" {
return nil
}
root := filepath.Join(context.GlobalString("root"), id)
path := filepath.Join(root, "notify.sock")
notifySocket := ¬ifySocket{
socket: nil,
host: notifySocketHost,
socketPath: path,
}
return notifySocket
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/notify_socket.go#L23-L38
この関数の返り値として、 notifySocket
構造体のインスタンス(のポインタ?)が得られます。
ちなみに notifySocket
構造体はこのように定義されています。
type notifySocket struct {
socket *net.UnixConn
host string
socketPath string
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/notify_socket.go#L17-L21
ところで newNotifySocket
関数の引数として渡される context *cli.Context
は何でしょうか。
これはruncが採用しているCLIツール用パッケージ https://github.com/urfave/cli で定義されている Context 構造体を指しています
https://godoc.org/github.com/urfave/cli#Context
startContainer
では、 newNotifySocket
を呼んだ直後に、返ってきた notifySocket
に対して setupSpec
を呼んでいます。これも見ていきます。
// If systemd is supporting sd_notify protocol, this function will add support
// for sd_notify protocol from within the container.
func (s *notifySocket) setupSpec(context *cli.Context, spec *specs.Spec) {
mount := specs.Mount{Destination: s.host, Source: s.socketPath, Options: []string{"bind"}}
spec.Mounts = append(spec.Mounts, mount)
spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", s.host))
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/notify_socket.go#L44-L50
この関数のコメントにもあるように、systemdが何か関係していそうだということがわかりました。
ここでの処理は runtime-spec を読むとわかりそうです。とりあえず、Process.Env
に対して NOTIFY_SOCKET
環境変数を追加しているようです。
startContainer
に戻ると、 createContainer
を呼んだあとに notifySocket.setupSocket()
を呼んでいます。これを見ていきます。
func (s *notifySocket) setupSocket() error {
addr := net.UnixAddr{
Name: s.socketPath,
Net: "unixgram",
}
socket, err := net.ListenUnixgram("unixgram", &addr)
if err != nil {
return err
}
s.socket = socket
return nil
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/notify_socket.go#L52-L65
net.UnixAddr
とは何でしょうか。これの実体は https://golang.org/pkg/net/#UnixAddr にあります。
type UnixAddr struct {
Name string
Net string
}
ここでの unixgram
は datagram socketを指すようで、UDPのような送りっぱなしのプロトコルのようです。
( https://github.com/golang/go/blob/master/src/net/unixsock_posix.go#L16-L27 の syscall.SOCK_DGRAM
を参照 )
net.ListenUnixgram
によってconnectionを張り、それを notifySocket.socket
に格納したものを、 runner
構造体の notifySocket
フィールドに入れています。
type runner struct {
init bool
enableSubreaper bool
shouldDestroy bool
detach bool
listenFDs []*os.File
preserveFDs int
pidFile string
consoleSocket string
container libcontainer.Container
action CtAct
notifySocket *notifySocket
criuOpts *libcontainer.CriuOpts
}
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/utils_linux.go#L254-L267
この後に、 notifySocket
に対して行われている操作は、runner.run
内部で以下のコードを呼んでいる部分があります。
// Setting up IO is a two stage process. We need to modify process to deal
// with detaching containers, and then we get a tty after the container has
// started.
handler := newSignalHandler(r.enableSubreaper, r.notifySocket)
https://github.com/opencontainers/runc/blob/v1.0.0-rc8/utils_linux.go#L305-L308
一旦ここまでをまとめると、
NOTIFY_SOCKET
という環境変数をもとにsoket通信をしている?unixgram
によって通信するものといったところでしょうか。
何やらsystemdが関係していそうなことはわかっているので、単純に NOTIFY_SOCKET
でググってみると、いくつか記事が見付かりました。
freedesktop.orgでは
These functions send a single datagram with the state string as payload to the AFUNIX socket referenced in the \$NOTIFYSOCKET environment variable. If the first character of \$NOTIFY_SOCKET is “@”, the string is understood as Linux abstract namespace socket.
https://www.freedesktop.org/software/systemd/man/sd_notify.html#Notes
「sd_notifyの通信方法 - Qiita」では
systemdのマネージャ(デーモンプロセス)は、起動プロセスの最後の方でsdnotifyという関数を用いて、起動が完了したことをsystemd本体(PID=1)に通知する。(注:sdnotifyは実際にはもっと汎用的なステータス通知に使える。)
https://qiita.com/ozaki-r/items/ced43d5e32af67c7ae04
ざっくりとした理解でいくと、プロセスが起動した、などのステータスの通知に使用されているんだろうということがわかりました。
ここで、「ではDockerの場合はどうなのだろう」と思い、 https://github.com/docker/cli 内をgrepしましたが、見当りません。いや、Dockerはmobyに移行したのでした。 案の定、 https://github.com/moby/moby 内をgrepすると見付かりました。
$ git grep NOTIFY_SOCKET
libcontainerd/supervisor/remote_daemon.go:200: // clear the NOTIFY_SOCKET from the env when starting containerd
libcontainerd/supervisor/remote_daemon.go:203: if !strings.HasPrefix(e, "NOTIFY_SOCKET") {
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:49:// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:53:// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:54:// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:58: Name: os.Getenv("NOTIFY_SOCKET"),
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:62: // NOTIFY_SOCKET not set
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:68: if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go:74: // Error connecting to NOTIFY_SOCKET
https://github.com/moby/moby/search?q=NOTIFY_SOCKET&unscoped_q=NOTIFY_SOCKET
ということは、Dockerを使っているだけでそのようなsocketが作成されているのではないでしょうか。調べてみましょう。
Docker daemonが動作しているマシン上で、systemdが関係していそうなunixドメインソケットの数を出してみました。
$ ss --family=unix | grep systemd | wc -l
110
けっこうな数ありますね。grepする単語を変えてみます。
$ ss --family=unix | grep container
u_str ESTAB 0 0 /var/snap/microk8s/common/run/containerd.sock 21833469 * 21836828
u_str ESTAB 0 0 /var/snap/microk8s/common/run/containerd.sock 21836830 * 21836829
u_str ESTAB 0 0 /var/run/docker/containerd/containerd.sock 23108 * 23106
u_str ESTAB 0 0 /var/run/docker/containerd/containerd.sock 23114 * 23113
u_str ESTAB 0 0 /var/run/docker/containerd/containerd.sock 23110 * 25748
それらしきものが存在しています。
もっと見ていきましょう。dockerdのpidを調べます。
$ ps aux --forest # 抜粋
root 601 /usr/bin/dockerd -H fd://
root 769 \_ containerd --config /var/run/docker/containerd/containerd.toml --log-level info
root 1213 \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/61f9489e17355a4f00594feb5c
root 1230 \_ bash
pid 601
の環境変数を見てみます。
$ sudo cat /proc/601/environ # 改行を入れています
LANG=ja_JP.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/var/lib/snapd/snap/bin
NOTIFY_SOCKET=/run/systemd/notify
LISTEN_PID=601
LISTEN_FDS=1
LISTEN_FDNAMES=docker.socket
INVOCATION_ID=e65738cc4b8f461e968d23c6740a557e
JOURNAL_STREAM=9:22835
確かに NOTIFY_SOCKET
がありますね。
NOTIFY_SOCKET
でsystemdとやりとりしているようだdockerd
には NOTIFY_SOCKET
が与えられていることが確認できたrunc run
を実行したときにもこれは与えられるのか?ここまでがMeetupでの発表内容になります。
ここからは、当日の発表のあと、その場で行われた議論の簡単な書き起しになります。
NOTIFY_SOCKET
が与えられるのは、systemd経由で起動した場合だけで、bashなどから直接 $ runc run
など実行してもこの環境変数が自動的に作成されるということはない。
NOTIFY_SOCKET
を活用できるのであれば、docker-composeにおける pg_isready
などのhackが不要になるんじゃないか?
return
しているだけなので改善の余地はありそう
sd_notify
を使用して自身の状態を通知しないといけないからそれもハードルになるのではないか
Type=notify
がそれらしい2019年5月1日から、個人事業主として株式会社バンクで1日8時間の週4日間で稼動していました。
「週4日労働にしたかった」 ためです。好きなようにコードを書いたり、映画など娯楽に興じたり、心身を養ったりする時間のために、もう1日休日が欲しいという気持ちは2019年になってから心のどこかにずっと引っかかっていました。
ただ、フリーランスになるとは言ってもバンクを離れたくはありませんでした。当時から計画されていた新サービスの実装、まだまだ綺麗にし足りないコード、インフラ構成のキャッチアップ……やりたいことは山ほどありました。
なのでまずは人事の方に相談し、こちらの意向として
ということを伝えました。
結果としてですが、フリーランスとして契約をし直すということになりました。
最初に人事の方に「フリーランスを検討している」という意向を伝えたのが2月28日、面談を行ったのが3月8日、代表の光本さんと話したのが3月15日と19日、そこから総務の方と話し、有休の消化等の兼ね合いで、5月1日からフリーランスとして勤務する、という時系列になっています。
その他、詳細や発表資料などについては https://unasuke.com/activity などにまとめてあります。また各種ポートフォリオサービスへのURLは以下になります。
バンクでの契約が一区切りしたタイミングというのもあり、このタイミングで公開しました。一区切りしたとはいえ、契約更新のタイミングであったというだけで、まだバンクで引き続きお仕事をしています。
( ※ この日記は、フリーランスになった5月頃から、最初の契約更新のタイミングである11月1日に公開するつもりで下書きを作成していましたが、解散発表のタイミングで公開することにしました。 )
これからフリーランスとして仕事をしていくなかで、ずっとバンクだけと関わっていく訳ではないので、 興味のある方は声をかけていただけるとありがたいです。
(解散に伴なって色々あり、来年までは埋まっているかもしれません。状況を見つつ動きたいと思います。)
ただ、将来的に実家のある福井に戻りたいという展望があり、徐々に仕事をリモートで行えるようにしていきたいと思っているので、フルリモートが可能であると(より)嬉しいです。
また「交渉の過程」でも触れたように、「週4日勤務」という条件を満たせるのであれば正社員としてのオファーも嬉しいです。
うなすけです。