2.13. コンテナの使用#

2.13.1. Dockerの内部でツールを実行する#

Dockerコンテナは、ソフトウェアとその依存関係のための完全な既知の良いランタイムを提供することによって、ソフトウェアのインストールを簡素化します。 しかし、コンテナはホストシステムから意図的に隔離されているため、Dockerコンテナ内でツールを実行するには、入力ファイルがコンテナ内で利用可能で、出力ファイルがコンテナから回収できることを確認するための追加作業が必要です。 CWL runnerはこの作業を自動的に行うことができるため、Dockerコンテナの呼び出しや管理の複雑さを回避しながら、Dockerを使用してソフトウェア管理を簡素化できます。

CWL runnerの役割のひとつに、入力ファイルのパスをコンテナ内のでのパスに合わせることがあります。

この例では、Dockerコンテナ内で簡単なNode.jsスクリプトを実行し、標準出力に「Hello World」と表示します。

docker.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: node
hints:
  DockerRequirement:
    dockerPull: node:slim
inputs:
  src:
    type: File
    inputBinding:
      position: 1
outputs:
  example_out:
    type: stdout
stdout: output.txt
docker-job.yml#
src:
  class: File
  path: hello.js

これを実行する前に、これを分解して、いくつか細かく何をするのかを見てみましょう。 この大部分は以前のセクションで説明したもので、本当に新しいのはdockerRequirement の部分だけです。

baseCommand: node
hints:
  DockerRequirement:
    dockerPull: node:slim

baseCommand: node は、Javascript ファイル用の Node Js ランタイムを使用してこのコマンドを実行することを CWL に指示します。次に、必要なコンテナを見つける方法について、hints をいくつか指定する必要があります。 この場合、DockerRequirements に docker コンテナに関する要件だけを列挙します。 dockerPull: パラメータは、docker pull コマンドに渡すのと同じ値を取ります。つまり、コンテナイメージの名前です(タグを指定することも可能で、再現可能な研究にコンテナを使用する際のベストプラクティスに適しています)。この場合、node:slim というコンテナを使用しました。

Javascriptで "hello.js "というファイルを作成し、cwltool コマンドラインでツール定義と入力オブジェクトを指定して呼び出します:

hello.js#
console.log("Hello World");
$ cwltool docker.cwl docker-job.yml
INFO /opt/hostedtoolcache/Python/3.9.19/x64/bin/cwltool 3.1.20240508115724
INFO Resolved 'docker.cwl' to 'file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/using-containers/docker.cwl'
INFO [job docker.cwl] /tmp/qo5vhm37$ docker \
    run \
    -i \
    --mount=type=bind,source=/tmp/qo5vhm37,target=/puBHaQ \
    --mount=type=bind,source=/tmp/9j95bijv,target=/tmp \
    --mount=type=bind,source=/home/runner/work/user_guide/user_guide/src/_includes/cwl/using-containers/hello.js,target=/var/lib/cwl/stge88fb01a-b830-4460-8fd7-692b07452116/hello.js,readonly \
    --workdir=/puBHaQ \
    --read-only=true \
    --net=none \
    --log-driver=none \
    --user=1001:127 \
    --rm \
    --cidfile=/tmp/q_03q71y/20240518114653-403171.cid \
    --env=TMPDIR=/tmp \
    --env=HOME=/puBHaQ \
    node:slim \
    node \
    /var/lib/cwl/stge88fb01a-b830-4460-8fd7-692b07452116/hello.js > /tmp/qo5vhm37/output.txt
INFO [job docker.cwl] completed success
{
    "example_out": {
        "location": "file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/using-containers/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$648a6a6ffffdaa0badb23b8baf90b6168dd16b3a",
        "size": 12,
        "path": "/home/runner/work/user_guide/user_guide/src/_includes/cwl/using-containers/output.txt"
    }
}INFO Final process status is success
$ cat output.txt
Hello World

CWL runnerがスクリプトを実行するためにDockerコマンドラインを構築していることに注目してください。

この例では、スクリプトhello.js のパスは、コンテナの外側では /home/me/cwl/user_guide/hello.js が、コンテナの内側では/var/lib/cwl/job369354770_examples/hello.js です。これはnode コマンドの呼び出しに反映されているためです。