是否可以从镜像生成Dockerfile?有两个原因想知道:
我可以从仓库下载镜像,但想看到生成它们的配方。
我喜欢保存快照的想法,但一旦完成,有一个结构化的格式来审查所做的事情会很不错。
是否可以从镜像生成Dockerfile?有两个原因想知道:
我可以从仓库下载镜像,但想看到生成它们的配方。
我喜欢保存快照的想法,但一旦完成,有一个结构化的格式来审查所做的事情会很不错。
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"
dfimage -sV=1.36 nginx:latest
-sV=1.36
不总是必需的。如果你想知道每个层次中有哪些文件被更改了
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 镜像是如何构建的,可以使用 docker history --no-trunc
命令。
你可以从一个镜像文件构建一个 Docker 文件,但它并不包含您完全了解图像生成方式所需的全部内容。您可以提取的是 Dockerfile 的 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"
我将其用作重建运行容器为镜像的脚本的一部分: https://github.com/docbill/docker-scripts/blob/master/docker-rebase
Dockerfile主要有用的是,如果您想重新打包一个镜像。
需要记住的是,Docker镜像实际上可以只是真实或虚拟机器的tar备份。我已经用这种方式制作了几个Docker镜像。即使构建历史记录显示我导入一个巨大的tar文件作为创建镜像的第一步...
我有些绝对错过了被接受答案中的实际命令,因此在此再次列出它,更加突出地显示在自己的段落中,看看像我这样的人有多少
$ docker history --no-trunc <IMAGE_ID>
ub.docker.com/r/chenzj/dfimage
?这甚至是一个更近期的答案。 - lucid_dreamerdocker history
命令以相反的顺序打印 Dockerfile 的行,并且会删除 RUN
指令(你只能得到命令本身,没有前面的 RUN
关键字)和其他东西,所以你需要手动编辑才能得到可构建的 Dockerfile。那个其他工具可能可以自动为您完成此编辑(我没有尝试过,所以不确定)。 - user7610docker 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"]
tac() { awk '{ l[NR]=$0} END {for(i=NR;i>0;--i)print l[i];}' "$@";}
。与phulei的解决方案相比,这种方法更加节约内存并且总的CPU时间稍微少一些。 - Otheushead -n -1
替换为 sed '$p'
。 - Otheus更新2018年12月至宝马的回答
chenzj / dfimage-如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: 守护进程的错误响应: OCI运行时创建失败:container_linux.go:349: 启动容器进程导致 "exec: \"cc6cb8df58e2\": 可执行文件在 $PATH 中未找到": 未知。
- Trevor Hickeychenzj/dfimage
重命名为你要求的 Docker 镜像? - 404pio如果你对Docker hub注册表中的某个镜像感兴趣,并想要查看其Dockerfile,可以按以下步骤操作:
例如:
如果你希望查看名为"jupyter/datascience-notebook"的镜像的Dockerfile,直接在浏览器地址栏中输入单词“Dockerfile”即可,如下所示。
https://hub.docker.com/r/jupyter/datascience-notebook/
https://hub.docker.com/r/jupyter/datascience-notebook/Dockerfile
注意: 并不是所有的镜像都有Dockerfile,例如https://hub.docker.com/r/redislabs/redisinsight/Dockerfile。 有时,这种方法比在Github中搜索Dockerfile更快捷。
#!/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 pull chenzj/dfimage
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage"
dfimage image_id
dfimage
命令的输出结果:$ dfimage 0f1947a021ce
FROM node:8
WORKDIR /usr/src/app
COPY file:e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c in ./
RUN /bin/sh -c npm install
COPY dir:a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a in .
EXPOSE 8080
CMD ["npm" "start"]
目前尚不可能(除非图片的作者明确包含了 Dockerfile 文件)。
然而,这肯定是有用的!有两件事将有助于获得此功能。