うなすけとあれこれ

2020年04月17日

Rubyのdistroless imageをmagicpakで構築できるのか?

Distroless ruby magicpak

distroless-ruby

こんにちは、趣味でこのようなものを作っている者です。

https://github.com/unasuke/distroless-ruby

作るだけ作って、実用はしていませんけど。

Distrolessとは何か、ということについては以下の記事をご参照ください。

distrolessイメージを使って、ランタイムDockerイメージを作ってみる - Qiita

さて私がこれまでこのimageをどのように作成していたのかと言いますと、この記事に書いたように人力で依存関係を調べて頑張っていました。 Rubyが動くdistroless image は作ることができるのか - Qiita

Ruby 2.6までは順調だったのですが、2.7ではリンクされるライブラリが増えたのかなんなのか、これまでのように単純なバージョンの変更では上手くいかずに手が止まってしまっていました。

そこに登場したのがこのツール、magicpakです。

これを使えば、Rubyが実行するために必要なファイルを列挙でき、distrolessなimageの作成が楽になるのではないかと考え、試してみました。

magicpak -v $(which ruby)

では早速次のようなDockerfileを作成し、buildの様子を眺めてみます。

FROM ruby:2.7.0-buster
ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak
RUN /usr/bin/magicpak -v $(which ruby) /bundle

docker buildが……

Sending build context to Docker daemon   2.09MB
Step 1/4 : FROM ruby:2.7.0-buster as ruby
 ---> ea1d77821a3c
Step 2/4 : ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
Downloading [==================================================>]  4.222MB/4.222MB
 ---> bd6ae35e14fe
Step 3/4 : RUN chmod +x /usr/bin/magicpak
 ---> Running in e75094fba6fd
Removing intermediate container e75094fba6fd
 ---> 8280a91988f3
Step 4/4 : RUN /usr/bin/magicpak -v $(which ruby) /bundle
 ---> Running in 818a39c7466f
[INFO] exe: loading /usr/local/bin/ruby
[INFO] action: bundle shared object dependencies of /usr/local/bin/ruby
[INFO] exe: loading /usr/local/lib/libruby.so.2.7

################ snip #############################

[INFO] exe: using default interpreter /lib64/ld-linux-x86-64.so.2
[INFO] action: bundle executable /usr/local/bin/ruby as None
[INFO] action: emit /bundle
[INFO] action: emit: creating /bundle as it does not exist
[INFO] emit: link /lib/x86_64-linux-gnu/libpthread-2.28.so => /bundle/lib/x86_64-linux-gnu/libpthread.so.0
[INFO] emit: copy /lib/x86_64-linux-gnu/libpthread-2.28.so => /bundle/lib/x86_64-linux-gnu/libpthread-2.28.so
[INFO] emit: link /usr/local/lib/libruby.so.2.7.0 => /bundle/usr/local/lib/libruby.so.2.7
[INFO] emit: copy /usr/local/lib/libruby.so.2.7.0 => /bundle/usr/local/lib/libruby.so.2.7.0
[INFO] emit: link /lib/x86_64-linux-gnu/libdl-2.28.so => /bundle/lib/x86_64-linux-gnu/libdl.so.2
[INFO] emit: copy /lib/x86_64-linux-gnu/libdl-2.28.so => /bundle/lib/x86_64-linux-gnu/libdl-2.28.so
[INFO] emit: link /lib/x86_64-linux-gnu/libm-2.28.so => /bundle/lib/x86_64-linux-gnu/libm.so.6
[INFO] emit: copy /lib/x86_64-linux-gnu/libm-2.28.so => /bundle/lib/x86_64-linux-gnu/libm-2.28.so
[INFO] emit: link /lib/x86_64-linux-gnu/ld-2.28.so => /bundle/lib64/ld-linux-x86-64.so.2
[INFO] emit: copy /lib/x86_64-linux-gnu/ld-2.28.so => /bundle/lib/x86_64-linux-gnu/ld-2.28.so
[INFO] emit: link /lib/x86_64-linux-gnu/libz.so.1.2.11 => /bundle/lib/x86_64-linux-gnu/libz.so.1
[INFO] emit: copy /lib/x86_64-linux-gnu/libz.so.1.2.11 => /bundle/lib/x86_64-linux-gnu/libz.so.1.2.11
[INFO] emit: link /lib/x86_64-linux-gnu/libcrypt-2.28.so => /bundle/lib/x86_64-linux-gnu/libcrypt.so.1
[INFO] emit: copy /lib/x86_64-linux-gnu/libcrypt-2.28.so => /bundle/lib/x86_64-linux-gnu/libcrypt-2.28.so
[INFO] emit: link /lib/x86_64-linux-gnu/librt-2.28.so => /bundle/lib/x86_64-linux-gnu/librt.so.1
[INFO] emit: copy /lib/x86_64-linux-gnu/librt-2.28.so => /bundle/lib/x86_64-linux-gnu/librt-2.28.so
[INFO] emit: link /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2 => /bundle/usr/lib/x86_64-linux-gnu/libgmp.so.10
[INFO] emit: copy /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2 => /bundle/usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
[INFO] emit: copy /usr/local/bin/ruby => /bundle/usr/local/bin/ruby
[INFO] emit: link /lib/x86_64-linux-gnu/libc-2.28.so => /bundle/lib/x86_64-linux-gnu/libc.so.6
[INFO] emit: copy /lib/x86_64-linux-gnu/libc-2.28.so => /bundle/lib/x86_64-linux-gnu/libc-2.28.so
Removing intermediate container 818a39c7466f
 ---> 077d681487ae
