Image 如何从图像生成Dockerfile?

Image 如何从图像生成Dockerfile?,image,repository,docker,Image,Repository,Docker,是否可以从图像生成Dockerfile?我想知道有两个原因: 我可以从存储库下载图像,但想看看生成它们的配方 我喜欢保存快照的想法,但一旦我完成了,最好有一个结构化的格式来检查所做的工作 在这一点上是不可能的(除非图像的作者明确地包含Dockerfile) 然而,它绝对是有用的!有两件事将有助于获得此功能 受信任的构建(详细信息请参见 生成过程生成的后续映像中更详细的元数据。从长远来看,元数据应指示生成映像的生成命令,这意味着可以从一系列映像重建Dockerfile 要了解docker映像是如何

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

  • 我可以从存储库下载图像,但想看看生成它们的配方

  • 我喜欢保存快照的想法,但一旦我完成了,最好有一个结构化的格式来检查所做的工作


  • 在这一点上是不可能的(除非图像的作者明确地包含Dockerfile)

    然而,它绝对是有用的!有两件事将有助于获得此功能

  • 受信任的构建(详细信息请参见
  • 生成过程生成的后续映像中更详细的元数据。从长远来看,元数据应指示生成映像的生成命令,这意味着可以从一系列映像重建Dockerfile

  • 要了解docker映像是如何构建的,请使用
    docker历史记录——无trunc
    命令

    您可以从映像生成docker文件,但它不会包含您想要完全了解映像生成方式的所有内容。合理地说,您可以提取docker文件的MAINTAINER、ENV、EXPOSE、VOLUME、WORKDIR、ENTRYPOINT、CMD和ONBUILD部分

    以下脚本应适用于您:

    #!/bin/bash
    docker history --no-trunc "$1" | \
    sed -n -e 's,.*/bin/sh -c #(nop) \(MAINTAINER .*[^ ]\) *0 B,\1,p' | \
    head -1
    docker inspect --format='{{range $e := .Config.Env}}
    ENV {{$e}}
    {{end}}{{range $e,$v := .Config.ExposedPorts}}
    EXPOSE {{$e}}
    {{end}}{{range $e,$v := .Config.Volumes}}
    VOLUME {{$e}}
    {{end}}{{with .Config.User}}USER {{.}}{{end}}
    {{with .Config.WorkingDir}}WORKDIR {{.}}{{end}}
    {{with .Config.Entrypoint}}ENTRYPOINT {{json .}}{{end}}
    {{with .Config.Cmd}}CMD {{json .}}{{end}}
    {{with .Config.OnBuild}}ONBUILD {{json .}}{{end}}' "$1"
    
    我将此用作脚本的一部分,以将正在运行的容器重建为图像:

    如果希望能够重新打包图像,Dockerfile主要很有用

    需要记住的是,docker映像实际上可以是真实或虚拟机的tar备份。我用这种方式制作了几个docker映像。甚至构建历史记录显示,我导入一个巨大的tar文件作为创建映像的第一步

    如何从图像生成或反转Dockerfile

    你可以

    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
    并不总是必需的

    参考:

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

    奖金 如果您想知道每个层中更改了哪些文件

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

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

    (使用空格折叠目录)

    旧答案 下面是旧的答案,它不再起作用了

    $ 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
    

    $docker从图像中提取centurylink/dockerfile
    
    $alias dfimage=“docker run-v/var/run/docker.sock:/var/run/docker.sock--rm centurylink/dockerfile from image” $dImage--帮助 用法:dockerfile-from-image.rb[选项] -f、 --完整树为所有父层生成Dockerfile -h、 --帮助显示此消息
    我不知何故完全忽略了公认答案中的实际命令,因此,在这里,在它自己的一段中,我再次看到了它,看看有多少人像我一样

    $ docker history --no-trunc <IMAGE_ID>
    
    $docker历史记录--无trunc
    
    bash解决方案:

    docker history --no-trunc $argv  | tac | tr -s ' ' | cut -d " " -f 5- | sed 's,^/bin/sh -c #(nop) ,,g' | sed 's,^/bin/sh -c,RUN,g' | sed 's, && ,\n  & ,g' | sed 's,\s*[0-9]*[\.]*[0-9]*\s*[kMG]*B\s*$,,g' | head -n -1
    
    逐步解释:

    tac : reverse the file
    tr -s ' '                                       trim multiple whitespaces into 1
    cut -d " " -f 5-                                remove the first fields (until X months/years ago)
    sed 's,^/bin/sh -c #(nop) ,,g'                  remove /bin/sh calls for ENV,LABEL...
    sed 's,^/bin/sh -c,RUN,g'                       remove /bin/sh calls for RUN
    sed 's, && ,\n  & ,g'                           pretty print multi command lines following Docker best practices
    sed 's,\s*[0-9]*[\.]*[0-9]*\s*[kMG]*B\s*$,,g'      remove layer size information
    head -n -1                                      remove last line ("SIZE COMMENT" in this case)
    
    例如:

     ~  dih ubuntu:18.04
    ADD file:28c0771e44ff530dba3f237024acc38e8ec9293d60f0e44c8c78536c12f13a0b in /
    RUN set -xe
       &&  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
       &&  echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests
    RUN rm -rf /var/lib/apt/lists/*
    RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list
    RUN mkdir -p /run/systemd
       &&  echo 'docker' > /run/systemd/container
    CMD ["/bin/bash"]
    

    这源于@fallino的答案,通过使用的输出格式选项进行了一些调整和简化。由于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
    

    更新2018年12月宝马的答案

    chenzj/dImage-如hub.docker.com上所述,从其他图像重新生成Dockerfile。因此,您可以按如下方式使用它:

    docker pull chenzj/dfimage
    alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage"
    dfimage IMAGE_ID > Dockerfile
    
    docker pull chenzj/dImage
    别名dfimage=“docker run-v/var/run/docker.sock:/var/run/docker.sock--rm chenzj/dfimage”
    
    dImage\u id
    这是Docker的方法,应该标记为选中的答案。@jenson这不完全相同,可以覆盖95%。但不适用于压扁的图像。@BMW您能帮我解决这个问题吗?运行示例中的图像?/usr/lib/ruby/gems/2.2.0/gems/excon-0.45.4/lib/excon/unix\u socket.rb:14:in'connect\u nonblock':C连接被拒绝-connect(2)for/var/run/docker.sock(Errno::econnreference)(Excon::Errors::SocketError)centurylink/dockerfile from image不适用于新版本的docker。这一个适用于我:imagelayers.io似乎已损坏。它找不到任何图像,包括它的演示图像。这让我明白:json:无法将数组解组为类型的Go值。ContainerJSONC您能更详细地描述您的上一条评论吗?所有内容是否都在/只是按照正常?还是有特殊情况?我想这是一个6yo的答案,但我从daemon那里得到了
    错误响应:找不到页面
    ,那么为什么我们需要
    ub.docker.com/r/chenzj/dfimage
    ?这甚至是一个更新的答案。我猜是因为
    docker history
    以相反的顺序打印Dockerfile行,并删除
    RUN
    指令(您只会得到命令本身,而不是它前面的
    运行
    keyworkd)和其他内容,因此您需要手动编辑它以获得可构建的Dockerfile。其他工具可能会自动为您进行编辑(我没有尝试过,所以我不知道。)@user7610您的命令仅显示从集线器提取的图像的历史记录。我如何在docker图像上看到我的命令?@BarzanHayati您可以将其作为一个新问题提问并链接到此处吗?提问时要非常具体。显示启动图像的命令,然后发出一些您希望稍后看到的命令,例如,然后停止容器(如果你实际上就是这么做的),然后询问如何检索发出的命令。谢谢。@user7610我可以问,但只要我问了,我就必须删除它,因为其他用户对重复的问题会给我加减分。最简单的解决方案。谢谢!这不会在分解多行运行语句时添加反斜杠。我已经在inspi中添加了我自己的答案mac上不提供this.tac的red,因此您可以选择下面的awk:| awk