Elixir 프로젝트를 Heroku에 배포하기

5 minute read

Heroku란?

Heroku is a container-based cloud Platform as a Service (PaaS). Developers use Heroku to deploy, manage, and scale modern apps. Our platform is elegant, flexible, and easy to use, offering developers the simplest path to getting their apps to market.

About Heroku - Heroku - heroku.com

PaaS(platform as a service)다. 운영체제 뭐 이런 건 신경 쓸 필요는 없고 데이터와 소프트웨어만 신경 쓰면 된다.

Buildpacks are responsible for transforming deployed code into a slug, which can then be executed on a dyno. Buildpacks are composed of a set of scripts, and depending on the programming language, the scripts will retrieve dependencies, output generated assets or compiled code, and more. This output is assembled into a slug by the slug compiler.

Buildpacks - Heroku Dev Center - devcenter.heroku.com

Buildpacks는 내 소스를 빌드해서 Heroku dyno에서 실행할 수 있게 해준다. 여기서 dyno는 실행 인스턴스라고 생각하면 된다. Buildpacks 실행은 누가 책임지나? Heroku가 책임진다.

Heroku로 소스코드만 배포하면 알아서 빌드해서 내가 세팅한 dyno에서 프로그램을 실행한다. 편하다.

왜 Heroku를 쓰는가?

무료라서 사용했다. 낮은 성능의 dyno를 무료로 사용할 수 있게 해줬다. 매달 사용할 수 있는 시간을 초기화시켜 줬다. 오래 써서 그런가? 매달 무료로 주어지는 사용 시간이 좀 늘어났었다. 그래서 앱 2개 정도는 무료로 돌릴 수 있었다.

하지만 이제는 무료 dyno가 없다.

Starting October 26, 2022, we will begin deleting inactive accounts and associated storage for accounts that have been inactive for over a year. Starting November 28, 2022, we plan to stop offering free product plans and plan to start shutting down free dynos and data services. We will be sending out a series of email communications to affected users.

Heroku’s Next Chapter - Heroku - blog.heroku.com

이제는 $5를 결제해야 맛이라도 볼 수 있다. 제일 싼 요금제는 Eco 요금제다. 한 달에 $5를 결제해야 한다. 예전 무료 dyno와 거의 비슷한 서비스를 제공한다.

현재 tbot-800.ex 프로그램을 사용한 @book_quote_bot, @bquote_bot 트위터 봇을 Heroku에서 실행하고 있다. 매달 $5씩 결제하면서 말이다.

Heroku가 좋고 편해서 계속 사용하고 있을까? 아니다. 이제 무료가 아니니 나는 매력을 못 느끼겠다. 요즘 많이 들리는 Fly.io 같은 서비스로 옮기고 싶다. 최근 Clojure로 짠 트위터 봇을 Elixir로 재작성한다고 에너지를 다 써버려서 그대로 있다. 약간은 의리 뭐 그런 거로 매달 $5를 내고 있다. 그리 비싼 가격도 아니라서 내면서 버티고 있는지도 모르겠다. 하지만 머지않아 다른 서비스로 옮길 것 같다.

Git push로 배포

Git 프로그램으로 Heroku 저장소로 push하면 Heroku가 buildpack으로 빌드해서 배포한다. 편하다. 우선 이렇게 하려면 Heroku CLI부터 설치해야 한다.

brew tap heroku/brew && brew install heroku
heroku login

The Heroku CLI 페이지를 참고해 운영체제에 맞는 CLI 프로그램을 설치한다. 설치 후 로그인을 한다.

이제 git push로 배포하려면 remote 저장소(repository) 세팅이 필요하다. 이 세팅을 하려면 웹브라우저로 Heroku 홈페이지에 접속해 대시보드에서 새로운 app을 만들고 배포 관련 안내에 따라 세팅을 해준다.

heroku git:remote -a tbot800ex

이런 식으로 세팅하라고 안내해 주는데 세팅하게 되면 이제 git push로 배포할 수 있다.

git push heroku master

이렇게 배포할 수 있다.

하지만 배포한다고 바로 사용할 수는 없다. 어떻게 빌드할 것인지를 결정하는 Buildpacks 세팅을 해줘야 하기 때문이다.