Successfully built 077d681487ae

多いですね。これを /bundle にまとめて展開すれば動くのでしょうか?次のようなDockerfileを使って試してみましょう。

FROM ruby:2.7.0-buster as ruby

ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak
RUN /usr/bin/magicpak -v $(which ruby) /bundle

FROM gcr.io/distroless/base-debian10

COPY --from=ruby /bundle /.
RUN ["/usr/local/bin/ruby", "-v"]
RUN ["/usr/local/bin/gem", "install", "sinatra"]

buildしてみると……

# ...snip...
Step 5/8 : FROM gcr.io/distroless/base-debian10
 ---> 5bb0e81ff6e4
Step 6/8 : COPY --from=ruby /bundle /.
 ---> f2a8875bdfdc
Step 7/8 : RUN ["/usr/local/bin/ruby", "-v"]
 ---> Running in 2cce67b240b1
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
Removing intermediate container 2cce67b240b1
 ---> 145cba6957e9
Step 8/8 : RUN ["/usr/local/bin/gem", "install", "sinatra"]
 ---> Running in e445421dbc07
OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/usr/local/bin/gem\": stat /usr/local/bin/gem: no such file or directory": unknown

/usr/local/bin/gem がないようです。確かにmagicpakの対象にしたのはrubyコマンドのみで、gemやbundlerに対しては何もしていません。これらも含めてあげましょう。

FROM ruby:2.7.0-buster as ruby

ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak
RUN /usr/bin/magicpak -v $(which ruby) /bundle

FROM gcr.io/distroless/base-debian10

COPY --from=ruby /bundle /.
COPY --from=ruby /usr/local/bin/ /usr/local/bin # ここを追加
RUN ["/usr/local/bin/ruby", "-v"]
RUN ["/usr/local/bin/gem", "install", "sinatra"]

結果は……

Step 9/9 : RUN ["/usr/local/bin/gem", "install", "sinatra"]
 ---> Running in e638dbdb65fd
<internal:gem_prelude>:1:in `require': cannot load such file -- rubygems.rb (LoadError)
        from <internal:gem_prelude>:1:in `<internal:gem_prelude>'
The command '/usr/local/bin/gem install sinatra' returned a non-zero code: 1

こんどは rubygems.rb がみつかりません。これは /usr/local/lib/ruby/以下にあります。これも含めます。

FROM ruby:2.7.0-buster as ruby

ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak
RUN /usr/bin/magicpak -v $(which ruby) /bundle

FROM gcr.io/distroless/base-debian10

COPY --from=ruby /bundle /.
COPY --from=ruby /usr/local/bin/ /usr/local/bin
COPY --from=ruby /usr/local/lib/ruby/ /usr/local/lib/ruby # ここを追加
RUN ["/usr/local/bin/ruby", "-v"]
RUN ["/usr/local/bin/gem", "install", "sinatra"]

