概要
Singularityコンテナのビルド方法は以下のようなものがあります。
- Singularity HubからPullする
- Docker HubからPullする
- Sandbox環境を使いビルドする
- 書き込み可能なイメージを使いビルドする
- 他のイメージフォーマットから変換する(例:Squashfs → writable ext3)
- Recipeファイルを使いビルドする
コンテナの再現性を確保すること、本番環境用のコンテナを作成することを目的とする場合には、Recipeファイルを使ったコンテナ作成方法が適しています。Recipeファイルを使う場合には、以下のようなメリットもあります。
- ファイルや環境変数を追加しやすい
- カスタムソフトウェアをインストールしやすい
本稿では、Recipeファイルのフォーマットを俯瞰するとともに、実際にRecipeファイルからイメージを生成する手順を説明します。詳細については公式ページを参照ください。
予備知識
Recipeファイルは大別すると2つの要素から構成されます。
- Header:ベースとなるOSを指定する部分
- Sections (Body):環境変数の設定やソフトウェアインストールについて記述する部分
Header
まずBootstrap:でベースとするイメージの取得先を指定します。この記述に依り、以降に続くキーワードは変化します。Bootstrap:に指定できる参照先は以下のようなものがあります。
Singularity Hubを指定する場合は以下のようになります。Bootstrap: shubにFrom:が続きます。
Bootstrap: shub
From: shub://<registry>/<username>/<container-name>:<tag>@<digest>
registry、tag、digestはオプションです。From:の冒頭、shub://も省略可能のようです。
例えば、白鳥氏のOpenFOAMのイメージを取得してビルドする場合には以下のようになります。
Bootstrap: shub
From: TakahisaShiratori/openfoam:4
Docker Hubを指定する場合は以下のようになります。上記と同様に、From:が続きます。
Bootstrap: docker
From: <registry>/<namespace>/<container>:<tag>@<digest>
例えば、Ubuntu 16.04のイメージを取得する場合は以下のようになります。
Bootstrap: docker
From: ubuntu:16.04
Sections
Sectionsはsection(scriptlet)から構成され、%から始まる文字列で区切られた領域に内容が記述されます。全てオプションとして記述されるものになり、必ず記述が必要なわけではありません。
Sectionの指定には以下のようなコマンドを利用できます。
| Notation | 説明 |
|---|---|
| %help | Singularityコマンドにhelpオプションを指定した際に表示されるコメントを記述する。 |
| %setup | コンテナにbase OSがインストールされた後にホスト側で実行する処理を記述する。 |
| %files | ホストからコンテナへのファイルコピーの処理を記述する。 |
| %labels | コンテナに格納するメタデータを記述する。 |
| %enviroment | コンテナが実行される際に読み込まれる環境変数を記述する。(ビルド時は無効) |
| %post | ビルド時にコンテナにbase OSがインストールされた後にコンテナ側で実行する処理を記述する。(ホストからコンテナへのファイルコピーは不可) |
| %runscript | コンテナが実行された際に呼び出される処理を記述する。 |
| %test | ビルドの最後の段階で行う処理、または、コンテナが実行された際に検証のために行う処理を記述する。 |
以下にいくつかの注意点を列記します。
-
%filesの処理は%postおよびインストールの処理の後に行われるため、%post処理中に必要となるファイルは%setupに置いてコピー処理を行います。 -
%setupにおいてコンテナ内にファイルをコピーするには$SINGULARITY_ROOTFSを使います。この指定がない場合はホスト側での処理になってしまいます。 -
%filesの処理は<source> <destination>のペアで記述されます。<destination>を省略した場合は、/直下にコピーされます。 - ビルド時に有効にさせたい環境変数がある場合には、
%environmentではなく%postに設定を記述します。 -
%labelsに記述されたメタデータは/.singularity.d/labels.jsonに格納されます。ここの記述は、singularity inspectで確認できます。 - Sectionが処理される順序は、[Build]
%setup→%post→%files→%test、[Run]%environment→%runscriptとなると考えられます。 - Sectionのいずれかの処理に失敗するとビルドは停止します。
Recipeファイルのフォーマット詳細については公式ページを参照ください。
準備
Singularityのイメージファイルのデフォルトのファイルフォーマットはsquashfsです。simgイメージが取り扱えるようにパッケージをインストールします。
sudo yum install -y squashfs-tools
なお、Recipeファイルからのビルドにはroot権限が必要になります。
操作
分子動力学計算ソフトウェアLAMMPSのコンテナイメージをRecipeファイルから作成する手順を説明します。
この操作は以下の手順で行います。
- Recipeファイルを作成する。
- Recipeファイルを指定して
buildコマンドを実行し、コンテナイメージを作成する。
Recipeファイルの作成
Recipeファイルの中では以下のような順序で操作を記述します。
- HeaderにDocker Hubからbase OS(CentOS)を取得する記述を行います。
-
%postに必要パッケージのインストール、LAMMPSのビルド・インストール処理を記述します。 -
%environmentに共有ライブラリの環境変数設定を記述します。 -
%runscriptにコンテナ実行時の処理を記述します。
以下内容は古家氏資料を参考にし、version 2.4における操作の説明に修正したものになります。
新規にRecipeファイルを作成します。
vi Singularity
Header情報を記述します。
Bootstrap: docker
From: centos:latest
次にインストール操作を%post以下に記述します。
%post
yum -y update
yum -y install gcc gcc-gfortran gcc-c++ make wget git
mkdir /tmp/build
cd /tmp/build
wget https://www.open-mpi.org/software/ompi/v1.6/downloads/openmpi-1.6.4.tar.gz
tar xvfz openmpi-1.6.4.tar.gz
cd openmpi-1.6.4
./configure --prefix=/usr/local
make
make install
cd /tmp/build
git clone -b 'patch_22Sep2017' https://github.com/lammps/lammps.git
cd lammps/src/
make g++_openmpi
cp lmp_g++_openmpi /usr/local/bin/
cd /
mkdir /enc
rm -rf /tmp/build
yum clean all
次に、共有ライブラリの環境変数を%enviromentに記述します。
%environment
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
続いて、run実行時の処理を記述します。
%runscript
/usr/local/bin/lmp_g++_openmpi
Recipeファイルを使ったイメージのビルド
上述のRecipeファイルを使い、lammps.simgを作成します。
sudo singularity build lammps.simg Singularity
なお、version 2.4以前においては、createコマンドを使い空のイメージを作成してからOSやアプリケーションのインストールを行う手法が取られていましたが、version 2.4以降はbuildコマンドを使い、イメージ作成とインストールを同時実行することが推奨されています。version 2.4では空のイメージを作成する場合は、image.createコマンドで代替することになりました。
補足
Proxy環境下において、Recipeファイルからのイメージ生成に失敗することがあります。http_proxy、https_proxyといった環境変数の設定を行っているにも関わらずエラーが発生する場合があります。
/usr/local/libexec/singularity/python/base.pyに以下のコマンドを追記することでこのエラーを回避できます。詳細はリンクを参照ください。
os.environ['http_proxy'] = "http://host:port"
os.environ['https_proxy'] = "http://host:port"
また、Recipeファイルからのビルドの際にもProxy設定が必要になります。%postの最初に以下のような記述の追記します。(ディストリビューションにより記述方法は異なります。)
export http_proxy="http://host:port"
export https_proxy="http://host:port"