うなすけとあれこれ

2019年02月15日

unasuke.fm が始まりました

unasukefm

経緯

一言で表わすと、「ノリと勢い」で始まりました。

音質改善の足しに、とKyashで投げ銭をしたのをきっかけに、あれよあれよと話が進んで、いつのまにかRailsdm podcast Season 2として unasuke.fm をやることになりました。

Railsdm Podcastに投げ銭したい

— うなすけ (@yu_suke1994) 2018年12月24日

2019年からの Railsdm Podcast は、某うなすけさんが聞き手で、毎回ゲストを変えてトークしていくという内容でリニューアルしていく方向です。実質 https://t.co/Yosts9pvuRです。 #railsdm

— カルパス (@yoshi_hirano) 2018年12月24日

Season 2 episode 1

まずepisode 1として、onkさんをゲストに収録を行いました。以下から聞くことができます。

ジングル

KORG Gadget for iOSで作成しました。カルパスさんから頂いたふんわりとしたイメージをもとに作ってみました。

上のはイントロで使ったshort verで、アウトロで使用したlong verは以下です。

機材

そもそも始めたばかりのpodcastでrebuild.fmレベルの環境・質を実現することは現実的ではありません。

Podcasting Guide 2017 – Tatsuhiko Miyagawa’s Blog

それでも、これまでの収録を聴いて「もっとよくできそうなんだけどな」という気持ちになっていたのも確かです。

今回の収録では、僕がそのとき持っていた機材だけで収録を行いました。それらを以下にまとめます。

録音編

録音にあたって、今回は以下の機材を使用しました。

これはさっちんさんに教えていただいたものです。

> https://t.co/pbAOT5yItE

マイクなら絶対これ。tsとかDiscordとかしてても設定ちゃんとすれば周りの音入らない。スピーカーでも全然OK
tsなら音楽流しながらでもボイスチャット出来る。

— 02/09 11:00 🍲 (@sachin21__) 2017年9月21日

購入してから自宅でのボイスチャットに使用していたものをそのまま持ち込んで録音しました。このマイクに関しては、普段の通話で問題になったことがなく(通話相手から何か言われたことがない、という意味)、それなりに安心して収録に臨めました。

収録ではマイクをUni(単一方向のみ集音)にして僕に向けていました。反対側にカルパスさんが居たのですが、カルパスさんの声が入ることがなく綺麗に音声を拾えていました。こちら側の音声についてはそれなりの質で収録できたのではないかなと思っています。

うなすけ君の編集後の音が全体的にかつてないほどクリアなので、クオリティ爆上がりしてる。それとともに今までスマンという気持ちがかなり溢れてる。

— カルパス (@yoshi_hirano) 2019年1月29日

今回onkさんが京都に居るという都合上、Hangout経由で収録しました。そのため、2人が同時に発声しているタイミングだとどちらか(どちらも?)の声が抑えられてしまい、何を話しているのか不明瞭な部分ができてしまいました。これはどうしようもないですね。

また今後ですが、既にある機材の他にもHolyGrailさんの環境を参考に、以下の機材を用意するつもりです。

ここ何ヶ月かかけていろいろ機材を揃えて環境はほぼ整ったので来年のなんらかの活動にご期待ください! pic.twitter.com/HzVtiqKrsk

— HolyGrail / 蜘蛛糸まな🕸️@新人VTuber (@HolyGrail) 2018年12月22日

機材に関してはキリがないので、あまり凝りすぎてもよくないでしょう。上記構成からさらに買い足していったり、上位機種への乗り換えなどはするつもりはありません。たぶんしないと思う。しないんじゃないかな。

自分はVTuberになるために機材に10万弱かけてきたがうなすけくんははたしてどうかな

— HolyGrail / 蜘蛛糸まな🕸️@新人VTuber (@HolyGrail) 2019年1月11日

機材構成に関しては、他のpodcastでの事例が探すと色々出てくるので、それらを参考にしてみるのもいいかもしれません。

podcastの運営に参加することになった結果、沼にはまっていっているように見えるかもしれませんが、オーディオインターフェースは既に所持していましたし、追加で欲しくなったのはPCMレコーダーくらいなものなので沼ではないです。

4月にどういう機材を手元に揃えているのかは誰にもわかりません。