Heroku Elixir buildpacks 세팅

공식 빌드팩(official buildpacks)에 Clojure는 있는데 Elixir는 없다. 사제를 사용해야 한다. HashNuke/heroku-buildpack-elixir 빌드팩을 사용해서 세팅하자. Heroku 대시보드에서 App을 선택해 buildpack을 세팅해도 되고 Heroku CLI 프로그램을 사용해도 된다.

heroku buildpacks:set hashnuke/elixir

이제 erlang version, elixir version 같은 걸 세팅해야 한다. 저장소 root에 elixir_buildpack.config 파일을 만들어서 세팅할 수 있다.

# Erlang version
erlang_version=25.1.2

# Elixir version
elixir_version=1.14.1

# Always rebuild from scratch on every deploy?
always_rebuild=false

# Create a release using `mix release`? (requires Elixir 1.9)
release=false

# A command to run right before fetching dependencies
hook_pre_fetch_dependencies="pwd"

# A command to run right before compiling the app (after elixir, .etc)
hook_pre_compile="pwd"

hook_compile="mix compile --force --warnings-as-errors"

# A command to run right after compiling the app
hook_post_compile="pwd"

# Set the path the app is run from
runtime_path=/app

트위터 봇인 tbot-800.ex 프로그램에서 세팅한 elixir_buildpack.config 설정이다.

빌드팩 설명을 보면 Procfile 이 없을 때, 디폴트 실행 방법이 나와 있다.

If your app doesn’t have a Procfile, default web task mix run –no-halt will be run.

HashNuke/heroku-buildpack-elixir - Buildpacks - Heroku Elements - elements.he…

web 프로세스 타입을 사용하면 Procfile 파일을 만들지 않아도 된다. 하지만 다른 프로세스 타입을 사용하려면 Procfile 을 만들어서 설정해야 한다.

사용하는 프로세스 타입과 시작 명령을 적는 Procfile

Procefile 에 어떤 프로세스 타입을 사용할 것인지와 프로세스 시작 명령을 적는다.

A Procfile declares its process types on individual lines, each with the following format:

: - is an alphanumeric name for your command, such as web, worker, urgentworker, clock, and so on. - indicates the command that every dyno of the process type should execute on startup, such as rake jobs: work. [The Procfile - Heroku Dev Center - devcenter.heroku.com](https://devcenter.heroku.com/articles/procfile#procfile-format)

mix release를 사용하지 않는다면 command로는 mix run --no-halt 를 넣으면 된다. process type은 web과 worker만 사용해 봤다. 한 번도 사용해 보지 않은 타입이 많네.

디폴트로 사용하는 web process type에 대한 설명을 보자.

A Heroku app’s web process type is special: it’s the only process type that can receive external HTTP traffic from Heroku’s routers. If your app includes a web server, you should declare it as your app’s web process.

The Procfile - Heroku Dev Center - devcenter.heroku.com

외부 HTTP 트래픽이 있으면 실행된다. 이걸로 웹서비스를 운영해 본 적이 없어서 cold start인지 warm start인지, 비활성화됐다가 HTTP 트래픽이 있을 때, 실행 시간을 얼마나 보장하는지는 잘 모르겠다.

만약 트래픽과 상관없이 계속 실행해야 하는 프로그램을 Heroku로 띄우려면 어떤 타입을 사용하면 될까? worker process type을 사용하면 된다.

트위터 봇인 tbot-800.ex은 외부 HTTP 트래픽을 받지 않고 계속 떠 있어야 하기에 worker process type을 사용했다.

worker: mix run --no-halt

마치며

Heroku로 PaaS(platform as a service) 맛을 처음 봤다. 소스 코드만 git remote 저장소로 push 하면 빌드하고 실행해 준다. 얼마나 편하게요~

공식 빌드팩이 없어서 아쉽다. 하지만 잘 만든 HashNuke/heroku-buildpack-elixir 사제 빌드팩이 있어서 불편한 걸 못 느끼겠다.

하지만 무료 dyno가 사라져서 더 이상 매력적이지 않다. 무료로 사용할 수 있는 다른 서비스를 찾아보거나 이왕 돈을 낸다면 잘나가고 핫한 서비스를 써보고 싶기 때문이다.

링크