ApptainerでNextflowのコンテナを動かそうとして苦戦した話

Apptainerはイミュータブルなコンテナイメージ形式を採用しているため、SIFコンテナ作成後にイメージ内を変更することはできません。
2023.05.29

こんにちは!コンサル部のinomaso(@inomasosan)です。

前回はApptainerというHPCに特化したコンテナプラットフォームをインストールして簡単な動作検証を実施しました。

せっかくなので、Nextflowというオープンソースで開発されている大規模なバイオインフォマティックス解析で使われているワークフローエンジンを、Apptainer上で動かそうとしたのですが、意外と苦戦してしまったのでブログにまとめていきます。

先にまとめ

  • Apptainerはイミュータブルなコンテナイメージ形式のため、基本的にはビルド以外でイメージ内に追加のパッケージ等の導入不可
  • Definition Fileの%postセクションで新しいソフトウェアやライブラリをインストールしたり、設定ファイルの書き込み、新しいディレクトリを作成等が可能
    • sandboxオプションでも対応可能だが再現性がなくなる可能性がある
  • Nextflowを管理しているコンテナから各種ツールのコンテナ呼ぶ構成は理想的ではないので避けた方がいいと言われているため、Nextflowはホストサーバにインストールする構成も検討した方が良い

ApptainerでNextflowのHello world実行失敗

今回はApptainer上で簡単な動作確認がしたかったので、Docker Hubのnextflow/nextflowのコンテナイメージでHello worldを試してました。

しかし、SIFファイル作成後にERROR ~ Unable to create plugins dir: /.nextflow/pluginsというメッセージが出力され、実行が失敗しました。

$ apptainer run docker://nextflow/nextflow:latest nextflow run hello
INFO:    Converting OCI blobs to SIF format
INFO:    Starting build...
Getting image source signatures
Copying blob 4edf64cf85c0 done
Copying blob bf72c394abb7 done
Copying blob a1e89988b6c0 done
Copying blob 62fd1cbca5f9 done
Copying blob 0638add0370f done
Copying blob c3f0bbd23613 done
Copying blob fdbc0e804c10 done
Copying config 27a8d24457 done
Writing manifest to image destination
Storing signatures
2023/05/29 06:49:05  info unpack layer: sha256:bf72c394abb748707ec4590d5017f36ad47098c9b92adc1b04c3ea3ba0b395f6
2023/05/29 06:49:05  warn rootless{dev/console} creating empty file in place of device 5:1
2023/05/29 06:49:05  warn rootless{dev/null} creating empty file in place of device 1:3
2023/05/29 06:49:05  warn rootless{dev/random} creating empty file in place of device 1:8
2023/05/29 06:49:05  warn rootless{dev/urandom} creating empty file in place of device 1:9
2023/05/29 06:49:05  warn rootless{dev/zero} creating empty file in place of device 1:5
2023/05/29 06:49:09  info unpack layer: sha256:4edf64cf85c039184023bdfaa7e82e8a607c7f0a55286cce0c938431af0d83d3
2023/05/29 06:49:13  info unpack layer: sha256:62fd1cbca5f9a86bc7d413a82b7707a24fd0369ed9bd03c05190f0665ca4f3c7
2023/05/29 06:49:19  info unpack layer: sha256:a1e89988b6c05d00cc1fd9e7e35b7e9881301cf3f9bd74ae3883448406267e90
2023/05/29 06:49:19  info unpack layer: sha256:0638add0370fe3b42b5eb71397768e22caaabf76ca84c4ba4a98b94706b11822
2023/05/29 06:49:19  info unpack layer: sha256:c3f0bbd23613185eadb849769a225b10db4babeb6c3419ce508a73c545efef77
2023/05/29 06:49:19  info unpack layer: sha256:fdbc0e804c10871837fe9d5f93139ae3569f753e9b57670edbaa573e9fbf8c61
INFO:    Creating SIF file...
N E X T F L O W  ~  version 23.05.0-edge
ERROR ~ Unable to create plugins dir: /.nextflow/plugins

 -- Check '.nextflow.log' file for details

Docker上で同様の内容を実行する分にはエラーは発生しなかったので、Apptainer側の問題である可能性が高いため原因を調査していました。

エラー原因

前回のApptainerを調べていた際に、特徴の一つとしてイミュータブルなコンテナイメージ形式であることを思い出しました。 このことからSIFコンテナ作成後は、基本的にイメージは変更不可であることに気がつきました。

