ジョブスケジューラーにdockerコマンドを実行させる

例えば、Rを使って、以下のような4×3の行列(testdata.csv)に対して、遺伝子ごとに平均値が0、分散が1になるようにスケーリングした結果を、新たにscaled_testdata.csvとして保存したいとする。

echo ",Gene1,Gene2,Gene3" > testdata.csv

echo "Cell1,2,1,3" >> testdata.csv
echo "Cell2,4,3,6" >> testdata.csv
echo "Cell3,5,4,7" >> testdata.csv
echo "Cell4,4,3,8" >> testdata.csv

Rで以下のように実行すれば、目的のものが手に入る。

input <- read.csv("testdata.csv")

scaled <- scale(input)
write.csv(scaled, "scaled_testdata.csv", quote=FALSE)

この作業を、Sun Grid Engineがある環境で、実行内容を書いたシェルスクリプトをqsubすることで行いたい。

また、特定のバージョンのRやパッケージを使うなどを想定して、dockerコマンドも使う。

手順は以下の通り。


Step.1 : Dockerコンテナを用意する

rockerを使うと、気軽にRがインストールされたLinux環境が手に入るので、プルして使う。

docker pull rocker/r-base

docker run -i -t rocker/r-base:latest /usr/bin/R -e 'sessionInfo()'

R version 3.5.1 (2018-07-02)がインストールされているもよう。


Step.2 : qsubするシェルスクリプトにdockerコマンドを書く

次に、以下のようなシェルスクリプト(Job.sh)を作成する。

#!/bin/bash

#$ -l nc=4
#$ -q node.q

# which dockerでは/bin/dockerにdockerコマンドあった
/bin/docker run --rm -v /home/antiplastics/Docker:/Docker \
rocker/r-base:latest sh \
-c "/usr/bin/R -e 'input <- read.csv(\"/Docker/testdata.csv\");\
scaled <- scale(input);
\
write.csv(scaled,
\"/Docker/scaled_testdata.csv\", quote=FALSE)'"

ここでは、作業環境が、/home/antiplastics/Dockerだったとして、コンテナ内に/Dockerというディレクトリを作成して、そこでtestdata.csvが触れるように-vオプションを使っている(重要)。

これをqsubすれば、scaled_testdata.csvが/home/antiplastics/Docker以下に出力される。

qsub Job.sh


Step.3 : アレイジョブで、3回同じ事をする

通し番号1,2,3を設定し、番号ごとに違うことをするべく、アレイジョブでqsubする。

ArrayJob.shというファイルを以下のように書いて、上記と同様、qsubした。

#!/bin/bash

#$ -l nc=4
#$ -t 1-3
#$ -q node.q

mkdir -p /home/antiplastics/Docker/$SGE_TASK_ID

/bin/docker run --rm -v /home/antiplastics/Docker:/Docker \
rocker/r-base:latest sh \
-c "/usr/bin/R -e 'input <- read.csv(\"/Docker/testdata.csv\");\
scaled <- scale(input);
\
write.csv(scaled,
\"/Docker/$SGE_TASK_ID/scaled_testdata.csv\", quote=FALSE)'"

qsub ArrayJob.sh

Step.2のJob.shと大体同じだが、

#$ -t 1-3

というqsubオプションにより、$SGE_TASK_IDに1から3までの値が格納され、各々別々のジョブとして実行される。

これにより、/home/antiplastics/Docker/{1..3}に、別々にscaled_testdata.csvが出力される。