ちょうど先日「Jonanは配信機材をRubyKaigiに持ち込んでいて現地から配信していた。ポッドキャストであれば映像も不要だしオーディオインターフェースとマイクだけで収録が可能なので実質ありとあらゆる場所で収録ができるようになるのでは?」という話をしたところなので期待ができそうですね。

— HolyGrail / 蜘蛛糸まな🕸️@新人VTuber (@HolyGrail) 2019年1月11日

編集編

録音した音声の編集は以下のような環境で行っています。

編集環境に関してはこれ以上のupdateはするつもりはありませんし、してもあまり意味がないかなと思っています。

ただ、マスタリングにあたって、低音域と高音域を削るイコライザーはかませましたが、ノイズ軽減などは今回はしていません。それについては改善の余地があると思います。

今後

今後お話ししてみたい方々をカルパスさんと話して十数人ほどリストアップしています。1年くらいは続くと思います。

#unasukefm の次回の配信は、来週 or 再来週の前半を予定しています。

— Railsdm (@railsdm) 2019年2月15日
Tweet
2019年02月15日
2019年01月30日

[WIP]kibela2esa をつくりました

kibela esa migration params

HolyGrail/kibela2esa: Kibela 2 esa.io

りゆう

やっぱりWIPっていいですよね。

どういうことをしているのか

  1. exportされたmarkdownを読みこむ
  2. exportされた画像を読みこむ(pathと名前だけ持っておく)
  3. 画像をesaにアップロードして、S3のURLを持っておく
  4. markdown内の画像URLをesaのS3 URLに置換する
  5. frontmatterなどの処理や整形した結果のmarkdownをesaに投稿する

できること

(まだ)できないこと

たいへんだったこと

まとめ

esaが好きです。

HolyGrail/kibela2esa: Kibela 2 esa.io

Tweet
2019年01月30日
2018年12月24日

OCI Image Format Specification v1.0.1を読んで

skopeo

まえおき

発端

めちゃくちゃ興味あり〼 https://t.co/gHfAV5rbEU

— うなすけ (@yu_suke1994) 2018年11月30日

頭の中には設計があるんですが、…
OCIの仕様を再確認するところから…

— Uchio KONDO 🔫 (@udzura) 2018年11月30日

とりあえずブログかキータ

— Uchio KONDO 🔫 (@udzura) 2018年11月30日

という訳で、書きました。

OCI Image とは

Open Container Initiativeによって定められた、コンテナイメージフォーマットの標準仕様です。

詳しくは Open Container Initiativeによるコンテナランタイムとコンテナイメージの最初の標準化作業が完了、「OCI v1.0」発表 - Publickey にて。

OCI Imageを触ってみる

現在、OCI ImageをdownloadできるDocker HubのようなWebサイトは知る限りありません。なので、自分でOCI Imageを作成する必要があります。

まずはDocker Imageから

まず、Docker Hubにて公開されているDocker imageをdownloadするところからです。以下のコマンドで、Docker Hubからダウンロードしたimageをtarballとして扱うことができるようになります。

$ docker image pull ruby:2.5.3-slim-stretch
$ docker save ruby:2.5.3-slim-stretch --output ruby_253_slim_stretch.tar

このtarを展開してみましょう。

$ tar -xf ruby_253_slim_stretch

すると、manifest.json というファイルができているので、見てみます。

[
  {
    "Config":"b1c1603e80c648f3ab902b0259ab846a7779d0780124bf9e417dd4b8c3cea296.json",
    "RepoTags":[
      "ruby:2.5.3-slim-stretch"
    ],
    "Layers":[
      "aeff88bcdbbd12ea45c023c45f97b870492092899651c811b2ef26ae7fdf3120/layer.tar",
      "c61a4dce9ddcebd63027d09811998052c9b2cdb3a379c297277cf755dfcf1420/layer.tar",
      "de2944e57fc93c2f354420cb36210fd1181687a990ffd7123600fdaecba3ee83/layer.tar",
      "49c3631e8651776127d66adb995e78af1e2cfc52b7a10a20df0d92d837258419/layer.tar",
      "eb50b8a8210f1b43ff1571598e66b694844b2dcf6fbaa0691e8af6b7c80dcaa7/layer.tar"
    ]
  }
]

なるほど、これはOCI image specを読むとわかるのですが、OCIに定められている形式のJSONではありませんね。

skopeo

ここで、containers/skopeo というtoolを使用して、Docker imageをOCI imageに変換してみます。

