techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

ワークフローエンジンDigDagでDockerを使ってみる(追記:6/28)

ワークフローエンジンのDigDagではワークフローを動かす環境をDockerにすることが可能とのことです。
そのためDockerで環境をワークフローを動かすときに構築するため、過去の設定情報などをクリアすることなく動作させ得ることができるため、ワークフローを書くのが非常に楽になります。

Dockerを使った方法についてご紹介します。
ただし、まだまだ開発中のようできちんと動きませんでした。

Dockerの指定(コンテナの環境構築なし)

DigDagでDockerを指定するには次のように行います。
今回の例では下記のような構成で実行するものとします。

.
├── digdag-docker.dig
└── tasks
    └── shell_sample.sh

[digdag-docker.dig]

timezone: UTC

_export:
  docker:
    image: ubuntu:14.04

+step1:
  sh>: tasks/shell_sample.sh

_exportでdockerの記述を行いimageでdockerのイメージを指定します。
この場合だとubuntuの14.04を指定します。
shell_sample.shはdigdag initで自動生成されるものをそのまま用いました。
これで実行した場合は次のような動作を行います。

  1. Dockerのイメージがなければダウンロード
  2. Dockerのrunコマンドを実行し、digdagコマンドを実行したフォルダを作業フォルダとしてマウントします。
  3. 各タスクの実行を行う

実行した結果は次のようになります。

$ digdag r digdag-docker.dig
2016-06-26 13:05:27 +0900: Digdag v0.8.2
2016-06-26 13:05:28 +0900 [WARN] (main): Reusing the last session time 2016-06-24T00:00:00+00:00.
2016-06-26 13:05:28 +0900 [INFO] (main): Using session .digdag/status/20160624T000000+0000.
2016-06-26 13:05:28 +0900 [INFO] (main): Starting a new session project id=1 workflow name=digdag-docker session_time=2016-06-24T00:00:00+00:00
2016-06-26 13:05:29 +0900 [INFO] (0019@+digdag-docker+step1): sh>: tasks/shell_sample.sh
/bin/sh: 1: tasks/shell_sample.sh: not found
2016-06-26 13:05:29 +0900 [ERROR] (0019@+digdag-docker+step1): Task failed with unexpected error: Command failed with code 127
java.lang.RuntimeException: Command failed with code 127
    at io.digdag.standards.operator.ShOperatorFactory$ShOperator.runTask(ShOperatorFactory.java:117)
    at io.digdag.util.BaseOperator.run(BaseOperator.java:49)
    at io.digdag.core.agent.OperatorManager.callExecutor(OperatorManager.java:265)
    at io.digdag.cli.Run$OperatorManagerWithSkip.callExecutor(Run.java:658)
    at io.digdag.core.agent.OperatorManager.runWithWorkspace(OperatorManager.java:231)
    at io.digdag.core.agent.OperatorManager.lambda$runWithHeartbeat$1(OperatorManager.java:124)
    at io.digdag.core.agent.NoopWorkspaceManager.withExtractedArchive(NoopWorkspaceManager.java:20)
    at io.digdag.core.agent.OperatorManager.runWithHeartbeat(OperatorManager.java:122)
    at io.digdag.core.agent.OperatorManager.run(OperatorManager.java:106)
    at io.digdag.cli.Run$OperatorManagerWithSkip.run(Run.java:640)
    at io.digdag.core.agent.LocalAgent.lambda$run$0(LocalAgent.java:70)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
2016-06-26 13:05:30 +0900 [INFO] (0019@+digdag-docker^failure-alert): type: notify
error: 
  * +digdag-docker+step1:
    Command failed with code 127

Task state is saved at .digdag/status/20160624T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

v0.8.2では残念ながら動きません。
7行目の「/bin/sh: 1: tasks/shell_sample.sh: not found」となっていることからDockerのマウントのところにバグがあり、実行できない状態になっています。
今、修正のためのパッチをpull requestを送っているのでそれがマージされると改善されます。 (マージされるといいな)

パッチを組み込んだ時の動作は下記の感じです。

追記:6/28
修正がされたようです。
v0.8.3からその内容が反映されるみたいです。

$ ./digdag-0.8.3-SNAPSHOT.jar r digdag-docker.dig
2016-06-26 13:03:40 +0900: Digdag v0.8.3-SNAPSHOT
2016-06-26 13:03:41 +0900 [WARN] (main): Reusing the last session time 2016-06-24T00:00:00+00:00.
2016-06-26 13:03:41 +0900 [INFO] (main): Using session .digdag/status/20160624T000000+0000.
2016-06-26 13:03:42 +0900 [INFO] (main): Starting a new session project id=1 workflow name=digdag-docker session_time=2016-06-24T00:00:00+00:00
2016-06-26 13:03:42 +0900 [INFO] (0019@+digdag-docker+step1): sh>: tasks/shell_sample.sh
Step1 of session 2016-06-24T00:00:00+00:00
Success. Task state is saved at .digdag/status/20160624T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

Dockerの指定(コンテナの環境構築あり)

追記:6/28
Dockerのbuildオプションは近い将来なくなるとのことですので、使わないようにしたほうがいいみたいです。 注意しましょう。

Dockerのコンテナ内を生成するたびにコンテナがまっさらなため環境構築しないとタスクが実行できないことがあり得ると思います。
そうした場合に利用するのはDockerのオプションでコンテナの環境構築を実施します。
それは次のように実施します。

