是否可以从映像生成Dockerfile ?我想知道有两个原因:

我可以从存储库下载图像,但希望看到生成它们的配方。 我喜欢保存快照的想法,但一旦我完成了,有一个结构化的格式来回顾所做的事情会很好。


当前回答

在这一点上是不可能的(除非图像的作者显式地包含Dockerfile)。

然而,它绝对是有用的东西!有两件事将有助于获得这个特性。

可信构建(详见docker-dev讨论) 构建过程生成的连续映像中的更详细的元数据。从长远来看,元数据应该指出是哪个构建命令生成了映像,这意味着可以从一系列映像重建Dockerfile。

其他回答

不知何故,我完全错过了公认答案中的实际命令,所以在这里,它在自己的段落中更明显一些,看看有多少人像我一样

$ docker history --no-trunc <IMAGE_ID>

这是源自@fallino的答案,通过使用docker历史的输出格式选项进行了一些调整和简化。因为macOS和Gnu/Linux有不同的命令行实用程序,所以Mac需要不同的版本。如果你只需要其中一个,你可以只使用那些行。

#!/bin/bash
case "$OSTYPE" in
    linux*)
        docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
        tac                                                    | # reverse the file
        sed 's,^\(|3.*\)\?/bin/\(ba\)\?sh -c,RUN,'             | # change /bin/(ba)?sh calls to RUN
        sed 's,^RUN #(nop) *,,'                                | # remove RUN #(nop) calls for ENV,LABEL...
        sed 's,  *&&  *, \\\n \&\& ,g'                           # pretty print multi command lines following Docker best practices
    ;;
    darwin*)
        docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
        tail -r                                                | # reverse the file
        sed -E 's,^(\|3.*)?/bin/(ba)?sh -c,RUN,'               | # change /bin/(ba)?sh calls to RUN
        sed 's,^RUN #(nop) *,,'                                | # remove RUN #(nop) calls for ENV,LABEL...
        sed $'s,  *&&  *, \\\ \\\n \&\& ,g'                      # pretty print multi command lines following Docker best practices
    ;;
    *)
        echo "unknown OSTYPE: $OSTYPE"
    ;;
esac

这只需要两步就可以做到。首先提取映像,然后运行docker history命令。也如SS所示。

docker pull  kalilinux/kali-rolling
docker history --format "{{.CreatedBy}}"   kalilinux/kali-rolling --no-trunc

image2df是什么

image2df是通过图像生成Dockerfile的工具。

这个工具是非常有用的,当你只有docker镜像,需要生成一个Dockerfile。

它是如何工作的

根据图像的历史信息进行反向解析。

如何使用这个图像

# Command alias
echo "alias image2df='docker run -v /var/run/docker.sock:/var/run/docker.sock --rm cucker/image2df'" >> ~/.bashrc
. ~/.bashrc

# Excute command
image2df <IMAGE>

See help docker run --rm cucker/image2df --help For example $ echo "alias image2df='docker run -v /var/run/docker.sock:/var/run/docker.sock --rm cucker/image2df'" >> ~/.bashrc $ . ~/.bashrc $ docker pull mysql $ image2df mysql ========== Dockerfile ========== FROM mysql:latest RUN groupadd -r mysql && useradd -r -g mysql mysql RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/* ENV GOSU_VERSION=1.12 RUN set -eux; \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ apt-get install -y --no-install-recommends ca-certificates wget; \ rm -rf /var/lib/apt/lists/*; \ dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ export GNUPGHOME="$(mktemp -d)"; \ gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ gpgconf --kill all; \ rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ apt-mark auto '.*' > /dev/null; \ [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ chmod +x /usr/local/bin/gosu; \ gosu --version; \ gosu nobody true RUN mkdir /docker-entrypoint-initdb.d RUN apt-get update && apt-get install -y --no-install-recommends \ pwgen \ openssl \ perl \ xz-utils \ && rm -rf /var/lib/apt/lists/* RUN set -ex; \ key='A4A9406876FCBD3C456770C88C718D3B5072E1F5'; \ export GNUPGHOME="$(mktemp -d)"; \ gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg; \ gpgconf --kill all; \ rm -rf "$GNUPGHOME"; \ apt-key list > /dev/null ENV MYSQL_MAJOR=8.0 ENV MYSQL_VERSION=8.0.24-1debian10 RUN echo 'deb http://repo.mysql.com/apt/debian/ buster mysql-8.0' > /etc/apt/sources.list.d/mysql.list RUN { \ echo mysql-community-server mysql-community-server/data-dir select ''; \ echo mysql-community-server mysql-community-server/root-pass password ''; \ echo mysql-community-server mysql-community-server/re-root-pass password ''; \ echo mysql-community-server mysql-community-server/remove-test-db select false; \ } | debconf-set-selections \ && apt-get update \ && apt-get install -y \ mysql-community-client="${MYSQL_VERSION}" \ mysql-community-server-core="${MYSQL_VERSION}" \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \ && chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \ && chmod 1777 /var/run/mysqld /var/lib/mysql VOLUME [/var/lib/mysql] COPY dir:2e040acc386ebd23b8571951a51e6cb93647df091bc26159b8c757ef82b3fcda in /etc/mysql/ COPY file:345a22fe55d3e6783a17075612415413487e7dba27fbf1000a67c7870364b739 in /usr/local/bin/ RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 3306 33060 CMD ["mysqld"] reference

如何从映像生成或反向Dockerfile ?

你可以。主要是。

注意:它不会生成一个Dockerfile,你可以直接使用docker build;输出结果仅供参考。

alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"
dfimage -sV=1.36 nginx:latest

它将自动拉出目标docker映像并导出Dockerfile。参数-sV=1.36并不总是必需的。

参考:https://hub.docker.com/repository/docker/alpine/dfimage

现在,如果您选择一个特定的标记,hub.docker.com将直接使用详细命令显示图像层。

奖金

如果您想知道每一层中哪些文件被更改

alias dive="docker run -ti --rm  -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive"
dive nginx:latest

在左边,您可以看到每个层的命令,在右边(用tab跳转),黄线是该层中一些文件被更改的文件夹

(使用SPACE折叠目录)

旧的答案

下面是旧的答案,它不再工作了。

$ docker pull centurylink/dockerfile-from-image
$ alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm centurylink/dockerfile-from-image"
$ dfimage --help
Usage: dockerfile-from-image.rb [options] <image_id>
    -f, --full-tree                  Generate Dockerfile for all parent layers
    -h, --help                       Show this message