10. Singularityの使い方¶
Singularityは、ソフトウェアを動作させるための仮想的な環境であるコンテナと呼ばれる仕組みを利用するためのプラットフォームです。コンテナを活用することで、異なるマシンやOSにおいても同じ環境でソフトウェアを動かすことができるため、ユーザーにとっては依存関係などを気にせずソフトウェアを使うことができ、また開発者にとっては可搬性や再現性を担保することができるといった利点があります。
各種ソフトウェアはイメージと呼ばれるパッケージの形態からコンテナを起動することで使用できます。イメージはDocker用に配布されているものをSingularityでも利用することができます。ToMMoスパコンにはSingularityが既にインストールされているため、配布されているイメージを使用するだけならば、Singularity自体を個々人でインストールする必要はありません。
10.1. Docker Hub からイメージを作る¶
注釈
この手順はインターネットへの接続が必要なため、UnitAのみの対応となります。UnitAにて次のコマンドを実行してから手順を進めてください。
$ export https_proxy=http://epx3x01:8080
$ export http_proxy=http://epx3x01:8080
Docker用にDocker Hubで配布されているイメージを、Singurlarity用に変換して使うことができます。
Docker Hubで使用したいイメージを探し、名前を確認します。
イメージのダウンロードとSingularity用イメージへの変換を行なうには、
singularity build (作成したいイメージの名前.sif) docker://(Dockerイメージの名前)
とします。
$ singularity build lolcow.sif docker://sylabsio/lolcow
正常に動作することを確認します。
$ singularity run lolcow.sif
______________________________
< Fri Jun 10 12:38:45 JST 2022 >
------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
10.2. 使用例¶
作成したイメージからコンテナを起動しコマンドを実行するには、
singularity exec (イメージの名前.sif) (実行したいコマンド) (引数)
とします。
$ singularity exec lolcow.sif cowsay hello
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
パイプでデータを渡すこともできます。
$ echo pipe | singularity exec lolcow.sif cowsay
______
< pipe >
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
singularty shell
を使うと、対話型の環境を実行することができます。
$ singularity shell lolcow.sif
Singularity> cowsay interactive
_____________
< interactive >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ヒント
対話型環境を終了するにはexit
と入力するか、control+Dを押します。
10.2.1. スパコン上の共有データ等を使用する際の注意¶
/share1/public
以下の共有データなどをコンテナから利用したい場合、そのままではアクセスすることができません。
$ singularity exec lolcow.sif ls /share1/public
/usr/bin/ls: cannot access '/share1/public': No such file or directory
これを可能にするには、コンテナ起動時に--bind
オプションでアクセスしたいパスを指定 (バインド) します。
$ singularity exec --bind /share1/public lolcow.sif ls /share1/public
database genome
singularity shell
の場合も同様に、singularity shell --bind
に続いてアクセスしたいパスを指定します。
ヒント
ホームディレクトリ$HOME
や カレントディレクトリ$PWD
などは、 (デフォルトの設定では) 自動的にバインドされます。(参考)
10.3. 自分でイメージを作る¶
自分でSingularity用のイメージを構築します。権限の関係上、スパコンではなくローカルのマシンで、Docker用に構築したイメージをSingularity用に変換するという手順で行ないます。
お手元のマシンにDockerがインストールされていない場合、公式の手順に従ってインストールしてください。
ヒント
手元にSingularityをインストールし直接Singularity用のイメージを作成することも可能ですが、Dockerの方が導入が簡単なため、この説明ではDockerを用いた手順を採用しています。
おおまかな手順としては、
Dockerfileを記述する
Docker用にイメージをビルド (構築) する
Singularity用にイメージを変換する
という流れです。まずは簡単な例で手元で動作することを確認してみましょう。
10.3.1. 簡単な例¶
Dockerfileは、イメージをビルドするための命令を列挙したテキストファイルです。(詳しい書き方はBest practicesもご参照ください)
適当な作業用ディレクトリに以下のディレクトリを作成して、以降の工程を進めます。
$ mkdir my_docker_dir
最低限の例として、my_docker_dir/Dockerfile
を次のように記述します (一行のみ) 。
1FROM ubuntu:20.04
2ENTRYPOINT ["/bin/sh", "-c", "echo Hello"]
これからイメージをビルドしコンテナを起動するには、次のコマンドを使用します。
$ docker build -t user_name/my_image:0.1 my_docker_dir/ # -t (ユーザー名)/(イメージ名):(バージョン) の形式
... # ログが表示される
$ docker run --rm user_name/my_image:0.1
Hello
docker build
でイメージを構築し、docker run
でそこからコンテナを起動し指定されたコマンドを実行しています(--rm
オプションをつけることで動作終了後コンテナを削除 ) 。うまくいっていればHello
と表示されます。
10.3.2. Singularity用のイメージに変換¶
Docker用のイメージからSingularity用のイメージへの変換は、docker2singularityで行なえます。
まず出力用のディレクトリを作成します。
$ mkdir out_sif
次のコマンドでdocker2singularityを実行します。
$ docker run -v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD/out_sif:/output \
--privileged -t --rm \
quay.io/singularity/docker2singularity \
--name my_singularity_image-0.1 \ # 変換後のイメージ名を指定
user_name/my_image:0.1
出力されたout_sif/my_singularity_image-0.1.sif
をscp
コマンドなどで転送すれば、スパコン上のSingularityでも同様に動作させることができます。詳しい転送方法は、Unit Aとインターネットにつながった手元の端末でデータを転送する方法もご参照ください。
10.3.3. 実践的な例¶
現実的なプログラム動作環境のイメージ化を想定した手順を、PythonとRの二通りの例で説明します。Dockerfile
などを適宜記述しイメージ化することで、動作環境ごとプログラムを配布することができます。
10.3.3.1. Python動作環境のイメージを構築する¶
特定のバージョンのPythonやモジュールの下で動くことを期待したプログラムのための環境を、イメージとして作成します。(参考:Build your Python image)
適当な作業用ディレクトリに以下のディレクトリを作成して、以降の工程を進めます。
$ mkdir my_docker_dir_py
my_docker_dir_py/Dockerfile
を以下のように記述します。
1FROM python:3.10-slim-buster
2COPY requirements.txt requirements.txt
3RUN pip3 install -r requirements.txt
4COPY . .
5ENTRYPOINT ["python3", "my_app.py"]
Pythonのバージョンを指定 (今回は3.10系) し、requirements.txt
に記述されたモジュールをインストールしたのち、my_app.py
を実行するという流れです。
モジュールとして、今回はNumPyのみを使用することとし、my_docker_dir_py/requirements.txt
を以下のように記述します (一行のみ) 。
1numpy==1.22.4
動作確認用のプログラムとして、my_docker_dir_py/my_app.py
を以下のように記述します。
1#!/usr/bin/env python3
2
3import sys
4
5import numpy as np
6
7
8def _main():
9 py_expected = '3.10'
10 py_running = ('.').join([str(x) for x in sys.version_info[:2]])
11 print('Expected python version:', py_expected)
12 print('Running python version :', py_running)
13 print()
14
15 numpy_expected = '1.22.4'
16 numpy_running = np.__version__
17 print('Expected numpy version:', numpy_expected)
18 print('Running numpy version :', numpy_running)
19
20
21if __name__ == '__main__':
22 _main()
PythonおよびNumPyのバージョンをチェックし、想定した通りのバージョンが動作していることを確認しています。
ビルドとコンテナの起動を以下のコマンドで行ないます。
$ docker build -t user_name/my_image_py:0.1 my_docker_dir_py/
...
$ docker run --rm user_name/my_image_py:0.1
Expected python version: 3.10
Running python version : 3.10
Expected numpy version: 1.22.4
Running numpy version : 1.22.4
あとは上記の例と同様にSingularity用のイメージに変換し、my_app.py
とともにスパコン上に転送すれば、ローカル環境と同様に動作します。
10.3.3.2. R動作環境のイメージを構築する¶
Rの場合もPythonと同様に、特定のバージョンのRやパッケージの下で動くことを期待したプログラムのための環境を、イメージとして作成します。
適当な作業用ディレクトリに以下のディレクトリを作成して、以降の工程を進めます。
$ mkdir my_docker_dir_r
my_docker_dir_r/Dockerfile
を以下のように記述します。
1FROM r-base:4.2.0
2RUN R -e "install.packages('remotes', repos='https://cran.ism.ac.jp/')"
3RUN R -e "remotes::install_github('cran/class@7.3-20')"
4COPY . .
5ENTRYPOINT ["Rscript", "my_app.R"]
Rのバージョンを指定 (今回は4.2.0) し、必要なパッケージをインストールしたのち、my_app.R
を実行するという流れです。パッケージのバージョンを指定するためremotesをはじめにインストールし、それを使って今回はclassをGitHubからインストールしています。
動作確認用のプログラムとして、my_docker_dir_r/my_app.R
を以下のように記述します。
1#!/usr/bin/env Rscript
2
3library(class)
4
5
6r_expected = '4.2.0'
7r_running = strsplit(version[['version.string']], ' ')[[1]][3]
8print(paste('Expected R version:', r_expected))
9print(paste('Running R version :', r_running))
10print('')
11
12class_expected = '7.3.20'
13class_running = packageVersion('class')
14print(paste('Expected class version:', class_expected))
15print(paste('Running class version :', class_running))
Rおよびclassのバージョンをチェックし、想定した通りのバージョンが動作していることを確認しています。
ビルドとコンテナの起動を以下のコマンドで行ないます。
$ docker build -t user_name/my_image_r:0.1 my_docker_dir_r/
...
$ docker run --rm user_name/my_image_r:0.1
[1] "Expected R version: 4.2.0"
[1] "Running R version : 4.2.0"
[1] ""
[1] "Expected class version: 7.3.20"
[1] "Running class version : 7.3.20"
これをSingularity用のイメージに変換し、my_app.R
とともにスパコン上に転送すれば、ローカル環境と同様に動作します。