1 of 18

“mix release” released

ymtszw�tokyo.ex #11

2 of 18

自己紹介

  • MATSUZAWA Yu / 松澤 有
    • 2019/06 ~ 株式会社Siiibo CTO
    • ~ 2019/05 株式会社ACCESS所属
  • ymtszw @ GitHub
  • gada_twt @ Twitter
  • 業務でも趣味でもだいたい関数型言語書いてる
    • ElixirかElm. Haskellは読むだけ
    • ElixirとElmですっかり満足してしまっているので、そろそろ何か新しい言語やりたい
  • PCゲーマー
    • Diabloシリーズ
    • WarcraftIII, World of Warcraft
    • 最近はSEKIROとかも
  • 右は実家で父が築き上げた薪山の頂上に座り南方を望むの図

2

3 of 18

Erlang & Elixir Fest 2019でLTしました

  • “Config” in Elixir
    • スライド
  • 社内勉強会の内容(初学者向け)の拡張、という資料体裁で、Elixir 1.9でのConfigとmix releaseの話をしました

4 of 18

Elixir 1.9.0, リリースされました

  • Elixir v1.9 released - Elixir
    • 6/24(月)
  • ということでLTで発表した内容が実際に使えるようになりました

5 of 18

今日のtalk

  • “Config” in Elixirが詰めっ詰めの早口になってしまったので、前半も含めて少し再放送させてください
  • Elixir 1.9のreleaseを実際に使うにあたって
    • migrationなどの付属スクリプトをどう実行させるか

6 of 18

再放送パート

7 of 18

“mix release” in production

  • 1.8まで、Distilleryの場合�
  • Releaseを生成できるようにするところまではdoc通り
  • Dockerを使う場合、他の言語と同様、「ビルド」と「実行」の環境を考えてDockerfileを上手に書く
    • 後述するスレッドでJoséが貼ってくれたのだが、phoenix公式guideのreleases.md に決定版がまとまっていた

8 of 18

Release & Docker

# 最近のバージョンのdockerでは、 ”AS” でDockerfile内ローカルなaliasを環境につけることができる

# Alpine使うのはmustではない。muslだとビルドできないdepsが入るかも、といった懸念があるならdebian系でも

FROM elixir:1.9.0-alpine AS build

...

ENV MIX_ENV=prod

RUN mix compile

RUN mix release

# ここで、まっさら&スリムなベースイメージに切り替え

FROM alpine:3.9 AS app

# ごっそりコピー、これで余計なビルド時のみ必要なパッケージの削除などが不要

WORKDIR /app

COPY --from=build /app/_build/prod/rel/my_app ./

9 of 18

Release & Docker

  • 恥ずかしながらこのやり方(AS/COPY --from)知らなかった
    • 早速使っている

10 of 18

Migrationスクリプトは

  • いつ、
  • どこで、
  • 誰が走らせる?

11 of 18

Deploy時のMigration

  • 「いつ」は当然deploy時、新規インスタンス(プロセス)の立ち上がる前なんだけど、そこにも注意は必要
    • そもそも新旧のプロセスが(短い時間とはいえ)混在する状況でMigrationして、どちらのプロセスもエラーを起こさないようにしたいかどうか、したいとすればどう実現するか、はElixir関係なく普遍的な関心事
      • 破壊的なMigrationをせず、addition & deprecationのみで進めて、十分にバージョンが上がってからdeletionする方式とか、一時的に新旧2パターンのテーブルに書き込んでいって、既存のデータは裏で移行するとか、いろいろ
    • ↑の話は別で決着がついているという前提で、とりあえず新規プロセス立ち上げ前にMigrationスクリプト(mix ecto.migrate相当)を走らせるとする

12 of 18

Deploy時のMigration

  • 「どこで」「だれが」
    • 作業者がローカル環境から、CIサーバから、デプロイ環境に立てるmix task専用インスタンスから、あるいは新規に導入されるアプリケーションサーバインスタンス自体から、など、いろいろあり得る
    • 最後の、サーバインスタンス(コンテナ)自体からデプロイ直前にMigrationスクリプトを走らせる方式は、以下の利点を見て個人的には採用していた(決定版かどうかはまだ微妙)
      • 別の実行環境を設定しなくて良い
      • ローカル(のdockerなど)で状況再現しやすい
      • DistilleryがBoot hooksとして対応していた
    • ちなみに最新のEctoでは、普通に使っていればmigrationは専用のtableでバージョン管理され、実行時にはロックが要求されるので、複数サーバがデプロイされるときも二重実行されることはない

13 of 18

1.9での“mix release” in production

  • 先のスライドの通り、releaseを組むところまでは本当に簡単
  • Dockerで利用するのも1.8と全く同手法で良い
  • 一方、Distilleryが持っていたBoot hooksという仕組みは採用されなかった

14 of 18

Migrationをどう走らせるか

  • 1.8で、「アプリケーションサーバ自身がデプロイ時に実行」するパターンで構築していた場合、代替手段が必要
  • ということで聞いておきました
  • Equivalent to distillery's boot hooks in mix release? (Elixir 1.9) - Questions / Help - Elixir Forum
    • 結構返信あったので、刺さる人がまあまあいたらしい

15 of 18

16 of 18

17 of 18

いくつか候補(いずれもOK)

  • 普通にアプリケーション起動時(startコールバックとか)に、関数として呼ぶ
    • Ecto.Migrator.runを使って実行時関数(mixに依存しない関数)にしておく前提
  • :steps機能で追加処理を仕込めるので、そこにコピー処理を仕込んでおき、スクリプトをreleaseに同梱させておき、明示的に実行
    • こちらのほうがBoot hooksよりも明示的にreleaseにまつわる追加処理ができる
  • もっというと、スクリプト化していなくても、bin/<release_name> eval “:release_tasks.migrate/0”などのインラインコマンドを仕込めば良い

18 of 18

まとめ

  • デプロイ周りの手順は1.9でほぼ成熟したと言えるんではないでしょうか
  • 安心してrelease使っていきましょう!
    • (hot code upgradeからは目を背けている)��
  • 株式会社SiiiboではElixirエンジニアを真剣に募集中です!
    • Twitterで @gada_twt に、あるいは support@siiibo.com にご連絡ください! 詳しくご説明いたします。
    • 「貯蓄から社債投資へ」をスローガンに、社債投資の民主化を目指すスタートアップです!
    • https://siiibo.com