详解如何基于Docker镜像逆向生成Dockerfile

 更新时间:2024年03月08日 09:02:11   作者:云原生运维圈  
这篇博客文章我们将通过使用一些开源工具,带领您逐步解读 Docker 镜像并转换为 Dockerfile 的过程,感兴趣的小伙伴可以跟随小编一起学习一下

引言

你是否曾经遇到过一个想要使用的 Docker 镜像,但却无法修改以适应你的特定需求?或者你可能发现了一个喜欢的 Docker 镜像,但想要了解它是如何构建的?在这两种情况下,将 Docker 镜像逆向生成一个 Dockerfile 可以使用一些工具来实现。

将 Docker 镜像转换为 Dockerfile 意味着获取现有的 Docker 镜像,并使用它来创建一个你可以修改和控制的 Dockerfile。

这个过程让你能够理解 Docker 镜像的内部运作方式,进行修改,更新镜像以在不同平台上运行,或者根据特定需求对其进行优化。

在这篇博客文章中,我们将通过使用一些开源工具,带领您逐步解读 Docker 镜像并转换为 Dockerfile 的过程。

使用Dedockify工具实现

Docker 镜像就像黑匣子,包含了在镜像构建过程中执行的一系列指令层。

现在有了 Dedockify,一个使用 Python 脚本的工具,可以帮助重建创建镜像所使用的 Dockerfile 的近似版本。

Dedockify 的工作原理是利用存储在每个镜像层旁边的元数据。它通过沿着层级树向后遍历,收集与每个层相关联的命令。

这个过程使它能够重建在镜像构建过程中执行的命令序列。

然而,有一个问题:如果使用了 COPY 或 ADD 指令,Dedockify 生成的输出不会完全匹配原始的 Dockerfile。这是因为 Dedockify 无法访问在执行原始的 docker build 命令时存在的构建上下文。

要使用 Dedockify,可以将其作为一个 Docker 容器运行:

docker run -v /var/run/docker.sock:/var/run/docker.sock dedockify <imageID>

参数 <imageID> 是镜像 ID(可以是缩短形式或完整的镜像 ID)。

该脚本通过与 Docker API 交互来查询各个镜像层的元数据,因此需要访问 Docker API 套接字。上面显示的 -v 标志使得在运行脚本的容器内部可以使用 Docker 套接字。

工作原理是什么?

当从 Dockerfile 构建镜像时,Dockerfile 中的每个指令都会生成一个新的层。您可以使用 docker images 命令和(现在已弃用的)--tree 标志来查看所有的镜像层。

$ docker images --tree
Warning: '--tree' is deprecated, it will be removed soon. See usage.
└─511136ea3c5a Virtual Size: 0 B Tags: scratch:latest
  └─1e8abad02296 Virtual Size: 121.8 MB
    └─f106b5d7508a Virtual Size: 121.8 MB
      └─0ae4b97648db Virtual Size: 690.2 MB
        └─a2df34bb17f4 Virtual Size: 808.3 MB Tags: buildpack-deps:latest
          └─86258af941f7 Virtual Size: 808.6 MB
            └─1dc22fbdefef Virtual Size: 846.7 MB
              └─00227c86ea87 Virtual Size: 863.7 MB
                └─564e6df9f1e2 Virtual Size: 1.009 GB
                  └─55a2d383d743 Virtual Size: 1.009 GB
                    └─367e535883e4 Virtual Size: 1.154 GB
                      └─a47bb557ed2a Virtual Size: 1.154 GB
                        └─0d4496202bc0 Virtual Size: 1.157 GB
                          └─5db44b586412 Virtual Size: 1.446 GB
                            └─bef6f00c8d6d Virtual Size: 1.451 GB
                              └─5f9bee597a47 Virtual Size: 1.451 GB
                                └─bb98b84e0658 Virtual Size: 1.452 GB
                                  └─6556c531b6c1 Virtual Size: 1.552 GB
                                    └─569e14fd7575 Virtual Size: 1.552 GB
                                      └─fc3a205ba3de Virtual Size: 1.555 GB
                                        └─5fd3b530d269 Virtual Size: 1.555 GB
                                          └─6bdb3289ca8b Virtual Size: 1.555 GB
                                            └─011aa33ba92b Virtual Size: 1.555 GB Tags: ruby:2, ruby:2.1, ruby:2.1.1, ruby:latest