調べてみるとDockerfileに相当するものとしてDefinition FileがApptainerにありました。
ガイドに以下のような記載がある通り、%postセクションに新しいソフトウェアやライブラリのインストール、設定ファイルの書き込み、新しいディレクトリを作成等を実施可能です。

This section is where you can download files from the internet with tools like git and wget, install new software and libraries, write configuration files, create new directories, etc.

エラー解消方法

Nextflowで特定のプラグインを作成させるコマンドが見つからなかったため、%postセクションでnextflow run helloを直接実行させることにしました。

まずは、適当なカレントディレクトリにNextflowのDefinition Filesとしてnextflow.defを作成します。

cat > nextflow.def << EOF
Bootstrap: docker
From: nextflow/nextflow

%post
    nextflow run hello
EOF

次に作成したnextflow.defを元にSIFのコンテナイメージを作成していきます。 今回はHellow world用のプラグインダウンロードが成功していることがわかります。

$ sudo apptainer build nextflow.sif nextflow.def
INFO:    Starting build...
Getting image source signatures
Copying blob c3f0bbd23613 done
Copying blob 62fd1cbca5f9 done
Copying blob bf72c394abb7 done
Copying blob 4edf64cf85c0 done
Copying blob a1e89988b6c0 done
Copying blob 0638add0370f done
Copying blob fdbc0e804c10 done
Copying config 27a8d24457 done
Writing manifest to image destination
Storing signatures
2023/05/29 06:45:16  info unpack layer: sha256:bf72c394abb748707ec4590d5017f36ad47098c9b92adc1b04c3ea3ba0b395f6
2023/05/29 06:45:20  info unpack layer: sha256:4edf64cf85c039184023bdfaa7e82e8a607c7f0a55286cce0c938431af0d83d3
2023/05/29 06:45:24  info unpack layer: sha256:62fd1cbca5f9a86bc7d413a82b7707a24fd0369ed9bd03c05190f0665ca4f3c7
2023/05/29 06:45:30  info unpack layer: sha256:a1e89988b6c05d00cc1fd9e7e35b7e9881301cf3f9bd74ae3883448406267e90
2023/05/29 06:45:30  info unpack layer: sha256:0638add0370fe3b42b5eb71397768e22caaabf76ca84c4ba4a98b94706b11822
2023/05/29 06:45:30  info unpack layer: sha256:c3f0bbd23613185eadb849769a225b10db4babeb6c3419ce508a73c545efef77
2023/05/29 06:45:30  info unpack layer: sha256:fdbc0e804c10871837fe9d5f93139ae3569f753e9b57670edbaa573e9fbf8c61
INFO:    Running post scriptlet
+ nextflow run hello
N E X T F L O W  ~  version 23.05.0-edge
Pulling nextflow-io/hello ...
 downloaded from https://github.com/nextflow-io/hello.git
Launching `https://github.com/nextflow-io/hello` [silly_ardinghelli] DSL2 - revision: 1d71f857bb [master]
executor >  local (4)
[f0/d86304] process > sayHello (4) [100%] 4 of 4 ✔
Bonjour world!

Ciao world!

Hello world!

Hola world!


INFO:    Creating SIF file...
INFO:    Build complete: nextflow.sif

最初に失敗したHello worldが実行できることを確認します。

$ apptainer run nextflow.sif nextflow run hello
N E X T F L O W  ~  version 23.05.0-edge
Launching `https://github.com/nextflow-io/hello` [evil_nightingale] DSL2 - revision: 1d71f857bb [master]
executor >  local (4)
[1a/5609e9] process > sayHello (4) [100%] 4 of 4 ✔
Ciao world!

Bonjour world!

Hello world!

Hola world!

他の解決策はないの?

--sandboxオプションを使用することで、書き込み可能なディレクトリ内にコンテナを作成することで変更することが可能なやり方があります。

以下は--sandboxオプションで対応した場合の例となります。

