Palmsonntagmorgen

NGSデータを使った解析と、その周辺。

Singularityを使ったDocker環境の利用が楽ちんという話

今回も解析環境構築にまつわるお話です。
結論を先に書くと、Docker使うならSingularityオススメ

Singularityとは

7月に書いた下記エントリでは、Dockerを使うメリットについて簡単に説明しました。

rnakato.hatenablog.jp

一方、Dockerにはいくつか不満な点が残ります。

  • 実行にsudo権限が必要である。共有サーバの場合、全ユーザにsudo権限を与えるのはセキュリティ的に問題。
  • sudo権限を与えられていない環境 (スパコンなど)では利用が難しい。
  • sudoで実行するため(デフォルトのコマンドでは)コマンド実行で生成されるファイルの所有者がrootになる。
  • コマンドを実行するためにまずDockerコンテナの生成・削除が必要なのがやや面倒。
  • ホストディレクトリとコンテナ内ディレクトリの紐づけ(マウント)がやや面倒。

JupyterやSQLデータベースのようにバックグラウンドで起動させる用途であれば、サーバ起動時に管理者がコンテナ起動しておけば良いだけなのでそれほど問題にはなりませんが、NGS解析のように各ユーザがアクティブにコマンド実行してデータ生成・処理をするような場合にはsudoまわりの問題は厄介です。

そこで登場するのがSingularityです。

www.ecomottblog.com

上記のページがわかりやすいですが、Docker単体と比較したSingularityのメリットは以下のようなものです。

  • Dockerのイメージを利用可能
  • sudo不要(ユーザが引き継がれる)
  • コンテナ起動不要
  • カレントディレクトリが自動でマウントされる
  • GUIGPUなどデバイス回りの対応が楽

私の管理するサーバのユーザに試してもらったところ、ユーザごとに追加の環境設定をしてもらう必要もなく、Dockerの概要を深く説明する手間もなく、通常のコマンドとほぼ同じ感じで利用可能でした。なので、NGS解析用共用サーバの管理に悩まされている管理者の方には特にお勧めします。 たとえば以下のような悩みから解放されます。

rnakato.hatenablog.jp

Singularityを試してみる

Singularityのインストールは多少面倒なのでひとまず後回しにし、ここではSingularityをインストール済という前提で、使用例を示します。

Dockerイメージのダウンロード

まず、singularity pull コマンドでDockerイメージをローカルに保存します。
DockerイメージはDocker Hubなどのレポジトリに登録されている必要があります。 ここでは例として私の作ったssp_drompa を使います*1。これはSSP, DROMPA3, DROMPAplusがインストール済のUbuntuイメージです。

$ singularity pull ssp_drompa.img docker://rnakato/ssp_drompa
INFO:    Starting build...
Getting image source signatures
Skipping fetch of repeat blob sha256:5b7339215d1d5f8e68622d584a224f60339f5bef41dbd74330d081e912f0cddd
(中略)
Writing manifest to image destination
Storing signatures
INFO:    Creating SIF file...
INFO:    Build complete: ssp_drompa.img

ssp_drompa.img という名前でイメージファイルが保存されました(ファイル名は自由に決められます)。 イメージファイルはLinux環境を丸ごと保存したものであり、ファイルサイズはそれなりに大きいです。特に大きいイメージだと10GBを超えるものもあります。 ssp_drompa.imgは473Mなので、やや小さめですね。

$ ls -lh
合計 473M
-rwxrwxrwx 1 rnakato rnakato 473M  821 16:19 ssp_drompa.img

イメージの利用

ここではsspを例にして実験します。まずは、普通にローカルのsspを実行してみます。

$ ssp
ssp: command not found

おそらく多くの方はsspをインストールしていないと思いますので*2、not foundになったのではないでしょうか。

次に、Singularityのイメージを使ってコマンドを実行します。 コマンドは、以下のようになります。

singularity exec <イメージファイル> <コマンド>

$ singularity exec ssp_drompa.img ssp

SSP v1.1.3
===============

Usage: ssp [option] -i <inputfile> -o <output> --gt <genome_table>
Use --help option for more information on the other options

イメージ内のSSPが起動し、ヘルプが表示されました。

優秀な読者の方は既にSSPをインストールしてくれているかもしれません。その場合はローカルのSSPと区別するために which ssp してみましょう。

$ singularity exec ssp_drompa.img which ssp
/home/SSP/bin/ssp

/home/SSP/bin/ssp というパスが表示されれば、イメージ内のsspになっている証拠です。

重要なポイントは、「あるツールを利用したいのだが、ローカルPCにはまだインストールされていないという時に、イメージファイルをダウンロードするだけで利用可能な状態になる」という点です。通常ですとローカルPCにそのツールをインストールしよう!という流れになる訳ですが、何らかの理由でエラーになり、インストールをあきらめてしまうということはよくあると思います(冒頭のDockerエントリ参照)。イメージのダウンロード形式に切り替えることでインストールのコストが不要となり、すぐにツールを導入できます。Python2系と3系の共存もこれで問題なくなります。