这些层中的每一个都是在 Dockerfile 中执行指令的结果。事实上,如果您对这些层中的任何一个执行 docker inspect,您可以看到用于生成该层的指令。

$ docker inspect 011aa33ba92b
[{
  . . .
  "ContainerConfig": {
    "Cmd": [
        "/bin/sh",
        "-c",
        "#(nop) ONBUILD RUN [ ! -e Gemfile ] || bundle install --system"
    ],
    . . .
}]

Docker 示例:

以下是一个示例,展示了如何拉取官方的 Docker Ruby 镜像并生成该镜像的 Dockerfile。

$ docker pull mrhavens/dedockify
Using default tag: latest
latest: Pulling from dedockify

$ alias dedockify="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm mrhavens/dedockify"

$ dedockify <imageID>
FROM buildpack-deps:latest
RUN useradd -g users user
RUN apt-get update && apt-get install -y bison procps
RUN apt-get update && apt-get install -y ruby
ADD dir:03090a5fdc5feb8b4f1d6a69214c37b5f6d653f5185cddb6bf7fd71e6ded561c in /usr/src/ruby
WORKDIR /usr/src/ruby
RUN chown -R user:users .
USER user
RUN autoconf && ./configure --disable-install-doc
RUN make -j"$(nproc)"
RUN make check
USER root
RUN apt-get purge -y ruby
RUN make install
RUN echo 'gem: --no-rdoc --no-ri' >> /.gemrc
RUN gem install bundler
ONBUILD ADD . /usr/src/app
ONBUILD WORKDIR /usr/src/app
ONBUILD RUN [ ! -e Gemfile ] || bundle install --system

使用Dive工具实现

Dive 是一个用于探索 Docker 镜像、层内容,并发现缩小 Docker/OCI 镜像大小的方法的工具。

Dive 是一个用于探索 Docker 镜像、层内容,并发现可以减小镜像大小的方法的工具。它提供了对每个层内容的详细分解,包括文件大小、权限等。特别适用于识别可以删除以减小镜像大小的不必要文件或依赖项。

特点:

  • 详细的层内容分解:Dive 提供了对 Docker 或 OCI 镜像中每个层内容的详细分解。它显示每个文件的大小、权限和其他元数据。
  • 色彩编码界面:Dive 使用色彩编码界面突出显示不同类型的文件。这使得识别并删除不必要的文件或依赖项变得容易。
  • 交互式探索:Dive 允许您交互式地探索每个层的内容。您可以浏览各个层、查看单个文件,并进行更改以优化您的镜像。
  • 优化建议:Dive 提供了优化镜像的建议。它识别大文件、不必要的依赖项和其他潜在的优化方案。

使用方法:

要使用 Dive,您需要在系统上安装它,并针对一个 Docker 或 OCI 镜像运行它:

dive <imageID>

例如,要分析官方的 Alpine Linux 镜像,您可以运行:

dive alpine:latest

然后 Dive 将显示镜像层的详细分解,让您可以探索每个层的内容并识别潜在的优化。

除了像 Dive 这样的第三方工具外,我们可以立即使用的工具是 docker history。如果我们在示例1镜像上使用 docker history 命令,我们可以查看在 Dockerfile 中用来创建该镜像的条目。

docker history nginx

因此,我们应该得到以下结果:

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
374e0127c1bc        25 minutes ago      /bin/sh -c #(nop) COPY file:aa717ff85b39d3ed…   0B
84acff3a5554        25 minutes ago      /bin/sh -c #(nop) COPY file:2a949ad55eee33f6…   0B
a9cc49948e40        25 minutes ago      /bin/sh -c #(nop) COPY file:e3c862873fa89cbf…   0B

请注意,CREATED BY 列中的所有内容都被截断了。这些是通过 Bourne shell 传递的 Dockerfile 指令。这些信息可能对重新创建我们的 Dockerfile 有用,尽管在这里被截断了,但我们也可以通过使用 --no-trunc 选项来查看所有内容:

$ docker history example1 --no-trunc
IMAGE                                                                     CREATED             CREATED BY                                                                                           SIZE                COMMENT
sha256:374e0127c1bc51bca9330c01a9956be163850162f3c9f3be0340bb142bc57d81   29 minutes ago      /bin/sh -c #(nop) COPY file:aa717ff85b39d3ed034eed42bc1186230cfca081010d9dde956468decdf8bf20 in /    0B
sha256:84acff3a5554aea9a3a98549286347dd466d46db6aa7c2e13bb77f0012490cef   29 minutes ago      /bin/sh -c #(nop) COPY file:2a949ad55eee33f6191c82c4554fe83e069d84e9d9d8802f5584c34e79e5622c in /    0B
sha256:a9cc49948e40d15166b06dab42ea0e388f9905dfdddee7092f9f291d481467fc   29 minutes ago      /bin/sh -c #(nop) COPY file:e3c862873fa89cbf2870e2afb7f411d5367d37a4aea01f2620f7314d3370edcc in /    0B

虽然这里包含一些有用的数据,但从命令行解析可能会有些挑战。我们也可以使用 docker inspect。

Dockerfile From Image (dfimage)

类似于 docker history 命令的工作方式,Python 脚本可以使用 Docker 存储在每个镜像层旁边的元数据重新创建(近似地)用于生成镜像的 Dockerfile。

https://github.com/LanikSJ/dfimage

Python 脚本本身被打包为一个 Docker 镜像,这样就可以很容易地使用 Docker run 命令来执行:

docker run -v /var/run/docker.sock:/var/run/docker.sock dfimage ruby:latest

ruby:latest 参数是镜像名称和标签(可以是缩写形式或完整的镜像名称和标签)。

由于该脚本与 Docker API 交互以查询各种镜像层的元数据,因此它需要访问 Docker API 套接字。上面显示的 -v 标志使得 Docker 套接字在运行脚本的容器内可用。

请注意,该脚本仅适用于存在于您本地镜像仓库中的镜像(即您在键入 docker images 时看到的内容)。如果要为本地仓库中不存在的镜像生成 Dockerfile,则首先需要使用 docker pull 命令拉取该镜像。

总结

将 Docker 镜像逆向工程为 Dockerfile,或者称为“回溯 Docker 镜像”,是一种有用的技术,可以帮助理解和重新创建镜像的构建过程。工具如 Dive 和 Dedockify 可以通过分析镜像层和元数据来生成相应的 Dockerfile,从而提供帮助。

以上就是详解如何基于Docker镜像逆向生成Dockerfile的详细内容,更多关于Docker镜像逆向生成Dockerfile的资料请关注脚本之家其它相关文章!

相关文章

  • 使用docker部署django的详细步骤

    使用docker部署django的详细步骤

    当用Django框架开发的网站项目完成后上线的话可以用物理主机、虚拟机来部署,也可以容器,下面这篇文章主要给大家介绍了关于使用docker部署django的详细步骤,需要的朋友可以参考下
    2022-08-08
  • Docker配置本地仓库web访问的实现

    Docker配置本地仓库web访问的实现

    本文主要介绍了Docker配置本地仓库web访问的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Docker本地目录挂载的实现步骤

    Docker本地目录挂载的实现步骤

    本文主要介绍了Docker本地目录挂载的实现步骤
    2024-02-02
  • 基于Docker部署GitLab环境搭建的方法步骤

    基于Docker部署GitLab环境搭建的方法步骤

    这篇文章主要介绍了基于Docker部署GitLab环境搭建的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • 详解Docker学习笔记之搭建一个JAVA Tomcat运行环境

    详解Docker学习笔记之搭建一个JAVA Tomcat运行环境

    本篇文章主要介绍了详解Docker学习笔记之搭建一个JAVA Tomcat运行环境,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 分享8个基本的Docker容器管理命令

    分享8个基本的Docker容器管理命令

    本文给大家分享8个基本的Docker容器管理命令,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-06-06
  • Docker守护进程安全配置项目详解

    Docker守护进程安全配置项目详解

    这篇文章主要介绍了Docker守护进程安全配置介绍,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 详解docker镜像centos7配置Java运行环境

    详解docker镜像centos7配置Java运行环境

    基于docker官网centos7镜像配置java运行环境,自己安装jdk和tomcat,解决docker容器与宿主机时间不一致问题
    2017-05-05
  • docker安装tomcat8的实现方法

    docker安装tomcat8的实现方法

    这篇文章主要介绍了docker安装tomcat8的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 解决docker run后容器出现Exited (0)情况的问题

    解决docker run后容器出现Exited (0)情况的问题

    这篇文章主要介绍了解决docker run后容器出现Exited (0)情况的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03

最新评论