Dedockify 是一个用于逆向Docker 镜像并生成相应 Dockerfile 的工具。
它的主要功能是通过解析 Docker 镜像的metadata(也就是history),重建出用于生成该镜像的 Dockerfile。

开源仓库地址: https://github.com/mrhavens/Dedockify

主要功能

  1. 逆向工程 Docker 镜像:Dedockify 能够从 Docker 镜像中提取信息,并生成一个近似的 Dockerfile。这对于需要了解镜像构建过程或修改镜像的用户非常有用。
  2. 使用 Docker API:Dedockify 利用 Python Docker API 与 Docker 交互,获取镜像的各层信息,并将这些信息重新格式化为 Dockerfile。
  3. 支持本地镜像:该工具只能对本地存在的 Docker 镜像进行操作。如果镜像不在本地仓库中,需要先使用 docker pull 命令将其拉取下来。

使用方法

基本用法

  1. 拉取 Dedockify 镜像

    docker pull mrhavens/dedockify
    
  2. 创建别名

    alias dedockify="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm mrhavens/dedockify"
    
  3. 生成 Dockerfile

    dedockify <imageID>
    

    其中 <imageID> 是目标 Docker 镜像的 ID,可以是截断形式或完整形式。

⚠️注意:。下面笔者给出一个fix:

首先需要安装最新的docker python sdk:

pip install docker

然后修改dedockify.py为如下:

#!/usr/bin/python3

from sys import argv
import docker
import docker.errors

class ImageNotFound(Exception):
    pass


class MainObj:
    def __init__(self):
        super(MainObj, self).__init__()
        self.commands = []
        self.cli = docker.client.from_env()
        self._get_image(argv[-1])
        self.hist = self.img.history()
        self._parse_history()
        self.commands.reverse()
        self._print_commands()

    def _print_commands(self):
        for i in self.commands:
            print(i)

    def _get_image(self, img_hash):
        try:
            img = self.cli.images.get(img_hash)
            self.img = img
        except docker.errors.ImageNotFound:
            raise ImageNotFound("Image {} not found".format(img_hash))
        

    def _insert_step(self, step):
        if "#(nop)" in step:
            to_add = step.split("#(nop) ")[1]
        else:
            to_add = ("RUN {}".format(step))
        to_add = to_add.replace("&&", "\\\n    &&")
        self.commands.append(to_add.strip(' '))

    def _parse_history(self, rec=False):
        first_tag = False
        actual_tag = False
        for i in self.hist:
            if i['Tags']:
                actual_tag = i['Tags'][0]
                if first_tag and not rec:
                    break
                first_tag = True
            self._insert_step(i['CreatedBy'])
        if not rec:
            self.commands.append("FROM {}".format(actual_tag))


__main__ = MainObj()

如果docker build过程中遇到速度很慢的问题,可以通过修改apk源和pip源解决,下面是一个修改后的例子:

FROM alpine:3.11.3


RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories

RUN apk --no-cache update && apk add --no-cache python3 wget \
    && wget -q --no-check-certificate https://bootstrap.pypa.io/get-pip.py \
    && apk del wget && python3 get-pip.py && rm -f get-pip.py \
    && pip install -U docker pip -i https://pypi.tuna.tsinghua.edu.cn/simple && yes | pip uninstall pip

RUN mkdir /app
COPY entrypoint.sh /.
COPY dedockify.py /app/.

ENTRYPOINT ["/entrypoint.sh"]

修改后的完整代码可以从笔者的fork中获取:https://github.com/merthmagic/Dedockify

示例

以下是一个使用 Dedockify 生成 Dockerfile 的示例:

## ⚠️ 如果不能工作,请用上面的更新后代码自行打包docker image
$ docker pull mrhavens/dedockify
$ alias dedockify="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm mrhavens/dedockify"
$ dedockify <imageID>

生成的 Dockerfile 可能如下所示:

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

限制

Dedockify 目前有一些限制,例如它无法处理所有类型的指令,特别是涉及复杂文件操作的指令。此外,未来的改进方向包括自动恢复容器中的文件并将其存储到本地,以及更好地推断基础镜像等。

但总的来说,Dedockify 是一个强大的工具,通过Dedockify再配合一些后续处理,能够帮助开发者和运维人员更好地理解和管理 Docker 镜像。

05-31 15:37