LoginSignup
0
1

More than 3 years have passed since last update.

EmbulkのDockerコンテナをHerokuで動かす

Last updated at Posted at 2019-09-16

HerokuでEmbulkを動かすためにHerokuの Container Registry を利用する必要がありました。
Heroku上でDockerコンテナを動かすためにいくつかポイントがあるので後世のために共有します。

前提条件

以下のようなユースケースでの実装例になります。
他のユースケースでは使用するEmbulkのプラグインが異なると思いますが基本的な部分は大差ないはずです。

  • Heroku上でEmbulkを実行する
    • Heroku Scheduler を利用して日次実行する
    • 過去分のデータ移行の処理も必要
  • S3のログファイルをBigQueryにロードする処理
    • 記事の本題ではないのでEmbulkを実行するスクリプトなどは割愛しています

1. Dockerfileの記述例

S3のログファイルをBigQueryにロードする処理で以下の3つのプラグインを使用しています。

  • embulk-input-s3
  • embulk-output-bigquery
  • embulk-parser-jsonl
FROM openjdk:8
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get install bash

WORKDIR /app

# 本題から逸れるのでアプリケーションコードの配置などは省いています

RUN curl -o /bin/embulk --create-dirs -L "http://dl.embulk.org/embulk-latest.jar" && chmod +x /bin/embulk

RUN embulk mkbundle bundle
RUN echo "gem 'embulk-input-s3', '0.3.4'" >> bundle/Gemfile
RUN echo "gem 'embulk-output-bigquery', '0.4.4'" >> bundle/Gemfile
RUN echo "gem 'embulk-parser-jsonl', '0.2.0'" >> bundle/Gemfile

WORKDIR bundle
RUN embulk bundle

WORKDIR /app

ポイントになるのは以下の2点です。
特に2点目がハマりどころです。

  1. Embulkを /bin 以下に配置することでパスの設定の手間を省く
  2. mkbundle を使用してプラグインのgemのインストール先を指定する

mkbundleを使用しない場合に発生する問題について

HerokuにコンテナをデプロイしてEmbulkを実行すると以下のエラーが発生して実行できません。

2019-09-15 19:22:17.628 +0900 [INFO] (main): Gem's home and path are set by default: "/app/.embulk/lib/gems"
2019-09-15 19:22:22.575 +0900 [INFO] (main): Started Embulk v0.9.18
org.embulk.config.ConfigException: InputPlugin 's3' is not found.
org.jruby.proxy.org.embulk.config.ConfigException$Proxy1: Unknown input plugin 's3'. embulk/input/s3.rb is not installed. Run 'embulk gem search -rd embulk-input' command to find plugins.

ポイントになるのは以下の部分です。

Gem's home and path are set by default: "/app/.embulk/lib/gems"

Embulkはインストールされたプラグインを /app/.embulk/lib/gems 以下に探しにいくのですが
実際には /root/.embulk/lib/gems 以下に配置されます。

プラグインインストール時のログ

Gem plugin path is: /root/.embulk/lib/gems

ローカルで実行した場合にはこの問題は発生しないのでHerokuのDockerコンテナのデプロイ、実行環境の問題だと思われるのですが詳細なメカニズムは分かりません。
対応としては以下の2点が挙げられるのですが 1 の方がスマートですね。

  1. mkbundle を利用してプラグインのインストール場所を指定する
  2. Dockerfileで WORKDIR /root にしてプラグイン、アプリケーションコードを全て /root 以下に配置する

なお、Embulkの実行は -b オプションでプラグインのインストール先を指定します。
このケースの場合は以下のようになります。

embulk run -b /app/bundle /app/config.yml

2. Herokuへのコンテナのデプロイ

Heroku Scheduler を利用して日次実行する という要件を満たすためには web でデプロイする必要があります。
これはHerokuの仕様で詳しくは Heroku Schedulerは --type=web のDockerコンテナしか実行しない を参照ください。

heroku container:push web --app [APP_NAME]
heroku container:release web --app [APP_NAME]

一方でデバッグや同期実行のために worker でもデプロイする必要があります。
どういうわけか web でデプロイした方に heroku run bash で接続すると1分間で強制切断されます。
HerokuのHTTPリクエストが1分でタイムアウトさせられる仕様が誤作動しているような印象です・

heroku container:push worker --app [APP_NAME]
heroku container:release worker --app [APP_NAME]

まとめると、スケジュール実行が必要な処理をHeroku上で行う場合は web worker の両方に同じコンテナをデプロイしなければなりません。

3. Dyno Typeについて

Embulkは実行時の消費メモリが大きいのでHerokuで実行するには Dyno Type は最低でも standard-2x は必要です。
Herokuへ接続する際や One-Off 実行する際は必ず --size オプションを指定しましょう。

Herokuへのbash接続コマンド例

heroku run bash --type=worker --size=standard-2x --app [APP_NAME]
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1