GoogleCloudPlatformで単発処理を行うDockerコンテナ

Posted: , Modified:   Docker GoogleCloudPlatform Qiita

本稿は Qiita 投稿記事 のバックアップです.

概要

あるところからデータの塊を取ってきて何らかの解析にかけたい.それらを GCP (Google Cloud Platform) で行いたいが,インスタンスの設定やファイルのダウンロード,アップロードが面倒.そんな時に使える Dockerコンテナイメージを作った.

なお,ここでの処理は,毎日ログデータを深夜に処理するなどのバッチ処理を考える.ストリーム処理には向かない.

Roadie-GCP

GCP でプログラムを実行する時に使える補助コンテナ.必要なファイル,処理内容,実行結果の保存先などをまとめた YAML スクリプトファイルを渡せば後はうまくやってくれる.なおベースイメージは Ubuntu である.

スクリプトファイル名が conf.yaml の場合,実行方法は次の通り.

$ docker run -i jkawamoto/roadie-gcp < conf.yml

なお,このコンテナは実行が終わり,結果をアップロードし終わるとインスタンスを削除する.そのため,インスタンスの作成時に https://www.googleapis.com/auth/compute スコープを指定する必要がある.この挙動を変える場合には --no-shutdown オプションを指定する.

スクリプトファイル

スクリプトファイル conf.yamlapt, source, data, run, result, upload の6要素を定義するYAML ファイル.それぞれ,プログラム実行に必要な apt パッケージ,プログラムのソースファイル,プログラムの実行に必要なデータファイル,プログラム実行手順,実行結果の保存先,そして実行結果のファイルパターンを定義する.script.yml は次のような形になる.

apt:
  - unrar
source: https://github.com/abcdefg/some-program.git
data:
  - http://mmnet.iis.sinica.edu.tw/dl/wowah/wowah.rar
run:
  - unrar x -r wowah.rar
  - ./analyze WoWAH
result: gs://somebucket/
upload:
  - "*.png"

このスクリプトファイルは,次のことを指示している.

  1. apt-get で unrar パッケージをインストールする.
  2. GitHub からソースコードをダウンドードする.
  3. プログラムの実行に必要なファイルをウェブから取得する.
  4. 次の二つのコマンドを実行する.
    • unrar で取得したファイルを解凍.
    • 自前の解析プログラムを実行する.
  5. Google Cloud Storage のバケットを出力の保存先として設定する.
  6. 解析プログラムが作成した *.png ファイルを (5) で設定したバケットにアップロードする.

apt

apt 要素では,apt-get でインストールするパッケージのリストを指定する.特にインストールすべきパッケージがない場合は省略可.

source

source 要素には,実行するプログラムのソース URL を指定する.URLは次の形式をサポートしている.

どの場合でも,URLが .zip, .tar, .tar.gz で終わっていれば適切に解凍される.ダウンロードしたソースは /data に展開される.

data

data 要素では,実行前に取得するファイルをリスト形式で記述する.リストの各要素は,URL:保存先 の形をとる. URLスキームには,http, https の他 Google Cloud Storage を表す gsDropboxの公開リンクを表す dropbox が使用できる.

保存先には絶対パス,相対パスどちらも使用できる.パスが / で終わっている場合は,指定されたディレクトリ内にURLが示すファイル名で保存する.逆に,パスが / で終わっていない場合は,当該ファイル名に変更して保存する.

なお,デフォルトのディレクトリは /data である.

data:
  - http://sample.com/input.json
  - gs://a-project/input/data:/tmp/

上記の例では,http://sample.com/input.json/data/input.json として保存し,Cloud Storage の a-project バケットにあるオブジェクト input/data を /tmp/data として保存する.

最終的に保存されるファイルの拡張子が .zip, .tar, .tar.gz の場合,展開される.この挙動を変える場合,--no-unzip オプションを使用する.

run

実行するコマンドのリスト.上から順に実行していく.

各コマンドの標準出力は記録される.先頭コマンドの標準出力は stdout0.txt,次のコマンドの標準出力は stdout1.txt というように番号付けられ,result で指定した場所へ保存される.標準エラー出力はコンテナの標準出力としてコンテナ外に出力される.したがって,処理結果など記録しておくべきものは標準出力に,実行時のログなどは標準エラー出力に書き出せば良い.

なお,標準出力の結果は /tmp/ に保存されるので,他のプログラムから利用することもできる.次の例は,/tmp/data を引数に run.sh を実行し,その標準出力の結果 /tmp/stdout0.txt を引数に次のコマンド plot.sh を実行している.

run:
  - ./run.sh /tmp/data
  - ./plot.sh /tmp/stdout0.txt

なお,apt パッケージ以外でプログラムの実行に必要なパッケージがある場合は,run セクションに書けば良い.

result

result セクションには,Cloud Storage の URL を指定する.そこに標準出力及び upload セクションで指定したファイルがアップロードされる.

upload

upload セクションには,Globパターンのリストを指定できる.ここで指定したパターンのいずれかにマッチしたファイルも,実行結果として result セクションで指定した Cloud Storage のバケットへアップロードされる.

result: gs://a-project/result/
upload:
- "*.out"

上記の例では,gs://a-project/result/stdout0.txtstdout1.txt に加えて /data/*.out にマッチするファイルもアップロードする.

Roadie-GCP イメージの拡張

実行するプログラムの準備や必要なライブラリのインストールは,aptdata, run を使えば行える.しかし,毎回同じ処理を行う場合,準備済みの Docker イメージを作成しておく方が早い.

例えば,次のような Dockerfile でイメージを作っておけば再利用しやすい.

FROM jkawamoto/roadie-gcp

# NumPy, SciPy, Matplotlib のインストール
RUN apt-get update && \
    apt-get install -y python-numpy python-scipy python-matplotlib

# matplotlib の設定
RUN mkdir -p /root/.config/matplotlib && \
    echo "backend: Agg" >> /root/.config/matplotlib/matplotlibrc

# 実行ファイルをコピー
ADD some_dir /root/

GCP インスタンスの作成と Roadie-GCP の実行

gcloud コマンドを使ってインスタンスを作成し実行する.Roadie-GCP イメージを拡張した jkawamoto/run というイメージが dockerhub にあるとする.

まず,script.yml を出力するスタートアップスクリプトを用意する.

#!/bin/bash
cd /root

cat <<EOF > script.yml
apt:
- unrar
source: https://github.com/abcdefg/some-program.git
data:
- http://mmnet.iis.sinica.edu.tw/dl/wowah/wowah.rar
run:
- unrar x -r wowah.rar
- ./analyze WoWAH
result: gs://somebucket/
upload:
- *.png
EOF

docker run -i jkawamoto/running < conf.yml

次に,gcloud コマンドでインスタンスを作成する.

$ gcloud compute --project "your_project_name" instances create "some_name" \
    --zone us-central1-b --image coreos --metadata-from-file startup-script="./startup.sh" \
    --machine-type "n1-standard-1" \
    --scopes=https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/devstorage.read_write

結果を Cloud Storage にアップロードし,インスタンスを削除するために,

の権限が必要になる.

おわりに

Roadie-GCP を使えば,比較的簡単にバッチ処理が行えると思う.特に処理が終わったらインスタンスを削除させるので,無駄にコストを払わなくて済む.

もっと自動化するためには,スタートアップスクリプトを自動生成したり,コンテナのログを Cloud Logging へ投げることも考える必要がある.それらを代わりに行ってくれる アプリケーション も作成してある. このアプリについては別の記事にまとめようと思う.