Docker hubにDockerfileがない!

メタゲノム解析で使うqiime2のDockerイメージをプルしたときのこと。
中身が気になってDockerfileを見に行った。
ところが、、

Dockerイメージがなかった。Docker hub上に、なかったのだ。

何言ってんの?

つまりこういうこと。 通常、Docker hubにあがっているDockerイメージには以下のように、Dockerfileを見るタブがある。

f:id:kimoppy126:20180826092819p:plain

どれもDocker hub上でDockerfileが見れるものかと思ってた。

のに、

以下はqiime2のcoreレポジトリ

f:id:kimoppy126:20180826092833p:plain

ないっ!

理由

以下で割と丁寧に説明されていた。

forums.docker.com

理由の部分を引用する。

The user just didn’t set it up that way, that simple.
It is a base image, created from a chroot-like directory of files. There is no Dockerfile to represent this process.
Building requires special arguments/files not available in the auto build process
It doesn’t makes sense to use the auto build structure to create multiple tags.
Building the docker image required an interactive step that wasn’t/can’t be Dockerfile-ed
etc…

  • 単にユーザーがセットアップしていない
  • chrootが必要なファイルやディレクトリから作られたbaseイメージで、この工程を表すDockerfileの記法がなかった。
  • ビルドに自動ビルドでは用意できない特別な引数/ファイルが必要だった。
  • 複数のタグを作るのに、自動ビルドでは都合が悪かった。
  • interactiveなステップが必要であり、Dockerfileの記法で書けなかった。
  • その他もろもろ

こういった理由が考えられるらしい。

試しにタグの部分を見てみると、

f:id:kimoppy126:20180826104321p:plain

お。latest以外にもいっぱいある。

(擬似的な) Dockerfileの生成

もしそのDockerイメージがDockerfileから作られたものならば、docker inspectの出力から親レイヤを辿っていくことにより、疑似的なDockerfile(Dockerイメージ構築の流れを示したもの)を出力することができる。

ひたすら親レイヤを辿って実行命令を出力する、以下の関数を使う。

function dc_trace_cmd() {
  local parent=`docker inspect -f '{{ .Parent }}' $1` 2>/dev/null
  declare -i level=$2
  echo ${level}: `docker inspect -f '{{ .ContainerConfig.Cmd }}' $1 2>/dev/null`
  level=level+1
  if [ "${parent}" != "" ]; then
    echo ${level}: $parent 
    dc_trace_cmd $parent $level
  fi
}

これを使うと、以下のように擬似的なDockerfileが作られる。

$ dc_trace_cmd filippobosi/mfi

0: {[/bin/sh -c #(nop) CMD [/usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java -Xmx1024M -jar /usr/lib/mfi/lib/ace.jar start]]}
1: aac1201414083a093c714c8b7090408edf970445e119883a74b7b9453fd9db9f
1: {[/bin/sh -c #(nop) EXPOSE 6080/tcp 6443/tcp]}
2: 4db9381d42448ed494d0ce33f544ca0e9356692053251f2a266e71675da16952
2: {[/bin/sh -c apt-get install -y mfi-beta]}
3: 431cc26d6aeb1a996114b6f8db99b3b3922632edffaa52958c1002e6520aedf0
3: {[/bin/sh -c apt-get update]}
4: b3443169958a009f6215b96417d9d0b865255726596f177d2e36fd9f049788c5
4: {[/bin/sh -c apt-key adv --keyserver keyserver.ubuntu.com --recv C0A52C50]}
5: a800750eed1fe2ea9c86cf5c828b54a23cbefc7e2d06b966ebfbd75914963dca
5: {[/bin/sh -c echo 'deb http://dl.ubnt.com/mfi/distros/deb/ubuntu ubuntu ubiquiti' >> /etc/apt/sources.list]}
6: 996ab0d2afe09131de6c3bbce375b517cacf54ca7bc6cfed1a0eb9c66852fa62
6: {[/bin/sh -c apt-get update]}
7: fc0d0fd55e22a3bc558b2b51dfb16ca873b3cfce1f712a527921490b8f0bad28
7: {[/bin/sh -c #(nop) MAINTAINER filippobosi]}
8: 1185472e68e981b60e1b9b2fdf50b535a99cace38d9a2963168806496c9db78d
8: {[/bin/sh -c #(nop) CMD ["/bin/bash"]]}
9: a8444a8212ea7f2d92e73c5464a0e81113428c3c6e34f1f60bff6f807cf8a778
9: {[/bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list]}
10: 398cb6c3acd3b3b63a0fa77ebac4e673e38218248bd068f4a240f0301945d933
10: {[/bin/sh -c echo '#!/bin/sh' > /usr/sbin/policy-rc.d && echo 'exit 101' >> /usr/sbin/policy-rc.d && chmod +x /usr/sbin/policy-rc.d && dpkg-divert --local --rename --add /sbin/initctl && cp -a /usr/sbin/policy-rc.d /sbin/initctl && sed -i 's/^exit.*/exit 0/' /sbin/initctl && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes]}
11: bfb92c15de016926b76a101de38d1ddfd2b114cdd2999de1b36050f8f3fd9c9f
11: {[/bin/sh -c #(nop) ADD file:b43bf069650bac07b66289f35bfdaf474b6b45cac843230a69391a3ee342a273 in /]}

実行してみた。

ところが。。

$ dc_trace_cmd qiime2/core:2018.6

0: [/bin/sh -c #(nop) WORKDIR /data]

あれ、、Dockerfileこれだけ??
#(nop)はno operationを指すしていて、RUN以外の命令のことらしい。
つまり、このイメージを作ったDockerfileは、WORKDIR /data命令しかしていない?

考察

  • Docker hub上でDockerfileのないDockerイメージは、作成者のローカル環境でビルドされ、イメージだけがアップロードされている?

  • タグを分けてdockerイメージをバージョン管理する(Docker hubでgithub的な使い方をする)ために、Dockerfileをアップロードしてない?

  • qiime2の環境はおそらくインタラクティブに作られた?

疑問符の残る考察しかできない。 誰か答えを教えてください。。


参考:
How can I view the Dockerfile in an image? - General Discussions - Docker Forums
What is #(nop) and where does it come from? - General Discussions - Docker Forums
What does #(nop) mean in docker history? - Stack Overflow