さてどうか……

Step 10/10 : RUN ["/usr/local/bin/gem", "install", "sinatra"]
 ---> Running in 888f7427612a
/usr/local/lib/ruby/2.7.0/yaml.rb:3: warning: It seems your ruby installation is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.
/usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': libyaml-0.so.2: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/2.7.0/x86_64-linux/psych.so (LoadError)

libyamlが見付からないというエラーが出ました。gemコマンドに対してはmagicpakを通してないからでしょうか。ちなみにそれをやってもエラーが出ます。

root@4033859f93d6:/# ./magicpak -v /usr/local/bin/gem /bundle
[INFO] exe: loading /usr/local/bin/gem
[ERROR] error: The executable is malformed: unknown magic number: 7795575320214446371

とりあえず、libyamlを足してやると……

FROM ruby:2.7.0-buster as ruby

ADD https://github.com/coord-e/magicpak/releases/latest/download/magicpak-x86_64-unknown-linux-musl /usr/bin/magicpak
RUN chmod +x /usr/bin/magicpak
RUN /usr/bin/magicpak -v $(which ruby) /bundle

FROM gcr.io/distroless/base-debian10

COPY --from=ruby /bundle /.
COPY --from=ruby /usr/lib/x86_64-linux-gnu/libyaml* /usr/lib/x86_64-linux-gnu/ # ここを追加
COPY --from=ruby /usr/local/bin/ /usr/local/bin
COPY --from=ruby /usr/local/lib/ruby/ /usr/local/lib/ruby
RUN ["/usr/local/bin/ruby", "-v"]
RUN ["/usr/local/bin/gem", "install", "sinatra"]

今度は……

6 gems installed
Removing intermediate container 1a7823880c0d
 ---> 680de9256898
Successfully built 680de9256898
Successfully tagged unasuke/distroless-ruby:2.7.0-buster

sinatraがインストールできました!ここでは省きますが、ちゃんとリクエストも受けつけるようになっています。imageのサイズは次のようになりました。

image size
ruby:2.7.0-buster 842MB
ruby:2.7.0-slim-buster 149MB
ruby:2.7.0-alpine 51.4MB
rubylang/ruby:2.7.0-bionic 359MB
unasuke/distroless-ruby:2.7.0-buster 59.4MB

alpineには敵わないものの、slim-busterのおよそ半分のサイズになりました。まあ、実用性については疑問点が残りますが。

まとめ

magickpakを使うことで、比較的楽にdistroless-rubyのDocker imageを作成することができました(それまでのtry-and-errorはこの比ではなかったので……)。distroless自体は、Goなどのシングルバイナリが動けばいいimageを作るときには便利に使えるのではないかと思います。

GoogleContainerTools/distroless: 🥑 Language focused docker images, minus the operating system.

Tweet
2020年04月17日
2020年04月16日

Arctis 7で通話をしながらDJ配信をする

arctis 7

オンライン飲み会でDJをする

皆さん、自宅待機生活はいかがお過ごしでしょうか。昨今はZoomやDiscordなどでビデオ通話をしながら飲み会をするというのが流行っていますね。 そんな会を盛り上げるために、DJをして会話のBGMをいい感じにしたいということがありますね。 ただ、DJをしながら通話に参加するには、ちょっと色々と工夫しないといけなかったので、それをメモとしてまとめます。

方法

準備するもの

まず前提として、DJはWindows上のrekordbox 5及びDDJ-RRで行いました。 これがmacOSの場合は多分こんな苦労は不要です。あくまでもWindows環境での話になります。 また、試せてはいませんがrekordbox 6でもおそらく同様の手順が使えると思います。

以上!

