Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Elixir on Containers
さっちゃん
May 19, 2019
Programming
1
630
Elixir on Containers
Know-how that ops Elixir on Docker containers.
さっちゃん
May 19, 2019
Tweet
Share
More Decks by さっちゃん
See All by さっちゃん
メトリックはいかにして見え續ける樣になったか #devio2022
ne_sachirou
0
10
名實一致
ne_sachirou
0
470
まかれるあなとみあ ―Mackerel のしくみを理解する 30 分― @ Hatena Engineer Seminar #16
ne_sachirou
0
2.3k
tacit programming : Point-free, Concatenatives & J
ne_sachirou
0
340
Monitoring Containerized Elixir
ne_sachirou
1
530
Let's create stateful systems, by Elixir
ne_sachirou
1
530
Phoenix LiveReact
ne_sachirou
1
280
Phoenix LiveView チュートリアル
ne_sachirou
1
110
DDD: Data Driven Development
ne_sachirou
6
4.4k
Other Decks in Programming
See All in Programming
僕が便利だと感じる Snow Monkey の特徴/20220723_Gifu_WordPress_Meetup
oleindesign
0
100
Haskellでオブジェクト指向プログラミング
koheisakata
0
180
回帰分析ではlm()ではなくestimatr::lm_robust()を使おう / TokyoR100
dropout009
0
4.4k
プロダクトのタイプ別 GraphQL クライアントの選び方
shozawa
0
8.1k
Now in Android Overview
aosa4054
0
370
JetpackCompose 導入半年で感じた 改善点
spbaya0141
0
140
Register-based calling convention for Go functions
cjamhe01385
0
390
More Than Micro Frontends: 3 Further Use Cases for Module Federation @DWX 2022
manfredsteyer
PRO
0
340
AWS Config Custom Rule、ノーコードでできるかな?
watany
0
250
Getting Started With Data Structures
adoranwodo
1
250
Google I/O 2022 Android関連概要 / Google I/O 2022 Android summary
phicdy
0
360
ZOZOTOWNにおけるDatadogの活用と、それを支える全社管理者の取り組み / 2022-07-27
tippy
0
3k
Featured
See All Featured
Become a Pro
speakerdeck
PRO
3
900
How to train your dragon (web standard)
notwaldorf
60
3.9k
Web development in the modern age
philhawksworth
197
9.3k
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
173
8.6k
Documentation Writing (for coders)
carmenintech
48
2.6k
Visualization
eitanlees
125
12k
Fontdeck: Realign not Redesign
paulrobertlloyd
73
4.1k
The World Runs on Bad Software
bkeepers
PRO
57
5.4k
Bash Introduction
62gerente
598
210k
From Idea to $5000 a Month in 5 Months
shpigford
373
44k
Music & Morning Musume
bryan
35
4.3k
The Web Native Designer (August 2011)
paulrobertlloyd
75
2k
Transcript
Elixir on Containers
.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)
Container is good, because: It gives an abstract of processes
with environments. It's easy to deploy.
I'm using container for Elixir server @ dev, test &
prod. A little bit stateful WebSocket servers. Umbrella Related tools: Distillery, Dialyzer, docker‑compose, Kubernetes.
Containers for local dev
Why use containers for local dev? Use the same env
between Alchemist team members. Use the same env between non‑Alchemist team members. (Rubyist, frontend enginier, etc.) Use the near env between dev, test & prod.
I maintain Docker images that fixes both Erlang & Elixir
ver.
Work with the team & CI (Continuous Integration).
My application have some umbrellas. apps/ app_a/ app_b/
Dockerfile (deps.compile & dialyzer ‑‑plt) FROM nesachirou/elixir:1.8_erl21 SHELL ["/bin/ash", "-ex",
"-o", "pipefail", "-c"] RUN apk add --no-cache -t .build-deps \ ~ \ git \ && rm -rf /var/cache/apk/* WORKDIR /var/www VOLUME /var/www COPY mix.exs mix.lock ./ COPY apps/app_a/mix.exs apps/app_a/ COPY apps/app_b/mix.exs apps/app_b/ RUN mix "do" deps.get, deps.compile \ && MIX_ENV="test" mix deps.compile \ && mix dialyzer --plt \ && mv _build deps /tmp RUN apk add --no-cache -t .runtime-deps \ inotify-tools \ rsync \ && rm -rf /var/cache/apk/* EXPOSE 4000 4001 CMD ["./entrypoint.sh"]
entrypoint.sh #!/bin/sh -eux # shellcheck shell=dash if test "$(stat /.dockerenv
> /dev/null || echo $?)" ; then : "Outside Docker" mix "do" deps.get, compile else : "Inside Docker" rsync -au /tmp/_build /tmp/deps . mix "do" deps.get, compile fi elixir --name example@127.0.0.1 --cookie example -S mix phx.server
docker-compose.yml --- version: "3" services: example: image: example.docker.registry/example/example:latest depends_on: [example-src]
logging: options: max-size: "100m" max-file: "2" ports: - 4000:4000 - 4001:4001 volumes: - example-src:/var/www ~
docker-compose.override.yml --- version: "3" services: example: build: context: . dockerfile:
Dockerfiles/Dockerfile.dev docker-compose build --pull --force-rm docker-compose push
docker‑sync http://docker‑sync.io/ Docker (for MacOS) is too slow in it's
file IO between containers & the host. docker‑sync solves this, but troublesome. I do a little bit different way (unison + rsync).
docker-compose.yml ~ example-src: image: eugenmayer/unison:2.51.2.1 environment: APP_VOLUME: /app_sync HOST_VOLUME: /host_sync
TZ: Asia/Tokyo UNISON_ARGS: | -debug default -ignore 'Name .git/*' -ignore 'Name _build/*' \ -ignore 'Name deps/*' -prefer /host_sync -numericids -auto -batch UNISON_DEST: /app_sync UNISON_SRC: /host_sync UNISON_WATCH_ARGS: -repeat watch volumes: - ../example:/host_sync:cached - example-src:/app_sync volumes: example-src:
precopy_appsync #!/bin/bash -eux rsync -auv \ --delete \ --exclude='.git/*' --exclude='_build/*'
--exclude='deps/*' \ /host_sync/ /app_sync docker-compose -f example/docker-compose.yml stop example-src docker-compose -f example/docker-compose.yml run --rm --no-deps example-src \ /host_sync/tools/precopy_appsync docker-compose -f example/docker-compose.yml start example-src
Testing container image yamllint https://github.com/adrienverge/yamllint hadolint https://github.com/hadolint/hadolint container‑structure‑test https://github.com/GoogleContainerTools/container‑ structure‑test
Containers for prod
Work with CD (Continuous Delivery).
Umbrella apps/ app_a/ app_b/ common/
Distillery https://github.com/bitwalker/distillery {:distillery, "~> 2.0", runtime: false}, No hot code
swapping, RollingUpdate.
rel/config.exs ~ environment :prod do set(include_erts: true) set(include_src: false) set(cookie:
:" ~") set(vm_args: Path.join("rel", "vm.args.prod")) end release :app_a do set(version: "0.0.1") set(applications: [:app_a, :common, :runtime_tools]) set(commands: [app_terminate: "rel/commands/app_terminate.sh"]) set(overlay_vars: [ ~]) end
rel/commands/app_terminate.sh → ./bin/app_a app_terminate (PreStop hook) #!/bin/bash -eu COOKIE=$(awk '/-setcookie/{print$2}'
releases/0.0.1/vm.args) export COOKIE bin/app_a command Elixir.AppA.Command app_terminate AppA.Command defmodule AppA.Command do def app_terminate do :ok = do_rpc(:"app_a@127.0.0.1", :"terminate@127.0.0.1", AppA.AppTerminator, :request_terminate, [], 1_800_000) end defp do_rpc(target_node, node_name, module, fun, args, timeout) do Node.start(node_name) Node.set_cookie(String.to_atom(System.get_env("COOKIE"))) :rpc.call(target_node, module, fun, args, timeout) end end
Dockerfile for app_a (multi stage build) FROM nesachirou/elixir:1.8_erl21 as builder
SHELL ["/bin/ash", "-ex", "-o", "pipefail", "-c"] RUN apk add --no-cache -t .build-deps \ build-base \ ~ \ git ARG REVISION ENV MIX_ENV=prod WORKDIR /var/www COPY mix.exs mix.lock ./ COPY apps/app_a/mix.exs apps/app_a/ COPY apps/common/mix.exs apps/common/ RUN mix "do" deps.get --only prod, deps.compile COPY apps/app_a apps/app_a COPY apps/common apps/common COPY config config COPY rel rel # hadolint ignore=DL3003 RUN mix compile \ && mix release --verbose --name=app_a ~
Dockerfile for app_a (multi stage build) ~ FROM alpine:3.9 SHELL
["/bin/ash", "-ex", "-o", "pipefail", "-c"] RUN apk add --no-cache -t .runtime-deps \ bash \ inotify-tools \ openssl \ && rm -rf /var/cache/apk/* WORKDIR /var/www # hadolint ignore=DL3010 COPY --from=builder /var/www/_build/prod/rel/app_a/releases/0.0.1/app_a.tar.gz ./ RUN tar xzf app_a.tar.gz \ && rm -rf app_a.tar.gz EXPOSE 80 4369 CMD ["bin/app_a", "foreground"]
container-structured-test.yml --- schemaVersion: "2.0.0" commandTests: - name: Application meta data
command: bin/example args: [describe] expectedOutput: - example-0.0.1 - "Name: example_maint_@127.0.0.1" - name: libcrypto command: bin/example args: [eval, ":crypto.strong_rand_bytes(8)"] metadataTest: cmd: [bin/example, foreground] exposedPorts: ["80", "4369"] workdir: /var/www