$ skopeo copy docker://ruby:2.5.3-slim-stretch oci:ruby-oci:latest

すると、 ruby-oci/index.json というファイルができているので、見てみます。

{
  "schemaVersion":2,
  "manifests":[
    {
      "mediaType":"application/vnd.oci.image.manifest.v1+json",
      "digest":"sha256:a3843587af4f3e838f3e1a10649631144d4dcf4391980b64f3b902d81048057c",
      "size":976,
      "annotations":{
        "org.opencontainers.image.ref.name":"latest"
      },
      "platform":{
        "architecture":"amd64",
        "os":"linux"
      }
    }
  ]
}

なるほど、これは OCI Image Specに定められている image manifest fileですね。

以下、OCI Image Format Specification v1.0.1

自分なりに理解しようと翻訳したもののメモになります。 正確性の保証はないです。誤訳とかあります。最後のほう力尽きてます。


Open Container Initiative Image Format Specification v1.0.1

Overviewで語られていること

high level image manifest にはcontentsとdependencies of the image including the content-addressable(連想?) identity of one of more file system layer changeset archives、展開すると最終的に実行可能なファイルシステムになる

image configuration にはapplication arguments, environmentsなどの情報

image indexには high level manifest list of manifests and discriptorsのpointが含まれる

それらのmanifestsは異なるimageの実装 ←プラットフォームや他の属性によって変化することができる

Build diagram

一度作成されたOCI imageは名前によって探索(discovered)、ダウンロード、hashによる検証、署名による信頼、OCI Runtime Bundleへの展開ができる

(No Title)

Understanding the specification

components of the specは以下を含む

optional featureとしてSignaturesやNamingが仕様に含まれるかもしれない。

OCI Image Media Types

HTTP responseのContent-Typeで上の値を返すなどのように、typeを返すなにかしらの方法を実装してもよい(MAY)、また実装はmedia typeとdigestを期待してよい? 実装は返却されたmedia typeを尊重する必要がある(SHOULD)

Compatibility Matrix

前方・後方互換を可能な限り維持する必要がある。

似た、または関連するmedia typeは以下

Relations

Image indexは複数のImage manifestを持つ。Image manifestとImage JSON(config)は1対1。Image manifestはLayerのtar archiveを複数持つ。 Discriptorは全ての参照を持つ。

OCI Content Discriptors

properties

Digests

こういう形式

sha256とsha512がRegistered algorithmsとされている。sha256はMUSTでsha512はMAY。

Example

{
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "size": 7682,
  "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
  "urls": ["https://example.com/example-manifest" ]
}

OCI Image Layout Specification

OCI Image LayoutはOCI content-addressable blobs と location-addressable references のための directory構造を表す(?) Layoutではtarやzipなどのarchive formats、nfsなどの共有ファイルシステム、http、ftp、rsyncなどのネットワークによるファイル取得を使用してもよい。

あるimage layoutと参照は、manifestと指定された順序で適用されるfilesystem layerとOCI runtime specificationのconfig.jsonへ変換できるimage configurationがあればOCI Runtime Specification bundleを何らかのtoolによって作成できる。(?)

Content

Example

$ cd example.com/app/
$ find . -type f
./index.json
./oci-layout
./blobs/sha256/3588d02542238316759cbf24502f4344ffcc8a60c803870022f335d1390c13b4
./blobs/sha256/4b0bc1c4050b03c95ef2a8e36e25feac42fd31283e8c30b3ee5df6b043155d3c
./blobs/sha256/7968321274dc6b6171697c33df7815310468e694ac5be0ec03ff053bb135e768

$ shasum -a 256 ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51
afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51 ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51

Blobs

Example

$ cat ./blobs/sha256/9b97579de92b1c195b85bb42a11011378ee549b02d7fe9c17bf2a6b35d5cb079 | jq
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7143,
      "digest": "sha256:afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51",
      "platform": {
        "architecture": "ppc64le",
        "os": "linux"
      }
    },
...
$ cat ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51 | jq
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 7023,
    "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270"
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 32654,
      "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
    },