やりかた

  1. 標準のサウンドデバイスをPCのスピーカーにする
    • Windows sound setting 要はこういう状態ですね
  2. PCのスピーカーの音量を絞っておく
    • ヘッドセットのマイクが音を拾わないようにするためです
  3. ビデオ通話に使用する音声デバイスをArctis 7のChat側にする
    • Discord sound setting Discordだとこのような感じです
  4. rekordboxのサウンド設定をこのように設定する
    • Rekordbox sound setting いわゆる「いつもの」設定
  5. DJコントローラーのPHONESにArctis 7のステレオミニ端子を接続する
    • 「コンソールケーブル」は使いません。フォン端子とステレオミニを繋ぎます。
  6. DJをする
    • この状態だと、CUEがGameサウンドとして、通話の音声はChatとして、MasterがPCのスピーカーから流れる状態になります。
  7. 配信をする
    • 通話に参加しているみんなに聞いてもらう音声はストリーミングサービスのURLを渡すのが簡単だと思います。OBSなどでPCのmasterを配信すれば会話の内容は配信には乗らず、安心しておはなしできます。

最後に

AG03などのミキサーや、物理マシンがもうひとつあればもうすこしうまいことできる気がします。皆さんそれぞれのやり方を公開していただけると有り難いです。

Tweet
2020年04月16日
2020年04月13日

自分がリモートワークに慣れているというだけの話

desk

触発

■ - masawadaの日記 を読んで触発され、記録の目的も兼ねて書きます。

一時期、半年ほど1人でリモートワークをしていた時期がありますが、精神に異常をきたしたりしておりません。

— うなすけ (@yu\_suke1994) April 6, 2020

僕自身、一時期半年近くリモートワークをしていたのですが、特に閉塞感がどうこう、というのはありませんでした。(他の要因もあります) ただ昨今の外出自粛な状況になって同様のメンタルを保っていられるかはまた別の話だと思います。

とりあえず最近の状況についてまとめていきます。

リモートワーク力

「リモートワーク力」というのがあると思います。これは筋力のような身体的なものというよりは、自宅の設備などの話であったり、仕事のスタイルであったりを指して言っています。

僕自身、新卒入社したところでリモートワークが盛んに行われていたこともあり、また将来の展望から、自宅での作業環境についてはそれなりに投資してきています。それはベッドに寝ながら作業をできるようにしたり、身体にあったオフィスチェアを買ったりなどです。これらは数年かけて整えてきたものなので、ここ数ヶ月でいきなりリモートに切り替えるとなると、どうしてもパフォーマンスが落ちたり身体を痛めたり、チームでの仕事がうまくいかなかったり、ということが起こるでしょう。

現時点での作業環境は冒頭画像のようになっています。このPCで通話をしたり、Slackやコラボレーションツールを表示したりして、実際の作業は支給されたマシンを机や膝に置いて行っています。 (手頃な箱を卓上に置いて、その上にマシンを置くことでスタンディングデスクもできます)

この環境のためにベッド上のディスプレイを流用したので、寝ながらの作業はもうできなくなっています。

仕事がどう変わったか

現在、契約関係にあるのは3社です。このうち1社については感染症の流行以前から完全なリモートワークになっていました。 2社目は、あまり出社しなくてもよい状態だったのが、完全に出社しなくてもよくなりました。 そして3社目(以下A社)では、ここは基本的に出社をしていたのですが、東京都のロックダウン宣言の噂が出た時期あたりから原則としてリモートワークに切り替わりました。

これにより、契約関係のある全ての会社でリモートワークをすることになりました。

一番混乱が大きかったのはA社です。突然リモートワークに切り替わったので、masawadaさんのように家での作業環境が整っていないメンバーがそこそこ居たり、コミュニケーションの方法を検討し直さざるを得なかったりと、多分まだ落ち着いてはいないのかな、という様子を感じています。一番厄介なのがインターネット回線の問題だと思っています。

具体的に起こった問題を挙げます。

A社で、僕が発熱し(COVID-19ではありません)、解熱してから感染防止のため1週間ほどリモートワークをしたときは、ビデオ通話をつけっぱなしにして作業をしていました。これはオフィスのメンバーはオフィスの回線で繋いでいたので問題がなかったのですが、全員自宅勤務に変わってからは、回線の太さやそもそも容量制限のかかっている回線しかなかったりして、ビデオ通話を接続したままということが難しくなってしまいました。いわゆる「空気感」の共有が難しくなったような気がします。

僕も長時間のビデオ会議ということはこれまでやったことがなく、常用のヘッドホンは長時間つけていると耳が痛くなるという問題が発生しました。ひとまず社内でリモートワークにおすすめの機材を教えてもらい、良さそうなものを購入しました。