$ apptainer build --sandbox plugins/ docker://nextflow/nextflow
INFO:    Starting build...
Getting image source signatures
Copying blob 0638add0370f skipped: already exists
Copying blob a1e89988b6c0 skipped: already exists
Copying blob 4edf64cf85c0 skipped: already exists
Copying blob c3f0bbd23613 skipped: already exists
Copying blob 62fd1cbca5f9 skipped: already exists
Copying blob bf72c394abb7 skipped: already exists
Copying blob fdbc0e804c10 skipped: already exists
Copying config 27a8d24457 done
Writing manifest to image destination
Storing signatures
2023/05/29 08:27:15  info unpack layer: sha256:bf72c394abb748707ec4590d5017f36ad47098c9b92adc1b04c3ea3ba0b395f6
2023/05/29 08:27:15  warn rootless{dev/console} creating empty file in place of device 5:1
2023/05/29 08:27:15  warn rootless{dev/null} creating empty file in place of device 1:3
2023/05/29 08:27:15  warn rootless{dev/random} creating empty file in place of device 1:8
2023/05/29 08:27:15  warn rootless{dev/urandom} creating empty file in place of device 1:9
2023/05/29 08:27:15  warn rootless{dev/zero} creating empty file in place of device 1:5
2023/05/29 08:27:18  info unpack layer: sha256:4edf64cf85c039184023bdfaa7e82e8a607c7f0a55286cce0c938431af0d83d3
2023/05/29 08:27:23  info unpack layer: sha256:62fd1cbca5f9a86bc7d413a82b7707a24fd0369ed9bd03c05190f0665ca4f3c7
2023/05/29 08:27:29  info unpack layer: sha256:a1e89988b6c05d00cc1fd9e7e35b7e9881301cf3f9bd74ae3883448406267e90
2023/05/29 08:27:29  info unpack layer: sha256:0638add0370fe3b42b5eb71397768e22caaabf76ca84c4ba4a98b94706b11822
2023/05/29 08:27:29  info unpack layer: sha256:c3f0bbd23613185eadb849769a225b10db4babeb6c3419ce508a73c545efef77
2023/05/29 08:27:29  info unpack layer: sha256:fdbc0e804c10871837fe9d5f93139ae3569f753e9b57670edbaa573e9fbf8c61
WARNING: The sandbox contain files/dirs that cannot be removed with 'rm'.
WARNING: Use 'chmod -R u+rwX' to set permissions that allow removal.
WARNING: Use the '--fix-perms' option to 'apptainer build' to modify permissions at build time.
INFO:    Creating sandbox directory...
INFO:    Build complete: plugins/
$ apptainer shell --writable plugins/
Apptainer> nextflow run hello
N E X T F L O W  ~  version 23.05.0-edge
Pulling nextflow-io/hello ...
 downloaded from https://github.com/nextflow-io/hello.git
Launching `https://github.com/nextflow-io/hello` [stoic_koch] DSL2 - revision: 1d71f857bb [master]
executor >  local (4)
[53/cfba17] process > sayHello (4) [100%] 4 of 4 ✔
Bonjour world!

Ciao world!

Hello world!

Hola world!

サンドボックスで編集後にSIFコンテナに変換することができるのですが、ガイドに記載されているように変換前に書き込み可能がコンテナに変更があった場合は、変更内容の再現不可能となるため、ApptainerのDefinition Fileから構築することがベストプラクティスとなるようです。

Use care when converting a sandbox directory to the default SIF format. If changes were made to the writable container before conversion, there is no record of those changes in the Apptainer definition file rendering your container non-reproducible. It is a best practice to build your immutable production containers directly from an Apptainer definition file instead.

そもそも論として

Nextflow のローカル開発環境のために Docker コンテナを利用してみてわかったことここで疑問に引用されている通り、Nextflowを管理しているコンテナから各種ツールのコンテナ呼ぶ構成は理想的ではないので避けた方がいいと言われています。

Even though this is possible (docker within docker), it is not ideal and should be avoided. Nextflow is easy enough to install (it's just a file downloaded) and Java is practically everywhere, so you should be able to run nextflow natively wherever you are ?

Running nextflow inside docker container · nextflow-io/nextflow · Discussion #3177


また、NextFlowドキュメントにはApptainerでの使い方があったので確認したのですが、NextFlowをホストサーバにインストールするのが前提のようでした。

まとめ

Apptainerは日本語記事や、今回の事象に関連する記事等が少なかったため、原因調査に時間がかかってしまいました。

Apptainer初心者の方が、Dockerと比較して最初にハマりやすいポイントと感じたのでまとめてみました。

この記事が、どなたかのお役に立てば幸いです。それでは!