...
$ cat ./blobs/sha256/5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270 | jq
{
  "architecture": "amd64",
  "author": "Alyssa P. Hacker <alyspdev@example.com>",
  "config": {
    "Hostname": "8dfe43d80430",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": [
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    ],
    "Cmd": null,
    "Image": "sha256:6986ae504bbf843512d680cc959484452034965db15f75ee8bdd1b107f61500b",
...
$ cat ./blobs/sha256/9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0
[gzipped tar stream]

oci-layout file

これ。

{
    "imageLayoutVersion": "1.0.0"
}

index.json

必須。image-layoutの参照、descriptorsのentry pointになる。/index.json に置かれる。 "org.opencontainers.image.ref.name" にイメージのtagが格納される?

{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.index.v1+json",
      "size": 7143,
      "digest": "sha256:0228f90e926ba6b96e4f39cf294b2586d38fbb5a1e385c05cd1ee40ea54fe7fd",
      "annotations": {
        "org.opencontainers.image.ref.name": "stable-release"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7143,
      "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
      "platform": {
        "architecture": "ppc64le",
        "os": "linux"
      },
      "annotations": {
        "org.opencontainers.image.ref.name": "v1.0"
      }
    },
    {
      "mediaType": "application/xml",
      "size": 7143,
      "digest": "sha256:b3d63d132d21c3ff4c35a061adf23cf43da8ae054247e32faa95494d904a007e",
      "annotations": {
        "org.freedesktop.specifications.metainfo.version": "1.0",
        "org.freedesktop.specifications.metainfo.type": "AppStream"
      }
    }
  ],
  "annotations": {
    "com.example.index.revision": "r124356"
  }
}

OCI Image Manifest Specification

imageと、そのコンポーネントのために生成された一意なIDからハッシュ可能なimageのconfigurationimage modelをサポートした参照可能なimageを作成すること、platform固有のmanifestを含んだ"fat manifest"による複数architecture対応のimageの実現、OCI Runtime Specificationへの変換の3つを目標にしている。

Image Manifest

image indexはarchitectureやOSごとに展開可能なそれぞれのimageの情報を持つが、image manifestは特定のarchitecture、OSに対する単一のcontainer imageにおけるconfigurationとlayerの集合を提供する。

Image Manifest Property Descriptions

Example

{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 7023,
    "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 32654,
      "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 16724,
      "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 73109,
      "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
    }
  ],
    "annotations": {
    "com.example.key1": "value1",
    "com.example.key2": "value2"
  }
}

OCI Image Index Specification

Image Index Property Descriptions

Example

{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7143,
      "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
      "platform": {
        "architecture": "ppc64le",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7682,
      "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    }
  ],
  "annotations": {
    "com.example.key1": "value1",
    "com.example.key2": "value2"
  }
}

Image Layer Filesystem Changeset

change types

file types

File attributes

hardlinks

Platform-specific attributes

Createing

rootfs-c9d-v1/
    etc/
        my-app-config
    bin/
        my-app-binary
        my-app-tools

色々とfilesystemについての解説が続く

Non-Distributable Layers

OCI Image Configuration

用語

properties

Example

{
    "created": "2015-10-31T22:22:56.015925234Z",
    "author": "Alyssa P. Hacker <alyspdev@example.com>",
    "architecture": "amd64",
    "os": "linux",
    "config": {
        "User": "alice",
        "ExposedPorts": {
            "8080/tcp": {}
        },
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "FOO=oci_is_a",
            "BAR=well_written_spec"
        ],
        "Entrypoint": [
            "/bin/my-app-binary"
        ],
        "Cmd": [
            "--foreground",
            "--config",
            "/etc/my-app.d/default.cfg"
        ],
        "Volumes": {
            "/var/job-result-data": {},
            "/var/log/my-app-logs": {}
        },
        "WorkingDir": "/home/alice",
        "Labels": {
            "com.example.project.git.url": "https://example.com/project.git",
            "com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b"
        }
    },
    "rootfs": {
      "diff_ids": [
        "sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
        "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
      ],
      "type": "layers"
    },
    "history": [
      {
        "created": "2015-10-31T22:22:54.690851953Z",
        "created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
      },
      {
        "created": "2015-10-31T22:22:55.613815829Z",
        "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
        "empty_layer": true
      }
    ]
}

Annotations

Rules

Pre-Defined Annotation Keys

Back-compatibility with Label Schema