また、おやつどうする問題があると思います。出社すればおやつが用意してあった環境だと、家で作業するときに口さみしいとか糖分が欲しいのになにもないという状況になりがちです。あとは、用意してあっても飽きるとかですね。 なので、たまたまTwitterでみかけた、スナックミーというサービスを契約してみました。

おやつ体験BOX snaq.me

おやつ体験BOX https://t.co/7oS7mgoJBY のプレミアムドライパイン #うなすけのおやつ #異常独身男性の菓子 #もちぷにゃGET #スナックミー pic.twitter.com/iQnID04uPR

— うなすけ (@yu\_suke1994) April 3, 2020

おやつの好みを選べるし、小分けになってて食べすぎず、美味しいのでオススメです。

インターネットの話

全てがつらい。怒っているひとがあまりに多すぎる。特にTwitter。

同感です。これについては、身内しかいないSlackやDiscordでうまいこと発散することで心を穏やかに保つようにしています。公に怒りを増幅させたり、いわゆる冷笑とかをしたりせず、自分自身は普段通りの発言を日々続けていこうと考えています。これは東日本大震災のときの経験が大きいのかもしれません。

生活の話

ここ最近、食事についてはほとんどUberEatsやChompyなどの出前に頼るか、最寄りのコンビニで済ますようになっています。コンビニ食ばかりだとさすがに飽きがくるので出前を頼りがちですが、それだとどうしても高額になってしまい、これがずっと続くのがよくないことは感じています。

ただ料理をしようにも、コンロが1口しかない狭いキッチンなので、あまり手の込んだものを作ることができません。ホットクックなどを導入するか、キッチンが整った物件に引っ越すこともうっすら考えています。

外に出られない鬱憤については、いわゆる「引きこもり耐性」のある側の人間だと思っているのでそこまで苦ではないですが、イベントが中止になったり中止したりすることがあり、昨今の情勢と重なって気分が沈みがちかもしれません。なので最近は配信をするというていでDJをして楽しんでいます。

これからのリモートワークの話

圧倒的な実力、この仕事はこの人にお願いしたいという立場になり、リモートワークを認めてもらうことを当初は考えていたが、そういう能力によって待遇に勾配をつけるのもよろしくないように思えてきて、つまり普通にみんながリモートワークを認めてもらえる社会になればいいのに、もしくはそういう会社に勤めればいいという考えに変わってきた。

とある場所でこのような意見を書きました。この、リモートワークが実は可能だったということが判明していき、もっとリモートワークへの障壁が低くなっていくのは、僕にとってはありがたいことです。

また、これを見据えていることもあり、masawadaさんが感じている、終わりが見えないことへの閉塞感というものは、リモートワークに関してはずっと続くことを覚悟していたのであまり感じてはいません。外に出られないのはしんどいですが。

一度引っ越しをしてから地元に戻るのか、今の物件のままでUターンの時期を見計らうかが若干迷いどころですが、いずれは戻りたいです。(実家に、ではない)

その他

完全リモートワークに慣れてから出社生活に切り替わると、通勤の過程がつらくなります。家から出る勇気が必要になります。満員電車は本当にしんどいです。

まとめ

触発されたといいつつ、書き出してみると「自分は大丈夫ですけど?」みたいな感じになってしまいました。まあ個人差があるということで……

Tweet
2020年04月13日
2020年03月27日

OCI Runtime Spec v1.0.2 is coming soon

Oci runtime spec

以前、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までの間に入った変更について見てみようと思います。ただし全部は取り上げません。

v1.0.0-rc3

https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc3

rcの間は駆け足で行きます。 Windowsについての記述が追加されています。 #565, #573 それに関してか?consoleのサイズについての情報を格納するfiledが #563 で追加されています。これらはMicrosoftの人によるcommitですね。

v1.0.0-rc4

https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0-rc4

いくつかのresouceに負の値を指定できるようになっています。でもmemory usage limitとかに負を指定できて嬉しいんだろうか? #648

v1.0.0-rc5

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

v1.0.0-rc6

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

v1.0.0

https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.0

first release!

disableOOMKiller がmemory section配下に移動しました。#896 breaking chnageとされているのはこれだけ。

v1.0.1