上記のメリットはDockerでも共通ですが、Singularityの場合は実行したいコマンドの前に singularity exec <イメージファイル> を追加するだけですので、初心者の方でも技術的に難しいことはありません。PATHを追加で通す必要もなくなるので、むしろ簡単になるかもしれません*3

Dockerの場合

同じことをDockerでやる場合は以下のようになります。

$ sudo docker pull rnakato/ssp_drompa  # イメージのダウンロード
$ sudo docker run -it --rm  rnakato/ssp_drompa ssp

(本来はコンテナをバックグラウンドで起動し、そのコンテナを指定してコマンドを実行するという二段階のステップを踏む必要がありますが、ここでは簡単のため「コマンド実行のためにコンテナを起動し、コマンド終了と同時にコンテナを削除する」というオプションにしています。)

Dockerの場合はsudo権限が必要になります。ユーザをdockerグループに所属させることでsudoなしで実行できるようになりますが*4、管理者権限で実行しているという点は変わりません。従って、Dockerコマンドによって生成されるファイルの所有者はrootになります。
Dockerのコマンドで生成されるファイルを一般ユーザ権限にするためには -u $(id -u):$(id -g) -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v /etc/shadow:/etc/shadow:ro のようなオプションを追加してやる必要がありますが、やや面倒です。

ホストディレクトリのマウント

Singularityの場合はカレントディレクトリを自動でマウントしますので、カレントディレクトリ以下にあるファイルはそのまま参照できます。異なるディレクトリのファイルやツールを利用したい場合は別途 --bind オプションでマウントしてやる必要があります。

例として、/work ディレクトリをマウントする場合は以下のようになります。

$ singularity exec --bind /work ssp_drompa.img ssp -i /work/sample.bam --gt /work/genome_table

Dockerですと全てのホストディレクトリをマウントする必要があります。コマンドは以下のようになります。

$ sudo docker run -it --rm -v $(pwd):$(pwd) -v /work:/work rnakato/ssp_drompa ssp -i /work/sample.bam --gt /work/genome_table

-v オプションでマウントします。ディレクトリのパスは絶対パスである必要があります。

Singularityの注意点

  • Docker Hub上でイメージが更新された場合、それを反映するためにはイメージをダウンロードしなおす必要があります。
  • イメージは通常バージョン管理されていますので、バージョン番号をイメージファイル名につけておくと良いと思います。
  • ダウンロードしたイメージ内で更にパッケージをインストールするなど、イメージの内容をローカルで追加編集したい場合はSingularityでもsudo 権限が必要になります。そのようなケースでは、DockerとSingularityを併用するのがよいのではないかと思います。

Singularityのインストール

最後になりましたが、インストール方法です。

以下が公式のマニュアルです。

Mac, Windowsのインストール方法は試していないので、ここでは私がLinuxへインストールした時の方法を載せておきます。
Singularityのversion 2であればaptで入りますが、最新のversion 3は自分でコンパイルする必要があります。

なお、2019年8月時点では、WSL2だとインストールには成功するもののコマンドの実行は ERROR : Failed to set securebits: Invalid argument というエラーが出てうまくいかないようでした。

必要なパッケージのインストール

sudo apt-get update && sudo apt-get install -y \
   build-essential \
   libssl-dev \
   uuid-dev \
   libgpgme11-dev \
   squashfs-tools \
   libseccomp-dev \
   wget \
   pkg-config \
   git

Goのインストール

$ VERSION=1.12.7.linux-amd64
$ wget https://dl.google.com/go/go$VERSION.tar.gz 
$ sudo tar -C /usr/local -xzvf go$VERSION.tar.gz 
$ rm go$VERSION.tar.gz
$ echo 'export GOPATH=${HOME}/go' >> ~/.bashrc && \
 echo 'export PATH=/usr/local/go/bin:${PATH}:${GOPATH}/bin' >> ~/.bashrc && \
 source ~/.bashrc

Singularityのインストール

$ git clone https://github.com/sylabs/singularity.git 
$ cd singularity
$ git checkout v3.2.1
$ ./mconfig 
$ make -C ./builddir 
$ sudo make -C ./builddir install

参考:Singularityのインストール (v3) - Qiita

感想

DockerよりSingularityの方が楽。

*1:https://hub.docker.com/r/rnakato/ssp_drompa

*2:使ってくれているという方は、どうもありがとうございます。

*3:実際、初心者にとってはインストール自体よりパスを通すことの方が難しく感じることもあります。

*4:https://qiita.com/matyapiro31/items/3e6398ce737e2cdb5a22