(ChatGPTに生成させた下書きを私が修正した記事になります。)
バイオインフォマティクス解析では、解析ツールをDockerやApptainerを通じて配布することが増えています。
たとえば、
docker pull ...
docker run ...
apptainer exec ...
などと書かれていても、DockerやApptainerを使ったことがないと、そもそも何をしているのかよく分かりません。
「コマンドをコピーして実行したら何か動いたが、入力ファイルをどこに置けばよいのか分からない」「解析結果がどこに保存されたのか分からない」ということもよくあります。
そこで今回は、DockerとApptainerが何をするためのものなのか、最低限どのように使えばよいのかを説明します。
なぜDockerやApptainerを使うのか
例えばRNA-seq解析では、STAR、RSEM、SAMtools、DESeq2など、複数のソフトウェアを組み合わせて使います。
これらを自分でインストールしようとすると、それぞれについて、
- 対応するOS
- ソフトウェアのバージョン
- PythonやRのバージョン
- 必要なライブラリ
- ほかのソフトウェアとの依存関係
を考える必要があります。
ローカルPCでは動いたのに、共有サーバでは動かない…ということもあります。数年後に同じ解析を再実行しようとしたら、ソフトウェアの更新によってエラーが発生するということもあるでしょう。
DockerやApptainerは、解析に必要なソフトウェアと実行環境をまとめて配布する仕組みです。
簡単にいえば、
解析ソフト一式を、設定済みのLinux環境ごと箱に入れて配布する
ようなものです。
利用者は個々のソフトウェアをインストールする代わりに、その箱をダウンロードして、中に入っているソフトウェアを実行します。
これにより、利用者はインストールの手間を減らすことができ、一方開発者は個々の利用者に対するインストールトラブル対応の手間を削減することができます。
イメージとコンテナ
DockerやApptainerの説明では、「イメージ」と「コンテナ」という言葉が出てきます。
最初はこの2つの区別が分かりにくいのですが、次のように考えるとよいでしょう。
イメージは、解析環境を保存した箱です。
コンテナは、そのイメージを使って実際に起動した解析環境です。
同じDVDから何度でも映画を再生できるように、同じイメージから複数の異なるコンテナを生成・起動できます。
DockerまたはApptainer(イメージ)
└── コンテナ
└── コンテナ2
└── コンテナ3
Dockerの公式ドキュメントでも、イメージはプログラム、ライブラリ、設定などを含む標準化されたパッケージ、コンテナはイメージから起動される隔離されたプロセスとして説明されています。
ホストとコンテナ
DockerやApptainerを実行している元のPCやサーバをホストと呼びます。
ホスト
├── FASTQファイル
├── 解析結果
└── DockerまたはApptainer(イメージ)
└── コンテナ
├── STAR
├── SAMtools
└── DESeq2
└── コンテナ2
├── STAR
├── SAMtools
└── DESeq2
解析ソフトはコンテナの中にありますが、FASTQなどの入力ファイルは通常、ホスト側に保存します。
しかし、デフォルトではコンテナ内のファイルやディレクトリはホストから隔離されており、コンテナ内からホスト側のデータを見ることができません。
また、Dockerのコンテナ内部に作成したファイルはコンテナを削除すると失われるため、残したい解析結果はホスト側のディレクトリへ保存する必要があります。
したがって、実際に解析するときには、
ホスト側のディレクトリやその中のデータをコンテナ側から見えるようにする
必要があります。
Dockerではこれをマウント、Apptainerでは主にbind mountと呼びます。
DockerとApptainerの違い
DockerとApptainerは、どちらもコンテナを実行するためのソフトウェアですが、よく使われる環境が異なります。
| |
Docker |
Apptainer |
| イメージ |
Dockerイメージ |
主にSIFファイル |
| 管理者権限 |
導入や実行に管理者権限が必要 |
一般ユーザー権限で実行しやすい |
| データの共有 |
明示的なマウントが必要 |
カレントディレクトリなどが通常は自動的に共有される |
| 実行例 |
docker run |
apptainer exec |
SIFはSingularity Image Formatの略です。Apptainerは以前はSingularityという名前でしたが、現在はApptainerに変更されました。
Dockerはコマンド実行に管理者権限が必要なケースが多いため、共有のスパコンなどではDockerの使用を許可していないことがあります。そのような環境でApptainerがインストールされている場合は、Apptainerを使いましょう。
Apptainerは、特にHPC、つまり大規模計算機環境での利用を想定して開発されています。デフォルトでコンテナの内側でも同じユーザーIDで実行されるため、扱いやすくなっています。
Dockerが使えるか確認する
まず、Dockerがインストールされているか確認します。
docker --version
インストールされていれば、次のようにバージョンが表示されます。
Docker version 28.x.x, build ...
数字は環境によって異なります。
次のように表示された場合は、Dockerを実行できません。
docker: command not found
これは、Dockerがインストールされていないか、Dockerのコマンドが設定されていないことを意味します。
また、Dockerがインストールされていても、
permission denied
と表示される場合があります。この場合は、Dockerを実行する権限(管理者権限)が与えられていない可能性があります。
Dockerイメージを取得する
今回は練習用として、UbuntuのDockerイメージを使います。
以下を実行します。
docker pull ubuntu:24.04
それぞれの部分は次の意味です。
docker Dockerを使う
pull イメージをダウンロードする
ubuntu イメージの名前
24.04 イメージのバージョン
ubuntu:24.04のように、コロンの後ろに付いている部分をタグと呼びます。
バイオインフォマティクスツールでは、タグにソフトウェアのバージョンが使われることがあります。
ツール名:1.0.0
ツール名:2.1.3
バージョンを指定せずにlatestを使う例もありますが、解析の再現性を考えると、可能であればバージョンを明示した方がよいでしょう。
Dockerコンテナの中に入る
取得したUbuntuイメージからコンテナを起動します。
docker run --rm -it ubuntu:24.04 /bin/bash
このコマンドは、以下を意味します。
docker run イメージからコンテナを起動する
--rm 終了時にコンテナを削除する
-it ターミナルから対話的に操作する
ubuntu:24.04 使用するイメージ
bash コンテナ内でbashを起動する
実行すると、画面の左側が次のような表示に変わります。
root@a1b2c3d4e5f6:/#
これは、Ubuntuコンテナの中に入ったことを表しています。
試しに、コンテナ内のOSを確認します。
cat /etc/os-release
Ubuntuに関する情報が表示されます。
NAME="Ubuntu"
VERSION="24.04 LTS ..."
コンテナから出るときは、以下を実行します。
exit
元のターミナル画面に戻ります(コンテナ終了)。
--rmオプションを付けたので、終了した時点でコンテナが削除されます。
このオプションをつけない場合はコンテナが残り、再び接続することが可能です。
残す場合は、大量にコンテナが残っている、という状態にならないよう気をつけましょう。
ホスト側のファイルをDockerから見る
次に、ホスト側のファイルをDockerコンテナから読み書きしてみます。
まず、ホスト側で練習用ディレクトリを作ります。
mkdir docker_test
cd docker_test
mkdirはディレクトリを作るコマンド、cdは指定したディレクトリへ移動するコマンドです。
入力ファイルを1つ作ります。
echo "Hello from host" > input.txt
ここでDockerコンテナを起動します。
docker run --rm -it \
-v "$PWD":/work \
-w /work \
ubuntu:24.04 \
bash
複数行に分かれていますが、末尾の\は「次の行へ続く」という意味です。
$PWDには、現在いるディレクトリの絶対パスが入っています。したがって、
-v "$PWD":/work
は、
ホストの現在のディレクトリを、コンテナ内の/workとして見せる
という指定です。
-w /workは、コンテナを起動した直後の作業場所を/workにする指定です。
コンテナ内でファイルを確認します。
catコマンドで次のように表示されれば、ホスト側のファイルをコンテナから読めています。
$ ls
input.txt
$ cat input.txt
Hello from host
今度はコンテナ内から出力ファイルを作ります。
echo "Hello from container" > output.txt
コンテナから出ます。
exit
ホスト側でファイルを確認すると、次のように表示されるでしょう。
$ ls
input.txt output.txt
$ cat output.txt
Hello from container
これで、コンテナとホストでデータのやりとりができるようになりました。
ひとつ注意点として、Dockerを管理者権限で起動した場合、コンテナ内で生成したデータがホスト側では管理者所有のファイルになっていることがあります。
コンテナ内で生成したファイルをホスト側で閲覧・編集が可能かどうか、確認してみてください。
Apptainerが使えるか確認する
共有サーバでは、DockerではなくApptainerを使うことが多いでしょう。
以下を実行します。
apptainer --version
インストールされていれば、バージョンが表示されます。
apptainer version 1.x.x
環境によっては、Apptainerの以前の名称であるSingularityが使われている場合があります。
singularity --version
apptainerもsingularityも見つからない場合は、サーバ管理者に確認してください。
共有サーバでは、Environment Modulesを使ってApptainerを読み込む場合もあります。
module avail
または、
module avail apptainer
で表示される場合があります。ただし、moduleの使い方はサーバによって異なるため、利用している計算機のマニュアルを確認してください。
Apptainerイメージを取得する
Apptainerでは、Docker Hubで公開されているDockerイメージを取得し、SIF形式へ変換できます。
apptainer pull ubuntu_24.04.sif docker://ubuntu:24.04
それぞれの部分は次の意味です。
apptainer Apptainerを使う
pull イメージをダウンロードする
ubuntu_24.04.sif 保存するファイル名
docker://ubuntu:24.04 取得元のDockerイメージ
実行後にファイルを確認します。lsコマンドでubuntu_24.04.sifが表示されればSIFファイルを生成できています。
$ ls
ubuntu_24.04.sif
SIFは1つのファイルとして扱えるため、共有サーバ上で共有したり、別のディレクトリへ移動したりしやすくなっています。
Apptainerコンテナの中に入る
SIFファイルを使って、コンテナ内のシェルに入ります。
apptainer shell ubuntu_24.04.sif
次のような表示になります。
Apptainer>
Dockerの場合と同じように、OSを確認します。
cat /etc/os-release
現在のユーザーを確認します。
whoami
Dockerの先ほどの例ではコンテナ内のユーザーがrootでしたが、Apptainerでは通常、コンテナの外側と同じユーザー名が表示されます。
コンテナから出るには以下を実行します。
exit
Apptainerでコマンドをホスト側から実行する
Apptainerではコンテナ内に入らず、ホスト側からコマンドを直接実行することもできます。
apptainer exec ubuntu_24.04.sif cat /etc/os-release
このコマンドは、
apptainer exec コンテナ内でコマンドを実行する
ubuntu_24.04.sif 使用するイメージ
cat /etc/os-release コンテナ内で実行するコマンド
という意味です。
実際の解析では、次の形式を頻繁に使います。
apptainer exec 解析環境.sif 解析コマンド
たとえばSTARがインストールされたイメージであれば、次のような形になります。
apptainer exec rnaseq.sif STAR --version
つまり、普段実行しているコマンドの前に、
apptainer exec イメージファイル
を付けると考えればよいでしょう。
Apptainerは標準設定では、ホームディレクトリ、/tmp、現在の作業ディレクトリなどをコンテナへ自動的にbind mountします。
カレントディレクトリを明示的にマウントする必要がなく、ユーザIDも引き継がれるため、Dockerより扱いやすいでしょう。
別のディレクトリにあるデータを使う
解析データが現在のディレクトリやホームディレクトリ以外にある場合は、--bindを使います。
たとえば、FASTQがホストの/work/RNAseqにあるとします。/work/RNAseqはデフォルトではマウントされないため、以下のように明示的にマウントします。
apptainer exec \
--bind /work/RNAseq \
ubuntu_24.04.sif \
ls /work/RNAseq
/work/RNAseqのファイル一覧が表示されれば、コンテナからアクセスできています。
ホスト側とコンテナ側で別の名前にすることもできます。
apptainer exec \
--bind /work/RNAseq:/data \
ubuntu_24.04.sif \
ls /data
この場合は、
ホスト側 コンテナ側
/work/RNAseq → /data
という対応になります。
通常の解析では、同じパスをそのまま見せる方が混乱しにくいと思います。
--bind /work/RNAseq
複数のディレクトリを同時にマウントしたい場合はコンマでつなぎます。例えば/work/RNAseq と /work2/ChIPseq をマウントする場合は以下のようになります。
apptainer exec \
--bind /work/RNAseq,/work2/ChIPseq \
ubuntu_24.04.sif \
ls /work/RNAseq /work2/ChIPseq
DockerとApptainerで覚えるコマンド
最初に覚える必要があるコマンドは、それほど多くありません。
Dockerでは、以下を使います。
# イメージを取得する
docker pull イメージ名
# コンテナ内に入る
docker run --rm -it イメージ名 /bin/bash
# ホストの現在のディレクトリを/workとして共有しながらコンテナ内に入る
docker run --rm -it \
-v "$PWD":/work \
-w /work \
イメージ名 \
/bin/bash
# コンテナ内でコマンドを1つ実行する
docker run --rm \
-v "$PWD":/work \
-w /work \
イメージ名 \
コマンド
Apptainerでは、以下を使います。
# DockerイメージからSIFを作る
apptainer pull 出力名.sif docker://イメージ名
# コンテナ内に入る
apptainer shell イメージ.sif
# コンテナ内でコマンドを1つ実行する
apptainer exec イメージ.sif コマンド
# 別のディレクトリをコンテナから見えるようにしながらコマンドを1つ実行する
apptainer exec \
--bind /データのディレクトリ \
イメージ.sif \
コマンド
まとめ
DockerとApptainerは、解析ソフトウェアと実行環境をまとめて利用するための仕組みです。
最初に理解しておきたいのは、次の3点です。
- イメージは解析環境を保存したものであり、コンテナはそれを起動した状態です。
- 解析ソフトはコンテナ内にありますが、入力データと解析結果はホスト側に置きます。
- ホスト側のデータをコンテナから使うには、Dockerではマウント、Apptainerでは必要に応じてbindを指定します。
コンテナ技術そのものに詳しくならずとも、ここで紹介した使い方を理解していれば、公式に配布されている様々なイメージ(実行環境)を利用可能になります。
また、自分で独自のイメージを作成することにより、自分の研究に最適化した環境を様々なサーバで共有することも可能になります。その方法についてはまた別の記事で紹介したいと思います。
参考