https://github.com/opencontainers/runtime-spec/releases/tag/v1.0.1

ほぼほぼwordingやtypo fixですね。当然ですけど。

v1.0.2 (予定)

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

まとめ

取り上げられていない変更がめちゃくちゃあるので気になった人は直接見てください。

Tweet
2020年03月27日
2020年02月25日

EC2インスタンスにRDPで手軽に接続したい

download rdp file dialog

どういうことがしたいのか

適当なWindowsが動いているEC2インスタンスがあり、それにリモートデスクトップしてもらいたいということが皆さんにもあるかと思います。そういう時、冒頭の画像にあるように、AWSコンソールからEC2インスタンスを作成し、「接続」からの「リモートデスクトップファイルのダウンロード」からダウンロードしたファイルを開くことで、ユーザーのパスワードを入力すればもう接続できる、というお手軽便利機能があります。

しかし、ざっとaws-sdkを眺めてみましたが、このファイルをAPI経由で取得する方法が見当りませんでした。

では、リモートデスクトップで作業してもらう人にAWSのコンソールには入ってほしくない、というときにはどうすればよいでしょう。

RDPファイルの生成

ところで、ダウンロードした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: で自由に設定できそうですね。

まとめ

パスワードだけは別で伝えないといけないのは仕方ありませんが、作業のおまかせが手軽にできそうでよかったです。

Tweet
2020年02月25日
2020年01月01日

初めての同人誌作成、サークル参加を振り返って

ブースの様子

参加を決めるまで

C96で友人のサークルをお手伝いしているとき、「サークル参加申込書買ってくるけど、どうする?」と聞かれ、勢いで「僕のぶんもお願い!」と言ったのが全ての始まりでした。 この時、そもそもサークルが存在しない状態であり、その上、何を同人誌として頒布するのかなどは何一つ決まっていませんでした。

その後、直近にあった出来事からサークル名を「キリンセル」とし、まずは日々更新しているpixivFANBOXのまとめを冊子にし、余力があればその他にも技術的なことをまとめて本にしようということになりました。

何なんだマジで pic.twitter.com/DeuNKCpVl3

— うなすけ(C97火曜日南リ17a) (@yu_suke1994) July 16, 2019

結果としては余力などなく。

FANBOXまとめを入稿するまで

正直なところ、楽観視していました。というのも、本にする内容は既に大量に存在しているからです。

実際にはログインしないと読めない秘密のコンテンツをどのようにローカルに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時間でした。自分のサークルに居たい気持ちとあちこちに挨拶&買い出しに行きたい気持ちとの戦いで、簡単な挨拶でそそくさ退散してしまったブースがいくつもあります。サークル出展って大変ですね。 当日、差し入れを下さった皆さんありがとうございました。全て美味しく頂きました。

振り返ってKPT

Keep

Problem

Try

Tweet
2020年01月01日
2019年12月25日

C97の4日目南リ17aでFANBOXのまとめ本を頒布します

お品書き

概要3行

もっと詳しく

コミックマーケット 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アプリの購入履歴画面を提示して前払い済みであることを証明してください。

取り置きQR

ほとんどの内容を無料で公開しているので、物理の冊子はあまり買われないかも?という予測をし、あまり数を用意していません。どうしても冊子として欲しい!という場合は取り置きをおすすめします。

(もし取り置きのみで用意している分がなくなってしまったら、pixivFANBOXで支援していただいている方のぶんを優先で確保します)

うなすけファンブックについて

詳しくは28日の配信にて明らかになります!!!!!!

長々と書きましたが、当日、会場でお会いできることを楽しみにしています!

Tweet
2019年12月25日
2019年12月16日

平成Ruby会議01参加記

Heiseirubykaigi 01

Speaker and Staff

平成Ruby会議01に、発表者として、また当日スタッフとして参加しました。

資料はこれです。

heiseirubykaigi-1

もともと平成.rbのメンバーの一員であったということもあり、平成Ruby会議で何かしらお手伝いできればなと思ってはいたのですが、仕事、プライベート(原稿)などの兼ね合いで当日のみのお手伝いとなりました。 (スタッフ用のchat roomにも参加していましたが、トーク採択には関わっていません)