[digdag-docker.dig]

timezone: UTC

_export:
  docker:
    image: ubuntu:14.04
    build: ["echo hello world" ,  "echo コマンド実行"]

+step1:
  sh>: tasks/shell_sample.sh

これで実行するとdigdagを実行したフォルダ内の「.digdag/tmp/Dockerfile.rev-1-<時刻など>」にdockerfileが作成され、ファイルには次のような記述で吐き出されます。

FROM ubuntu:14.04
ADD . /digdag
WORKDIR /digdag
RUN echo hello world
RUN echo コマンド実行

buildで指定したコマンドがRUNで指定されるようになっていることが確認されます。
このdockerfileが用いられてコンテナが作られることになるためRUNで指定したコマンドが実行される様になります。

これを実行すると次のようになります。

2016-06-26 13:32:32 +0900: Digdag v0.8.2
2016-06-26 13:32:33 +0900 [WARN] (main): Reusing the last session time 2016-06-24T00:00:00+00:00.
2016-06-26 13:32:33 +0900 [INFO] (main): Using session .digdag/status/20160624T000000+0000.
2016-06-26 13:32:33 +0900 [INFO] (main): Starting a new session project id=1 workflow name=digdag-docker session_time=2016-06-24T00:00:00+00:00
2016-06-26 13:32:34 +0900 [INFO] (0019@+digdag-docker+step1): sh>: tasks/shell_sample.sh
invalid argument "rev-1-2016-06-26T04:32:33.660Z" for t: Error parsing reference: "rev-1-2016-06-26T04:32:33.660Z" is not a valid repository/tag
See 'docker build --help'.
2016-06-26 13:32:34 +0900 [ERROR] (0019@+digdag-docker+step1): Task failed with unexpected error: Docker build failed
java.lang.RuntimeException: Docker build failed
    at io.digdag.standards.command.DockerCommandExecutor.buildImage(DockerCommandExecutor.java:207)
    at io.digdag.standards.command.DockerCommandExecutor.startWithDocker(DockerCommandExecutor.java:68)
    at io.digdag.standards.command.DockerCommandExecutor.start(DockerCommandExecutor.java:50)
    at io.digdag.standards.operator.ShOperatorFactory$ShOperator.runTask(ShOperatorFactory.java:104)
    at io.digdag.util.BaseOperator.run(BaseOperator.java:49)
    at io.digdag.core.agent.OperatorManager.callExecutor(OperatorManager.java:265)
    at io.digdag.cli.Run$OperatorManagerWithSkip.callExecutor(Run.java:658)
    at io.digdag.core.agent.OperatorManager.runWithWorkspace(OperatorManager.java:231)
    at io.digdag.core.agent.OperatorManager.lambda$runWithHeartbeat$1(OperatorManager.java:124)
    at io.digdag.core.agent.NoopWorkspaceManager.withExtractedArchive(NoopWorkspaceManager.java:20)
    at io.digdag.core.agent.OperatorManager.runWithHeartbeat(OperatorManager.java:122)
    at io.digdag.core.agent.OperatorManager.run(OperatorManager.java:106)
    at io.digdag.cli.Run$OperatorManagerWithSkip.run(Run.java:640)
    at io.digdag.core.agent.LocalAgent.lambda$run$0(LocalAgent.java:70)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
2016-06-26 13:32:34 +0900 [INFO] (0019@+digdag-docker^failure-alert): type: notify
error: 
  * +digdag-docker+step1:
    Docker build failed

Task state is saved at .digdag/status/20160624T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

こちらも残念ながら実行できません。
理由としてはDockerコマンドのbuildを実行するときのタグ名の指定が命名規則に従っていないためエラーとなります。
こちらもpull requestを送っているのでマージされると使えるようになるはずです。 (マージされるといいな)

パッチを組み込んだ時の動作は下記の感じです。

$ ./digdag-0.8.3-SNAPSHOT.jar r digdag-docker.dig
2016-06-26 15:19:43 +0900: Digdag v0.8.3-SNAPSHOT
2016-06-26 15:19:44 +0900 [WARN] (main): Reusing the last session time 2016-06-24T00:00:00+00:00.
2016-06-26 15:19:44 +0900 [INFO] (main): Using session .digdag/status/20160624T000000+0000.
2016-06-26 15:19:45 +0900 [INFO] (main): Starting a new session project id=1 workflow name=digdag-docker session_time=2016-06-24T00:00:00+00:00
2016-06-26 15:19:45 +0900 [INFO] (0019@+digdag-docker+step1): sh>: tasks/shell_sample.sh
Sending build context to Docker daemon 20.99 MB
Step 1 : FROM ubuntu:14.04
 ---> 8f1bd21bd25c
Step 2 : ADD . /digdag
 ---> 537a12ed2cb2
Removing intermediate container 988015fc96ad
Step 3 : WORKDIR /digdag
 ---> Running in e475d660aa91
 ---> 68bda60f2214
Removing intermediate container e475d660aa91
Step 4 : RUN echo hello world
 ---> Running in 4ef4374829c8
hello world
 ---> fe7bbf44120d
Removing intermediate container 4ef4374829c8
Step 5 : RUN echo コマンド実行
 ---> Running in f7847da40b07
コマンド実行
 ---> ac9406be209b
Removing intermediate container f7847da40b07
Successfully built ac9406be209b
Step1 of session 2016-06-24T00:00:00+00:00
Success. Task state is saved at .digdag/status/20160624T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.