org.opencontainers.image org.label-schema Compatibility notes
created build-date Compatible
url url Compatible
source vcs-url Compatible
version version Compatible
revision vcs-ref Compatible
vendor vendor Compatible
title name Compatible
description description Compatible
documentation usage URLの場合にはCompatible
authors Label Schemaにはない要素
licenses Label Schemaにはない要素
ref.name Label Schemaにはない要素
schema-version OCI Image Specにはない要素
docker.*, rkt.* OCI Image Specにはない要素

Conversion to OCI Runtime Configuration

Verbatim Fields

annotation fields

Parsed Fields

Optional Fields

Annotations

Considerations

Extensibility

Canonicalization

JSON

Extended Backus-Naur Form

Tweet
2018年12月24日
2018年11月30日

Railsのテストを実行する環境をdockerで構築したが使いみちがない

docker-compose ps ※ Rails アプリのテストではなく、Rails本体のテストについての話です。

僕がそうだったように、皆さんにもふと「Rails本体のテストを実行してみたいな〜」と思うことがあるでしょう。

ところが、Rails本体のテストというのは大変です。ActiveRecordひとつ取ってみても、網羅するためにはMySQL、PostgreSQL、MariaDB、SQLiteの4つのRDBを用意しなければいけません。

もちろん、公式でそのような環境を構築するためのものは用意されています。

https://github.com/rails/rails-dev-box

rails-dev-boxを使うと、Vagrantを用いて、Rails本体の開発環境を構築できます。(yahondaさんありがとうございます)

ですが、Dockerが仮想環境の主流となっている今、VagrantでなくDockerを使いたい、そう思うのもおかしくはないでしょう。ないですよね?

なので、docker-compose を使用して、Railsのテストを実行する環境を構築してみました。以下、それに伴って行なったことの解説になります。

Dockerfile

FROM ruby:2.5.3-stretch

WORKDIR /rails
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - \
  && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
  && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
  && apt update && apt install --assume-yes \
    ffmpeg \
    sqlite3 \
    imagemagick \
    mupdf \
    mupdf-tools \
    poppler-utils \
    libmariadbclient-dev \
    libsqlite3-dev \
    postgresql-contrib \
    libpq-dev \
    libxml2 \
    libxml2-dev \
    libxslt1-dev \
    libncurses5-dev \
    mysql-client \
    git \
    make \
    nodejs \
    yarn \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

COPY . .
RUN bundle install --jobs=4
RUN npm install
RUN cd actionview && npm install

FROM から WORKDIR の指定までは飛ばして、aptによるパッケージのインストールを見てみます。 ここで指定しているパッケージ郡ですが、 https://github.com/rails/rails-dev-box/blob/master/bootstrap.sh を参考にしました。

続く COPY . . で、 rails/rails のファイルを一気にimageに追加しています。いわゆるDocker image buildのお作法としては、Gemfile、Gemfile.lock 、package.json などのファイルをCOPYして、bundle installなりnpm installなりを行ってからアプリケーションのコードをCOPYしてくるのが一般的です。しかしRailsのしかも開発環境では、Rails gem自体がActiveRecordやActiveModelなどの複数のgemに依存しており、それらがmonorepo構成で rails/rails に含まれているため、このようにしないと bundle installが実行できません。

あとは bundle installとnpm installを実行しているだけです。

docker-compose.yml

version: '3'
services:
  rails:
    build: .
    command: /bin/bash
    environment:
      - MYSQL_HOST=mariadb
      - PGHOST=postgres
      - PGUSER=postgres
      - REDIS_URL=redis://redis:6379
      - MEMCACHE_SERVERS=memcached
    tty: true
    volumes:
      - ".:/rails"
    links:
      - mysql
      # - mariadb
      - postgres
      - redis
      - memcached
      - rabbitmq
  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
  postgres:
    image: postgres:11.1-alpine
  mariadb:
    image: mariadb:10.4.0-bionic
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
  redis:
    image: redis:5.0.1-alpine
  memcached:
    image: memcached:1.5.12-alpine
  rabbitmq:
    image: rabbitmq:3.7.8-alpine

Rails本体のテストを行うにあたり、必要な関連サービスはMySQL PostgreSQL MariaDB Redis Memcached RabbitMQ の6つになります。SQLiteについてはrails service内に含まれています。

testの実行

