はじめに
Phoenix の公式ドキュメントには 「heroku か Distillery」
と書いてあったので、 Distillery というのを使ってみます。
ちなみに Distillery (でぃすてぃらりー) というのは「蒸留酒製造工場」
のことらしいです。 distilling ってのが「蒸留」って意味らしいです。
しかし、この Distillery、どうやら release というアーカイブをビルドするところまでが
仕事の範囲らしく、このアーカイブをどうやって本番サーバーに適用するかまでは
扱っていないようです。
それらは
などを使って行わないといけないようです。
Distillery を使うと、
- 環境に応じた erts (Erlang RunTime System) の同梱
- 依存ライブラリの同梱
- OTP release 形式に対応したファイルの生成(Hot upgrade/downgrade)
- start, stop, restart, remote_console, ping などのアプリケーションに対する各種サブコマンド群の生成
などが行われるようです。
今回はビルドして動かしてみるところだけやってみます。
公式のドキュメントが結構充実しているので基本的にはここに書いてある通りにやってみます。
mix.exs へ依存関係の追加
@@ -40,7 +40,8 @@ defmodule Blog.Mixfile do
{:phoenix_html, "~> 2.10"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
- {:cowboy, "~> 1.0"}
+ {:cowboy, "~> 1.0"},
+ {:distillery, "~> 1.5", runtime: false}
]
end
します。現在の最新版は1.5系っぽいので、1.5で。
インストール
$ mix do deps.get, compile
Running dependency resolution...
Dependency resolution completed:
connection 1.0.4
cowboy 1.1.2
cowlib 1.0.2
db_connection 1.1.2
decimal 1.4.0
distillery 1.5.1
ecto 2.1.6
file_system 0.1.5
gettext 0.13.1
mime 1.1.0
phoenix 1.3.0
phoenix_ecto 3.2.3
phoenix_html 2.10.4
phoenix_live_reload 1.1.0
phoenix_pubsub 1.0.2
plug 1.4.3
poison 3.1.0
poolboy 1.5.1
postgrex 0.13.3
ranch 1.3.2
* Getting distillery (Hex package)
Checking package (https://repo.hex.pm/tarballs/distillery-1.5.1.tar)
Fetched package
==> distillery
Compiling 19 files (.ex)
Generated distillery app
==> blog
Compiling 17 files (.ex)
Generated blog app
を実行すると、mix.lock にも書き込まれます。
@@ -3,6 +3,7 @@
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [], [], "hexpm"},
"db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"decimal": {:hex, :decimal, "1.4.0", "fac965ce71a46aab53d3a6ce45662806bdd708a4a95a65cde8a12eb0124a1333", [], [], "hexpm"},
+ "distillery": {:hex, :distillery, "1.5.1", "7ad7354214959c0f65f57ddd49478c81c3b2733ca2e5ccfb9eb55351108466aa", [], [], "hexpm"},
"ecto": {:hex, :ecto, "2.1.6", "29b45f393c2ecd99f83e418ea9b0a2af6078ecb30f401481abac8a473c490f84", [], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"file_system": {:hex, :file_system, "0.1.5", "4f20ec7d186cd84ad478bd5477061aeb993b36b5458872041bbabba8b09d36ff", [], [], "hexpm"},
"gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [], [], "hexpm"},
一旦コミット。
Distillery の初期化
$ mix release.init
というのでやるらしいです。やってみましょう。
$ mix release.init
An example config file has been placed in rel/config.exs, review it,
make edits as needed/desired, and then run `mix release` to build the release
rel/config.exs
というファイルを作ったので、中身を確認して mix release
しなさいよ、と言っていますね。
# Import all plugins from `rel/plugins`
# They can then be used by adding `plugin MyPlugin` to
# either an environment, or release definition, where
# `MyPlugin` is the name of the plugin module.
Path.join(["rel", "plugins", "*.exs"])
|> Path.wildcard()
|> Enum.map(&Code.eval_file(&1))
use Mix.Releases.Config,
# This sets the default release built by `mix release`
default_release: :default,
# This sets the default environment used by `mix release`
default_environment: Mix.env()
# For a full list of config options for both releases
# and environments, visit https://hexdocs.pm/distillery/configuration.html
# You may define one or more environments in this file,
# an environment's settings will override those of a release
# when building in that environment, this combination of release
# and environment configuration is called a profile
environment :dev do
# If you are running Phoenix, you should make sure that
# server: true is set and the code reloader is disabled,
# even in dev mode.
# It is recommended that you build with MIX_ENV=prod and pass
# the --env flag to Distillery explicitly if you want to use
# dev mode.
set dev_mode: true
set include_erts: false
set cookie: :"&aDTF9&j0V;jKvIkZZnGy1t@~MGQcAjPKbDAnOQtpuXF$%bu0NvLbOJ.;<f69L;W"
end
environment :prod do
set include_erts: true
set include_src: false
set cookie: :"6w@<XVk7z?(or5_.A).YbBxVxL,]tU={/v6xicVy~Zq;?l~BN){{auYM%aWx82[*"
end
# You may define one or more releases in this file.
# If you have not set a default release, or selected one
# when running `mix release`, the first release in the file
# will be used by default
release :blog do
set version: current_version(:blog)
set applications: [
:runtime_tools
]
end
plugin、environment, release という概念があるみたいですね。
plugin が何をするのかはいまいちよくわかってませんが、それ以外については
詳細なコメントを書いてくれてるのでだいたいわかりますね。
include_erts
というのが erts(Erlang RunTime System) を release の
中に含めるのかを設定する場所のようです。
set applications: [
:runtime_tools
]
の部分がいまいちよくわかりませんが、とりあえず先へ進みます。
今回は初期状態から何も書き換える箇所がありませんでした。
一旦コミット。
prod.exs の設定
@@ -15,8 +15,12 @@ use Mix.Config
# which you typically run after static files are built.
config :blog, BlogWeb.Endpoint,
load_from_system_env: true,
- url: [host: "example.com", port: 80],
- cache_static_manifest: "priv/static/cache_manifest.json"
+ http: [port: {:system, "PORT"}],
+ url: [host: "localhost", port: {:system, "PORT"}],
+ cache_static_manifest: "priv/static/cache_manifest.json",
+ server: true,
+ root: ".",
+ version: Application.spec(:blog, :vsn)
server: true
とすると、 ビルド結果を実行したときに
Cowboy (というWebサーバー?)が起動するみたいです。
あと、PORT 番号は PORT 環境変数から起動時に読み込むように設定しています。
いよいよリリース用のビルド
まずは前回と今までと同じく assets のコンパイルです。
どうやら assets ディレクトリに cd しなくても
ディレクトリを指定して実行すると成功するようです。
$ brunch b -p assets/
13:43:02 - info: compiled 6 files into 2 files, copied 3 in 2.5 sec
そして digest。
$ MIX_ENV=prod mix phoenix.digest
==> distillery
Compiling 19 files (.ex)
Generated distillery app
mix phoenix.digest is deprecated. Use phx.digest instead.
==> blog
Check your digested files at "priv/static"
いよいよ、 Distillery の release タスクを実行してみます。
mix help <task名>
で詳細なヘルプを見られるということに気づきました。
$ mix help release
mix release
Build a release for the current mix application.
## Examples
# Build a release using defaults
mix release
# Build an executable release
mix release --executable
# Build an executable release which will cleanup after itself after it runs
mix release --executable --transient
# Build an upgrade release
mix release --upgrade
# Build an upgrade release from a specific version
mix release --upgrade --upfrom=0.1.0
# Build a specific release
mix release --name=myapp
# Build a release for a specific environment
mix release --env=staging
# Build a specific profile
mix release --profile=myapp:staging
# Pass args to erlexec when running the release
mix release --erl="-env TZ UTC"
# Enable dev mode. Make changes, compile using MIX_ENV=prod
# and execute your release again to pick up the changes
mix release --dev
# Mute logging output
mix release --silent
# Quiet logging output
mix release --quiet
# Verbose logging output
mix release --verbose
# Do not package release, just assemble it
mix release --no-tar
# Treat warnings as errors
mix release --warnings-as-errors
# Skip warnings about missing applications
mix release --no-warn-missing
Location: _build/dev/lib/distillery/ebin
verbose というのがあるのでつけてみましょう。
あと、MIX_ENV
と --env
を両方指定しないといけない
理由がいまいちよくわかってません。
$ MIX_ENV=prod mix release --env=prod --verbose
==> Loading configuration..
==> Assembling release..
==> Building release blog:0.0.1 using environment prod
==> Discovered applications:
poolboy-1.5.1
from: _build/prod/lib/poolboy
applications:
:kernel
:stdlib
includes: none
ecto-2.1.6
from: _build/prod/lib/ecto
applications:
:kernel
:stdlib
:elixir
:logger
:decimal
:poolboy
includes: none
phoenix_ecto-3.2.3
from: _build/prod/lib/phoenix_ecto
applications:
:kernel
:stdlib
:elixir
:logger
:ecto
:plug
includes: none
decimal-1.4.0
from: _build/prod/lib/decimal
applications:
:kernel
:stdlib
:elixir
includes: none
connection-1.0.4
from: _build/prod/lib/connection
applications:
:kernel
:stdlib
:elixir
includes: none
db_connection-1.1.2
from: _build/prod/lib/db_connection
applications:
:kernel
:stdlib
:elixir
:logger
:connection
includes: none
postgrex-0.13.3
from: _build/prod/lib/postgrex
applications:
:kernel
:stdlib
:elixir
:logger
:db_connection
:decimal
:crypto
includes: none
eex-1.5.1
from: /usr/local/Cellar/elixir/1.5.1/bin/../lib/eex
applications:
:kernel
:stdlib
:elixir
includes: none
poison-3.1.0
from: _build/prod/lib/poison
applications:
:kernel
:stdlib
:elixir
includes: none
phoenix-1.3.0
from: _build/prod/lib/phoenix
applications:
:kernel
:stdlib
:elixir
:plug
:poison
:logger
:eex
:phoenix_pubsub
:crypto
includes: none
mime-1.1.0
from: _build/prod/lib/mime
applications:
:kernel
:stdlib
:elixir
includes: none
plug-1.4.3
from: _build/prod/lib/plug
applications:
:kernel
:stdlib
:elixir
:crypto
:logger
:mime
includes: none
phoenix_html-2.10.4
from: _build/prod/lib/phoenix_html
applications:
:kernel
:stdlib
:elixir
:logger
:plug
includes: none
cowlib-1.0.2
from: _build/prod/lib/cowlib
applications:
:kernel
:stdlib
:crypto
includes: none
asn1-5.0
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/asn1-5.0
applications:
:kernel
:stdlib
includes: none
public_key-1.4.1
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/public_key-1.4.1
applications:
:asn1
:crypto
:kernel
:stdlib
includes: none
ssl-8.2
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/ssl-8.2
applications:
:crypto
:public_key
:kernel
:stdlib
includes: none
ranch-1.3.2
from: _build/prod/lib/ranch
applications:
:kernel
:stdlib
:ssl
includes: none
cowboy-1.1.2
from: _build/prod/lib/cowboy
applications:
:kernel
:stdlib
:ranch
:cowlib
:crypto
includes: none
crypto-4.0
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/crypto-4.0
applications:
:kernel
:stdlib
includes: none
phoenix_pubsub-1.0.2
from: _build/prod/lib/phoenix_pubsub
applications:
:kernel
:stdlib
:elixir
:logger
:crypto
includes: none
gettext-0.13.1
from: _build/prod/lib/gettext
applications:
:kernel
:stdlib
:elixir
:logger
includes: none
runtime_tools-1.12
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/runtime_tools-1.12
applications:
:kernel
:stdlib
includes: none
logger-1.5.1
from: /usr/local/Cellar/elixir/1.5.1/bin/../lib/logger
applications:
:kernel
:stdlib
:elixir
includes: none
compiler-7.1
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/compiler-7.1
applications:
:kernel
:stdlib
includes: none
elixir-1.5.1
from: /usr/local/Cellar/elixir/1.5.1/bin/../lib/elixir
applications:
:kernel
:stdlib
:compiler
includes: none
stdlib-3.4
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/stdlib-3.4
applications:
:kernel
includes: none
kernel-5.3
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/kernel-5.3
applications: none
includes: none
blog-0.0.1
from: _build/prod/lib/blog
applications:
:kernel
:stdlib
:elixir
:logger
:runtime_tools
:gettext
:phoenix_pubsub
:cowboy
:phoenix_html
:phoenix
:postgrex
:phoenix_ecto
includes: none
iex-1.5.1
from: /usr/local/Cellar/elixir/1.5.1/bin/../lib/iex
applications:
:kernel
:stdlib
:elixir
includes: none
sasl-3.0.4
from: /usr/local/Cellar/erlang/20.0/lib/erlang/lib/sasl-3.0.4
applications:
:kernel
:stdlib
includes: none
==> Generated overlay vars:
release_name=:blog
release_version="0.0.1"
is_upgrade=false
upgrade_from=:latest
dev_mode=false
include_erts=true
include_src=false
include_system_libs=true
erl_opts=""
run_erl_env=""
erts_vsn="9.0"
output_dir="_build/prod/rel/blog"
==> Copying applications to _build/prod/rel/blog
==> Generating nodetool
==> Generating start_erl.data
==> Generating vm.args
==> Generating sys.config from config/config.exs
==> Including ERTS 9.0 from /usr/local/Cellar/erlang/20.0/lib/erlang/erts-9.0
==> Generating boot script
==> Generating RELEASES
==> Generating start_clean.boot
==> Applying overlays
==> Applying mkdir overlay
dst: releases/0.0.1/hooks
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/pre_configure.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/post_configure.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/pre_start.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/post_start.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/pre_stop.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/post_stop.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/pre_upgrade.d
==> Applying mkdir overlay
dst: releases/0.0.1/hooks/post_upgrade.d
==> Applying copy overlay
src: _build/prod/lib/distillery/priv/libexec
dst: releases/0.0.1/libexec
==> Applying mkdir overlay
dst: releases/0.0.1/commands
==> Packaging release..
==> Archiving blog-0.0.1
==> Writing tarball to _build/prod/rel/blog/releases/0.0.1/blog.tar.gz
==> Updating tarball
==> Tarball updated!
==> Release successfully built!
You can run it in one of the following ways:
Interactive: _build/prod/rel/blog/bin/blog console
Foreground: _build/prod/rel/blog/bin/blog foreground
Daemon: _build/prod/rel/blog/bin/blog start
これで、
- 各種依存ライブラリ
- Erlang 20.0 の erts
- 各種ファイルやディレクトリ群
がアーカイブ用に準備され、
-
_build/prod/rel/blog/bin/blog
というコマンド -
_build/prod/rel/blog/releases/0.0.1/blog.tar.gz
という release アーカイブ
が出来上がったことがわかります。
ビルドされた結果を実行
$ _build/prod/rel/blog/bin/blog foreground
"$@" -- "${1+$ARGS}"
14:24:20.220 [info] Application blog exited: Blog.Application.start(:normal, []) returned an error: shutdown: failed to start child: BlogWeb.Endpoint
** (EXIT) an exception was raised:
** (RuntimeError) expected the PORT environment variable to be set
(blog) lib/blog_web/endpoint.ex:51: BlogWeb.Endpoint.init/2
(phoenix) lib/phoenix/endpoint/supervisor.ex:32: Phoenix.Endpoint.Supervisor.init/1
(stdlib) supervisor.erl:294: :supervisor.init/1
(stdlib) gen_server.erl:365: :gen_server.init_it/2
(stdlib) gen_server.erl:333: :gen_server.init_it/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
{"Kernel pid terminated",application_controller,"{application_start_failure,blog,{{shutdown,{failed_to_start_child,'Elixir.BlogWeb.Endpoint',{#{'__exception_
_' => true,'__struct__' => 'Elixir.RuntimeError',message => <<\"expected the PORT environment variable to be set\">>},[{'Elixir.BlogWeb.Endpoint',init,2,[{fi
le,\"lib/blog_web/endpoint.ex\"},{line,51}]},{'Elixir.Phoenix.Endpoint.Supervisor',init,1,[{file,\"lib/phoenix/endpoint/supervisor.ex\"},{line,32}]},{supervi
sor,init,1,[{file,\"supervisor.erl\"},{line,294}]},{gen_server,init_it,2,[{file,\"gen_server.erl\"},{line,365}]},{gen_server,init_it,6,[{file,\"gen_server.er
l\"},{line,333}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,247}]}]}}},{'Elixir.Blog.Application',start,[normal,[]]}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,blog,{{shutdown,{failed_to_start_child,'Elixir.BlogWeb.Endpoint',{#{'__exception__
' => true,'__struct__' => 'Elixir.RuntimeEr
Crash dump is being written to: erl_crash.dump...done
おっと、PORT 環境変数を指定し忘れてしまいました。
$ PORT=4000 _build/prod/rel/blog/bin/blog foreground
"$@" -- "${1+$ARGS}"
14:26:25.732 [info] Running BlogWeb.Endpoint with Cowboy using http://:::4000
14:26:32.936 request_id=6bplk7dihh1kvv3gl9oeef0h7jmgpd7p [info] GET /
14:26:32.938 request_id=6bplk7dihh1kvv3gl9oeef0h7jmgpd7p [info] Sent 200 in 2ms
14:26:35.926 request_id=6gqno4k0l558blc1pkdrvsma4uffupht [info] GET /articles
14:26:35.928 request_id=6gqno4k0l558blc1pkdrvsma4uffupht [info] Sent 200 in 2ms
14:26:37.459 request_id=r6h0vqfgdpl3t01tljhdtopc729vspjm [info] GET /articles/new
14:26:37.459 request_id=r6h0vqfgdpl3t01tljhdtopc729vspjm [info] Sent 200 in 476µs
"$@" -- "${1+$ARGS}"
というよくわからないログが気になりますが...
一応問題なく起動して、ブラウザからもアクセスできました。
その他のサブコマンド
何もタスク名を指定せずに実行するとヘルプが出ました。
$ _build/dev/rel/blog/bin/blog
Usage: blog <task>
Service Control
=======================
start # start blog as a daemon
start_boot <file> # start blog as a daemon, but supply a custom .boot file
foreground # start blog in the foreground
console # start blog with a console attached
console_clean # start a console with code paths set but no apps loaded/started
console_boot <file> # start blog with a console attached, but supply a custom .boot file
stop # stop the blog daemon
restart # restart the blog daemon without shutting down the VM
reboot # restart the blog daemon
reload_config # reload the current system's configuration from disk
Upgrades
=======================
upgrade <version> # upgrade blog to <version>
downgrade <version> # downgrade blog to <version>
install <version> # install the blog-<version> release, but do not upgrade to it
Utilities
=======================
attach # attach the current TTY to blog's console
remote_console # remote shell to blog's console
pid # get the pid of the running blog instance
ping # checks if blog is running, pong is returned if successful
pingpeer <peer> # check if a peer node is running, pong is returned if successful
escript <file> # execute an escript
rpc <mod> <fun> [<args..>] # execute an RPC call using the given MFA
rpcterms <mod> <fun> [<expr>] # execute an RPC call using the given Erlang expression for args
eval <expr> # execute the given Erlang expression on the running node
command <mod> <fun> [<args..>] # execute the given MFA
describe # print useful information about the blog release
Custom Commands
=======================
No custom commands found.
ほとんどがシェルスクリプト経由で実行されているらしく、
山のようにシェルスクリプトがありました。
$ find _build -name '*.sh'
_build/prod/rel/blog/bin/blog_loader.sh
_build/prod/rel/blog/releases/0.0.1/blog.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/attach.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/command.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/console.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/describe.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/escript.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/eval.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/foreground.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/help.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/install.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/pid.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/ping.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/pingpeer.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/reboot.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/reload_config.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/remote_console.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/restart.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/rpc.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/rpcterms.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/start.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/stop.sh
_build/prod/rel/blog/releases/0.0.1/libexec/commands/unpack.sh
_build/prod/rel/blog/releases/0.0.1/libexec/config.sh
_build/prod/rel/blog/releases/0.0.1/libexec/env.sh
_build/prod/rel/blog/releases/0.0.1/libexec/erts.sh
_build/prod/rel/blog/releases/0.0.1/libexec/helpers.sh
_build/prod/rel/blog/releases/0.0.1/libexec/logger.sh
試しに Linux に持っていって動かしてみる
Linux 用の erts の設定などを全くしてないので、絶対に動かないと思いますが、
Linux に持っていって、動かないことを確認してみましょう。
ちなみにアーカイブのサイズは
$ du -sh blog.tar.gz
15M blog.tar.gz
でした。
$ scp blog.tar.gz linux:
$ ssh linux
linux:~$ mkdir blog
linux:~$ mv blog.tar.gz blog
linux:~$ cd blog/
linux:~$ tar xfvz blog.tar.gz
(略)
linux:~$ ls
bin blog.tar.gz erts-9.0 lib releases
linux:~$ bin/blog
/home/tmaeda/blog/erts-9.0/bin/erlexec: 1: /home/tmaeda/blog/erts-9.0/bin/erlexec: Syntax error: "(" unexpected
あー、出ました!やっぱり動かないですね。
個人的にはクロスコンパイルみたいなやつは他に良い手段がないときに
最終手段として仕方なくやるものだと思っているので、今回はここは深追いしません。
Circle CIでビルドして、 edeliver で本番Linuxサーバー上にデプロイというのが
今見えている最も実践的なデプロイ方法なんじゃないかと思っています。
(追記) edeliver も調べてみましたが、どうもいまいちでした。自作shスクリプトか、capistranoかansibleかなぁ...
edeliverのツライところ
- 巨大なbashスクリプトである。bashスクリプトの割には非常にがんばってると思うけど、bashスクリプトでこんなに大きなもの作っちゃいけないと思う。エラー処理とか、カスタマイズとかデバッグとか大変でしょ。
- 起動時に外から環境変数を渡す仕組みがない? PORT=4000 みたいなやつ。
まとめ
- Distillery でのビルドと起動が公式ドキュメントに従って問題なくできました。
- Distillery を利用することで、非常に多くのサブコマンドが生成されることがわかりました。
- Mac で(特に設定せずに)作ったアーカイブを Linux に持っていっても起動できないことが確認できました。(Mac上に Linux 用の erts を置いておいて、
rel/config.exs
にパスを指定してあげると Linux 用の erts が同梱されて、Linux 上で動くようになるらしいですけど、そもそもこれは筋悪だと思っているので、深追いはしません) - Hot upgrade などが Distillery の醍醐味なんだと思いますが、それはまたの機会に。