また別件で、発表内にもあるようにWindows環境でのテストに悪戦苦闘していたこともあり、これで何か話せそうだということでCfPに応募したところ採択されたので、発表者としても参加することができました。

感想

懇親会で、このような会に参加するのが初めての方や学生の方が多く、「平成」の名を冠することが良い方向に働いたようでとてもよかったです。

また個人的には、Re:VIEWについて高橋会長にご挨拶できたこと、 #unasukefm まだですかという声を沢山頂けたことが、もう、たまらなく嬉しかったです。

あ、あとこれ。

エモ散らかしてて限界なんだが #heiseirubykaigi https://t.co/SgSXIRv1bp

— うなすけ(C97火曜日南リ17a) (@yu_suke1994) December 14, 2019
Tweet
2019年12月16日
2019年11月29日

Middlemanで生成したHTMLの<img>にloading="lazy"を付与するgemを作りました

performance

ChromeがNative lazy loadingをサポートするようになったので、僕のblogでもこれを使おうと作ってみたgemになります。

Markdownの変換に介入する

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という仕組みがあります。これで、![alt text](src) の変換に介入します。

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 での発表内容になります。

omotesandorb #51

生成されたHTMLを改変する

ところで、この手法は上手くいきませんでした。実際にこの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 での発表内容になります。

omotesandorb #52

改変してはいけない <img> を除外する

この実装では、 pre や code の内部の img にも loading 属性を付与してしまいます。これはどうやって解決するか悩んだのですが、Nokogiriによって親に pre 、 code 、blockquote がある img に関しては属性を編集しない、というように処理を変更しました。

https://github.com/unasuke/middleman-img_loading_attribute/pull/1/files#diff-ea964f9b9ef0f5bc6bdab0998e722d4e

まとめ

これで、ようやく僕のblogでlazy image loadingが実現できました。といってもChrome v76以降のみですが。

ということで、Starやpull reqなど頂けると大変ありがたいです。

Tweet
2019年11月29日
2019年10月28日

Awayのスーツケースを買いました

Away

スーツケースがあると便利

スーツケースを持っていなかった(Dockercon 2016のときに使っていたのは帰国時に壊れた )ので、RubyKaigiや帰省などの遠出のときには、少し大きいトートバッグ のなかに全部詰めこんでいました。

ふつうの帰省時にはこれで問題なかったのですが、冠婚葬祭で礼服も持ち帰らないといけないときに、このスタイルだと礼服だけ別で持つ必要があり、移動がとても大変でした。

スーツケースを検討する

さすがにスーツケースが欲しいなと思いはじめたのは、まつもとりーさんのnoteを読んでからでした。

これを見て、REMOWAのスーツケースよさそう、とはなったのですが、新規に購入するとなると思ったより高価なので、とりあえずレンタルしてRubyKaigi 2019で使ってみました。

デカいスーツケース、荷物をたくさん入れられて便利!!!!!!!!!!!!!!!!!!!!!!!!!!!!

— うなすけ (@yu_suke1994) April 14, 2019
また、そのときにhmskさんが使っていたスーツケースを見て、これもいいなと思って調べたところ、REMOWAほど高価でなく手が届きそうなので迷いがでてきました。

機内持ち込めてバッテリーとラップトップ用のスリーブが付いたAway届いた。かわいい。 https://t.co/M8XUZU0nYL pic.twitter.com/IciROgwXMC

— Kengo Hamasaki (@hmsk) March 27, 2019
これから結婚式など礼服が必要になるイベントが増えることを考えると、スーツケースは確実に必要なので、現時点で手が届くAwayのものを買うことに来めました。

スーツケース、まつもとりーさんオススメのREMOWAはちょっと高価が過ぎるのでhmskさんの使ってるAwayにしようと思ったが日本に発送できなそうでア

— うなすけ (@yu_suke1994) May 31, 2019

ただ公式では日本への発送はしておらず、BUYMAを利用して代理購入 → 日本への発送 という手続を踏みました。

購入したモデル

https://www.awaytravel.com/suitcases/bigger-carry-on-pocket/asphalt

これです。

Away

大きすぎず、小さすぎずちょうどいいサイズで気に入ってます。

Tweet
2019年10月28日
古い投稿