`$ docker-compose up -d rails でrails serviceが立ち上がります。そしたら、

$ docker-compose exec rails bash

でcontainerに入り、testを実行します。

とはいえ、test suiteはTravis CIで実行されることに最適化されているため、以下のようなpatchを当てる必要がありました。

testそのものは、travis.ymlを参考に、このように実行します。

$ GEM=am,amo,as,av,aj,ast ci/travis.rb

このコマンドでは、ActionMailer、ActiveModel、ActiveSupport、ActionView、ActiveJob、ActiveStorageのtestを実行します。

例えばActiveRecordの、SQLite3でのテストの実行結果は以下のようになりました。

root:/rails# time GEM=ar:sqlite3 ci/travis.rb

[Travis CI] activerecord with sqlite3
Running command: bundle exec rake sqlite3:test

...snip...

Rails build finished successfully

real    63m17.484s
user    12m22.931s
sys     6m50.865s
root@ebdba3a4da12:/rails#

あきらめたやつ

multi stage buildによる Node.js ランタイムの構築

tootsuite/mastodon などで採用されているテクニックですが、multi stage buildを用いてNode.js、npm、yarnのバイナリを main imageに追加することにより、パッケージマネージャやバイナリの直接ダウンロードと比較して高速に別言語のランタイムを構築することができます。今回もmsatodonと同様にNode.js、npm、yarn を COPY --from node で持ってこようとしたのですが、 cannot find module'../lib/utils/unsupported.js' というエラーが発生し、解決策として出てくるのがNode.jsのサイインストールばかりだったので、aptからインストールすることにしました

で、これどうするのか

どうすればいいんでしょうね。

他の皆さんはどうしているのか

気になったのでTwitterで聞いてみたところ、Travis, VPS, localなどがあるようですね。確かにlocalhostに直にインストールしてしまうのが一番楽だと思いました。

皆さんRailsのテストってどうやってますかね。あ、RailsアプリのテストではなくRails本体のテストのことです。

— うなすけ (@yu_suke1994) 2018年11月21日

VPS借りてUbuntu 18.04入れて回してます。期待する答えじゃないかもしれませんが、何か困ってますかね。

— Yasuo Honda (@yahonda) 2018年11月21日

homebrewある環境だったらMySQLとPostgreSQL bottleで入れてActiveRecordのtestに必要なdatabaseやuser作るのは1分ぐらいあればできるので僕はローカルにインストールしてますね。

— Ryuta Kamizono (@kamipo) 2018年11月21日

すごい手抜きなやり方だとRailsをforkした自分のリポジトリに対してtravis設定して雑にpushしながらテストするとかですかね?

— sue445 (@sue445) 2018年11月21日
Tweet
2018年11月30日
2018年10月11日

Itamaeのメンテナになりました

invited

きっかけ

@ryot_a_rai こんどitamaeの話をしたいので飲みに行きましょう!!!! CC @sue445

— うなすけ (@yu_suke1994) 2018年10月7日

僕が以前書いた、落ちていたitamaeのintegration specを直しました から、@sue445 さんもtravis-ciに移行させるpull reqを出したりと、停滞していた開発が再開しそうな流れになっていました。

しかし、作者の @ryotarai さんに時間がないのか、なかなかmergeまで持っていくことができていませんでした。 そこで冒頭のtweetがあり、3人で集まった結果、 僕とsue445さんが itamae-kitchen organization にMemberとして追加されることになりました。

【速報】.@yu_suke1994 さんが .@ryot_a_rai さんを詰めた結果(違)、Itamaeのコミッタになりました! pic.twitter.com/gSo2oTrhz1

— sue445@10/8技術書典5 か75 (@sue445) 2018年10月10日

(今気づいたのですが、現時点で僕のcommitはItamaeには入っていないんですね)

Itamae について思っていること

近年のWebアプリケーションインフラ界隈は、Docker、Kubernetesなどによって Cloud Native になっていく流れが主流となっているように感じています。今所属している会社でも、Rails on Docker on Kubernetes with GKE という構成になっており、いわゆる「モダン」と呼ばれる構成からはインスタンスのプロビジョニングという概念が消えつつあります。

Itamaeに限らず、ChefやAnsibleなど書くことになる機会も減っていくでしょう。

ただ、世間の潮流がどれだけ Cloud Native になったとしても、インスタンスの構築という作業が消えてなくなることは絶対にありません。それに、個人レベルで生のマシンの構築を行なったりするという概念もなくなりはしないでしょう。

そのような場合において、Itamaeを選択肢のひとつとして十分に検討対象であるという状況を続けていきたいと考えています。何故なら僕はRubyistですし、構成管理ツールの中ではItamaeが最も好きだからです。

今後のItamaeにおいて、後方互換を失う規模の変更が入るということはないと思いますが、ryotaraiさん、sue445さんと話していてまだまだ改善する部分はあるという認識は共通しています。細かい改善をしながら粛々とメンテナンスが行なわれていくことになるでしょう。

今後よろしくお願いします。

Tweet
2018年10月11日
2018年10月08日

第51回 情報科学若手の会に参加しました

もらった寿司

幹事のどくぴーや、前年参加のなっちゃん、puhitakuにオススメされたので情報科学若手の会に参加することにしました。

発表の内容は想像以上にアカデミックであり濃く深いものばかりで、正直なところ着いていくのがやっと、いや着いていけないというのが現実でした。

ただ、それは参加を後悔しているという訳ではなく、自分の知らなかった分野、知っていたつもりでもそれは表層だけでまだまだ深淵がある分野についてその存在を知ることができたということで、参加できたことはとても価値があることだと感じました。

僕は初参加だったのですが、ショート発表を1つ、LTを1つ行ないました。初対面の人が多いイベントでは、発表する側に回ったほうが認知が上がること、参加枠も発表者としてだと倍率が低くなることなどの利点があるためです。(定員問題はなさそうでしたが)

今回のショート発表については外部公開はしませんが、LTについては過去の表参道.rbでのmail gemの話をしました。参加者にRubyistが少ないので知らない人が大半だと考えたためです。発表自体はそれなりに盛り上がったようで良かったです。

懇親会でのカスタムキャスト将棋(2人で交互にカスタムキャストのパラメータをいじって好みのアバターを作成する競技)はとても楽しかったです。オタクが終わっていく様子は面白いですね。僕は終わりました。

僕と @ntddk さんで作った限界美少女です #wakate2018 pic.twitter.com/9vlkenzVQo

— うなすけ (@yu_suke1994) 2018年10月7日

アッアッアーーーーー #wakate2018 pic.twitter.com/kXHZ2L7nnT

— うなすけ (@yu_suke1994) 2018年10月7日

来年も参加したいです。もっというなら、他のアカデミックな発表に負けないような濃い内容の発表を持っていきたいと思いますが、さてそんなことができるかな……

Tweet
2018年10月08日
2018年09月30日

高専DJ部 #20 でした

kosendj-bu #20

セトリ

  1. 夏祭り - ジッタリン・ジン
  2. Champagne Showers - LMFAO Feat. Natalia Kills
  3. レーザービーム (Album-mix) - Perfume
  4. One More Time (Chris Moody Remix) - Richard Grey
  5. Atlantis (Extended Mix) - Deniz Koyu
  6. Kill EVERYBODY - Skrillex
  7. Mind Mapping - Ryu☆
  8. In The Place (Original Mix) - FRANO
  9. A Lot Like You - Zac Waters
  10. 君をのせて(totsumal ゼンニチリスペクト Remix) - totsumal
  11. Gekka (Original Mix) - Nhato
  12. Black Mirror (Extended Mix) - James Dymond
  13. Step Back (Original Mix) - Afrojack, MC Ambush
  14. Epidemic (Extended Mix) - SaberZ
  15. Children (Extended Mix) - Vigel
  16. Never Say Never (Extended Mix) - SICK INDIVIDUALS

夏も終わりですね。

Tweet
2018年09月30日
2018年09月17日

大江戸Ruby会議07で登壇しました

雷5656会館

発表資料

oedo07 - unasuke - Rabbit Slide Show

埋め込みがあまりうまくいかないので上のリンクからお願いします。

oedo07

ブログネタになるはずだった

スライドの中でも参照したのですが、もともとこれはこのブログの1記事として出す予定のものでした。

ただ、tqrk12のときに大江戸Ruby会議の登壇者を募集していると聞き、じゃあこっちに回してしまえということにしました。

Rabbitにはpull reqを出せる、と言ったものの

今の僕に理解できるのは、表示が絡まない部分のみなんですよね。GTKで書かれているところに関しては全くわかりません。また、slide.rabbit-shocker.orgも、Rails、Sinatraくらいしか触ったことのない僕にとっては、サッと読んだ程度では理解に相当時間がかかりそうでした。

とはいえ改善点は見えているのでそのうちパッチを送りたいと思います。

OSS信者なのか

PowerPointやKeynoteを用いた、デザインの優れたスライドをRabbitで作成するのは相当大変です。ではなぜ僕がそうするのかというと、発表でも話しましたが、過去の自分の資料が見られなくなってしまったからです。

PDF等に書き出していなかった自分が悪いといえばそれまでなのですが、プロプライエタリではこのようなことも起こりえます。

Tweet
2018年09月17日
2018年08月31日

Mastodon おひとりさまインスタンスを立てました

はい

立てました。

理由

主にMastodonでは末代(@unasuke@mstdn.maud.io)に軸足を置いて色々やっていました。しかし自分自身がRailsアプリケーションの運用を業務で担当しており得意とすることから、やはり自分のドメイン下で動かしてこそだろうと思いsingle user instanceを立てることにしました。(以前にも非公開で運用していたインスタンスはあったのですが、解消できない不具合があり閉じてしまっていました)

Kubernetesの勉強と書いたように、GKEの上で運用しています。費用を抑えるために全てのPodをPreemptible VM instance(最大でも24時間までしか稼動しない)上に配置しています。これはちょっとまずくて、Redisも24時間で自動的に再起動になるのでキャッシュが揮発してしまいます。この辺をなんとかしないといけないなーと思っているので、まだ積極的にリモートフォローはできない状態にいます。

また、このインスタンスでのアカウント作成を開放するつもりはありません。そもそもこのドメイン以下にアカウント作りたいか?という問題、特に今の構成では安定性が保証できないという問題などがあるためです。 5人以上が月に数百円の運営費用を負担してでも、というのであれば検討はしますが、基本的に開放は無いです。

参考にしたweb page

Tweet
2018年08月31日
2018年07月23日

寝転がったままパソコンを使う

外観

ごろ寝デスク

スライドつくりながら、これになることばかり考えている

第133回 夏休み特別企画・夢の仰向けUbuntu生活:Ubuntu Weekly Recipe|https://t.co/JqWu8qNOVX … 技術評論社 https://t.co/mWT75PMzGv

— うなすけ (@yu_suke1994) 2018年7月8日

僕が今使っている椅子は、上京したときに買った安いもので、ずっと座っていると腰が痛くなってくるし、角度によっては酷く軋むので、あまり集中して作業のできるものではありませんでした。

そんな訳でもっぱらベッドの上で作業していたのですが、胡座も長い時間は続けられませんし、寝転がるのも首を上げなくてはならず、どちらにせよ長時間の集中が厳しい状況にありました。(ノートPCです)

もちろん良い椅子を買うことも検討しましたが、とりあえず安価に始められそうということで、前述の記事にあるような寝転がったまま作業ができる環境を整えることにしました。

材料・費用

以下の物品を購入しました。

品名 価格 参照先
メタルラック棚板 幅130cmタイプ MR-1346T * 2 ¥9,892 https://www.irisplaza.co.jp/index.php?KB=SHOSAI&SID=K546794
【4本セット】メタルラックポール 120cmタイプMR-12P ¥2,894 https://www.irisplaza.co.jp/index.php?KB=SHOSAI&SID=K540357F
メタルラック用 大型キャスター MR-475C 4個入り ¥2,138 https://www.irisplaza.co.jp/index.php?KB=SHOSAI&SID=K539420
ナベ頭小ねじ(鉄/ユニクローム) M4×50 1パック(70個) ¥496 https://ihc.monotaro.com/item/C05503601/
Dell 23.8インチワイドモニタ P2418D ¥33,458 https://www.dell.com/ja-jp/shop/accessories/apd/210-amxb?c=jp&l=ja&s=dhs&cs=jpdhs1&sku=210-AMXB
ThinkPad Bluetooth ワイヤレス・トラックポイント・キーボード - 英語 ¥10,962 https://www.lenovo.com/jp/ja/accessories-and-monitors/keyboards-and-mice/keyboards/KEYBOARD-US-English/p/0B47189

合計で¥5,9840 でした。上の価格には配送料が含まれたりそうでなかったりしますが、良い椅子(ここではバロンチェアとする)より安価に済みました。

これはメタルラックにディスプレイを固定している部分です。

VESA

外観

すごく廃人っぽいです。

外観

感想

利点

欠点

今後の課題

総合的には快適です。皆さんもどうですか。

Tweet
2018年07月23日
古い投稿