一言で表わすと、「ノリと勢い」で始まりました。
音質改善の足しに、と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日
まず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
— 02/09 11:00 🍲 (@sachin21__) 2017年9月21日
マイクなら絶対これ。tsとかDiscordとかしてても設定ちゃんとすれば周りの音入らない。スピーカーでも全然OK
tsなら音楽流しながらでもボイスチャット出来る。
購入してから自宅でのボイスチャットに使用していたものをそのまま持ち込んで録音しました。このマイクに関しては、普段の通話で問題になったことがなく(通話相手から何か言われたことがない、という意味)、それなりに安心して収録に臨めました。
収録ではマイクを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日
HolyGrail/kibela2esa: Kibela 2 esa.io
やっぱりWIPっていいですよね。
esaが好きです。
HolyGrail/kibela2esa: Kibela 2 esa.io
めちゃくちゃ興味あり〼 https://t.co/gHfAV5rbEU
— うなすけ (@yu_suke1994) 2018年11月30日
頭の中には設計があるんですが、…
— Uchio KONDO 🔫 (@udzura) 2018年11月30日
OCIの仕様を再確認するところから…
とりあえずブログかキータ
— Uchio KONDO 🔫 (@udzura) 2018年11月30日
という訳で、書きました。
Open Container Initiativeによって定められた、コンテナイメージフォーマットの標準仕様です。
詳しくは Open Container Initiativeによるコンテナランタイムとコンテナイメージの最初の標準化作業が完了、「OCI v1.0」発表 - Publickey にて。
現在、OCI ImageをdownloadできるDocker HubのようなWebサイトは知る限りありません。なので、自分でOCI 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ではありませんね。
ここで、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ですね。
自分なりに理解しようと翻訳したもののメモになります。 正確性の保証はないです。誤訳とかあります。最後のほう力尽きてます。
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の実装 ←プラットフォームや他の属性によって変化することができる
一度作成されたOCI imageは名前によって探索(discovered)、ダウンロード、hashによる検証、署名による信頼、OCI Runtime Bundleへの展開ができる
components of the specは以下を含む
optional featureとしてSignaturesやNamingが仕様に含まれるかもしれない。
application/vnd.oci.descriptor.v1+json
application/vnd.oci.layout.header.v1+json
application/vnd.oci.image.index.v1+json
application/vnd.oci.image.manifest.v1+json
application/vnd.oci.image.config.v1+json
application/vnd.oci.image.layer.v1.tar
application/vnd.oci.image.layer.v1.tar+gzip
application/vnd.oci.image.layer.nondistributable.v1.tar
application/vnd.oci.image.layer.nondistributable.v1.tar+gzip
HTTP responseのContent-Typeで上の値を返すなどのように、typeを返すなにかしらの方法を実装してもよい(MAY)、また実装はmedia typeとdigestを期待してよい? 実装は返却されたmedia typeを尊重する必要がある(SHOULD)
前方・後方互換を可能な限り維持する必要がある。
似た、または関連するmedia typeは以下
application/vnd.oci.image.index.v1+json
application/vnd.docker.distribution.manifest.list.v2+json
(mediaTypeが違う?)application/vnd.oci.image.manifest.v1+json
application/vnd.docker.distribution.manifest.v2+json
application/vnd.oci.image.layer.v1.tar+gzip
application/vnd.docker.image.rootfs.diff.tar.gzip
互換性がある(入れ替え可能)application/vnd.oci.image.config.v1+json
application/vnd.docker.container.image.v1+json
Image indexは複数のImage manifestを持つ。Image manifestとImage JSON(config)は1対1。Image manifestはLayerのtar archiveを複数持つ。 Discriptorは全ての参照を持つ。
mediaType
digest
size
urls
annotations
data
こういう形式
sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b
sha512:401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b372742...
sha256とsha512がRegistered algorithms
とされている。sha256はMUSTでsha512はMAY。
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"urls": ["https://example.com/example-manifest" ]
}
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によって作成できる。(?)
blobs
directory
oci-layout
file
imageLayoutVersion
というfieldを持つ必要がある。index.json
$ 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
のサブディレクトリ以下にあるディレクトリは、各ハッシュアルゴリズムごとにまとめられている。そのディレクトリ以下に、実際のファイルが格納されている。
blobs/<alg>/<encoded>
<alg>:<encoded>
と対応している$ 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]
これ。
{
"imageLayoutVersion": "1.0.0"
}
必須。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"
}
}
imageと、そのコンポーネントのために生成された一意なIDからハッシュ可能なimageのconfigurationimage modelをサポートした参照可能なimageを作成すること、platform固有のmanifestを含んだ"fat manifest"による複数architecture対応のimageの実現、OCI Runtime Specificationへの変換の3つを目標にしている。
image indexはarchitectureやOSごとに展開可能なそれぞれのimageの情報を持つが、image manifestは特定のarchitecture、OSに対する単一のcontainer imageにおけるconfigurationとlayerの集合を提供する。
schemaVersion
mediaType
config
layers
annotations
{
"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"
}
}
application/vnd.oci.image.manifest.v1+json
← これ{
"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"
}
}
application/vnd.oci.image.layer.v1.tar
はtar archiveでなくてはならず、またtar archiveの結果となるpathに重複したエントリを含んではいけないrootfs-c9d-v1/
etc/
my-app-config
bin/
my-app-binary
my-app-tools
色々とfilesystemについての解説が続く
application/vnd.oci.image.layer.nondistributable.v1.tar
というmediaTypeでないといけないapplication/vnd.oci.image.config.v1+json
sha256:a9561eb1b190625c9adb5a9513e72c4dedafc1cb2d4c5236c9a6957ec7dfd5a9
ChainID(L₀) = DiffID(L₀)
ChainID(L₀|...|Lₙ₋₁|Lₙ) = Digest(ChainID(L₀|...|Lₙ₋₁) + " " + DiffID(Lₙ))
VARNAME=VARVALUE
という形式で格納される。
layers
である必要がある。実装は不明な値が入っていた場合はエラーを出す必要がある。{
"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
}
]
}
com.example.myKey
みたいなorg.opencontainers
はOCIによって予約済みなので使用してはならない。org.opencontainers.image
はOCIによって予約済みなので使用してはならない。(他のOCI仕様についても同様)org.opencontainers.image.created
org.opencontainers.image.authors
org.opencontainers.image.url
org.opencontainers.image.documentation
org.opencontainers.image.source
org.opencontainers.image.version
org.opencontainers.image.revision
org.opencontainers.image.vendor
org.opencontainers.image.licenses
org.opencontainers.image.ref.name
org.opencontainers.image.title
org.opencontainers.image.description
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にはない要素 |
application/vnd.oci.image.config.v1+json
を OCI Runtime configuration blobに変換する方法を定義するConfig.WorkingDir
→ process.cwd
Config.Env
→ process.env
※1Config.Entrypoint
→ process.args
※2Config.Cmd
→ process.args
※2org.opencontainers.image.author
に指定する必要があるorg.opencontainers.image.created
に指定する必要があるorg.opencontainers.image.stopSignal
に指定する必要があるConfig.User
→ process.user.*
/etc/passwd
をパースすることによってprocess.user.uid や process.user.gid に値を格納するConfig.ExposedPorts
→ annotations ※1Config.Vlumes
→ mounts
※2org.opencontainers.image.exposedPorts
に値をセットしなければならない※ 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のテストを実行する環境を構築してみました。以下、それに伴って行なったことの解説になります。
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を実行しているだけです。
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内に含まれています。
`$ 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#
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日
@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には入っていないんですね)
近年のWebアプリケーションインフラ界隈は、Docker、Kubernetesなどによって Cloud Native になっていく流れが主流となっているように感じています。今所属している会社でも、Rails on Docker on Kubernetes with GKE という構成になっており、いわゆる「モダン」と呼ばれる構成からはインスタンスのプロビジョニングという概念が消えつつあります。
Itamaeに限らず、ChefやAnsibleなど書くことになる機会も減っていくでしょう。
ただ、世間の潮流がどれだけ Cloud Native になったとしても、インスタンスの構築という作業が消えてなくなることは絶対にありません。それに、個人レベルで生のマシンの構築を行なったりするという概念もなくなりはしないでしょう。
そのような場合において、Itamaeを選択肢のひとつとして十分に検討対象であるという状況を続けていきたいと考えています。何故なら僕はRubyistですし、構成管理ツールの中ではItamaeが最も好きだからです。
今後のItamaeにおいて、後方互換を失う規模の変更が入るということはないと思いますが、ryotaraiさん、sue445さんと話していてまだまだ改善する部分はあるという認識は共通しています。細かい改善をしながら粛々とメンテナンスが行なわれていくことになるでしょう。
今後よろしくお願いします。
幹事のどくぴーや、前年参加のなっちゃん、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日
来年も参加したいです。もっというなら、他のアカデミックな発表に負けないような濃い内容の発表を持っていきたいと思いますが、さてそんなことができるかな……
夏も終わりですね。
oedo07 - unasuke - Rabbit Slide Show
埋め込みがあまりうまくいかないので上のリンクからお願いします。
スライドの中でも参照したのですが、もともとこれはこのブログの1記事として出す予定のものでした。
ただ、tqrk12のときに大江戸Ruby会議の登壇者を募集していると聞き、じゃあこっちに回してしまえということにしました。
今の僕に理解できるのは、表示が絡まない部分のみなんですよね。GTKで書かれているところに関しては全くわかりません。また、slide.rabbit-shocker.orgも、Rails、Sinatraくらいしか触ったことのない僕にとっては、サッと読んだ程度では理解に相当時間がかかりそうでした。
とはいえ改善点は見えているのでそのうちパッチを送りたいと思います。
PowerPointやKeynoteを用いた、デザインの優れたスライドをRabbitで作成するのは相当大変です。ではなぜ僕がそうするのかというと、発表でも話しましたが、過去の自分の資料が見られなくなってしまったからです。
PDF等に書き出していなかった自分が悪いといえばそれまでなのですが、プロプライエタリではこのようなことも起こりえます。
立てました。
主にMastodonでは末代(@unasuke@mstdn.maud.io)に軸足を置いて色々やっていました。しかし自分自身がRailsアプリケーションの運用を業務で担当しており得意とすることから、やはり自分のドメイン下で動かしてこそだろうと思いsingle user instanceを立てることにしました。(以前にも非公開で運用していたインスタンスはあったのですが、解消できない不具合があり閉じてしまっていました)
Kubernetesの勉強と書いたように、GKEの上で運用しています。費用を抑えるために全てのPodをPreemptible VM instance(最大でも24時間までしか稼動しない)上に配置しています。これはちょっとまずくて、Redisも24時間で自動的に再起動になるのでキャッシュが揮発してしまいます。この辺をなんとかしないといけないなーと思っているので、まだ積極的にリモートフォローはできない状態にいます。
また、このインスタンスでのアカウント作成を開放するつもりはありません。そもそもこのドメイン以下にアカウント作りたいか?という問題、特に今の構成では安定性が保証できないという問題などがあるためです。 5人以上が月に数百円の運営費用を負担してでも、というのであれば検討はしますが、基本的に開放は無いです。
スライドつくりながら、これになることばかり考えている
— うなすけ (@yu_suke1994) 2018年7月8日
第133回 夏休み特別企画・夢の仰向けUbuntu生活:Ubuntu Weekly Recipe|https://t.co/JqWu8qNOVX … 技術評論社 https://t.co/mWT75PMzGv
僕が今使っている椅子は、上京したときに買った安いもので、ずっと座っていると腰が痛くなってくるし、角度によっては酷く軋むので、あまり集中して作業のできるものではありませんでした。
そんな訳でもっぱらベッドの上で作業していたのですが、胡座も長い時間は続けられませんし、寝転がるのも首を上げなくてはならず、どちらにせよ長時間の集中が厳しい状況にありました。(ノート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 でした。上の価格には配送料が含まれたりそうでなかったりしますが、良い椅子(ここではバロンチェアとする)より安価に済みました。
これはメタルラックにディスプレイを固定している部分です。
すごく廃人っぽいです。
総合的には快適です。皆さんもどうですか。