我无法找到.dockerignore文件应该是什么样子的许多示例。
使用puppet在docker容器上安装一些软件包会导致映像从600MB扩展到3GB。我尝试使用.dockerignore
文件将大小保持为最小值
$ cat Dockerfile
FROM centos:centos6
#Work around selinux problem on cent images
RUN yum install -y --enablerepo=centosplus libselinux-devel
RUN yum install -y wget git tar openssh-server; yum -y clean all
Add Puppetfile /
RUN librarian-puppet install
RUN puppet apply --modulepath=/modules -e "class { 'buildslave': jenkins_slave => true,}"
RUN librarian-puppet clean
如果我运行docker images --tree
我可以看到图像瞬间增长几GB
$ docker images --tree
├─e289570b5555 Virtual Size: 387.7 MB
│ └─a7646acf90d0 Virtual Size: 442.5 MB
│ └─d7bc6e1fbe43 Virtual Size: 442.5 MB
│ └─772e6b204e3b Virtual Size: 627.5 MB
│ └─599a7b5226f4 Virtual Size: 627.5 MB
│ └─9fbffccda8bd Virtual Size: 2.943 GB
│ └─ee46af013f6b Virtual Size: 2.943 GB
│ └─3e4fe065fd07 Virtual Size: 2.943 GB
│ └─de9ec3eba39e Virtual Size: 2.943 GB
│ └─31cba2716a12 Virtual Size: 2.943 GB
│ └─52cbc742d3c4 Virtual Size: 2.943 GB
│ └─9a857380258c Virtual Size: 2.943 GB
│ └─c6d87a343807 Virtual Size: 2.964 GB
│ └─f664124e0080 Virtual Size: 2.964 GB
│ └─e6cc212038b9 Virtual Size: 2.964 GB Tags: foo/jenkins-centos6-buildslave:latest
我认为图像变得如此之大的原因是因为librarian-puppet
将一个木偶模块克隆到/modules
,这会破坏构建缓存
我已经尝试了以下.dockerignore
文件而没有运气。
$ cat .dockerignore
/modules
/modules/
/modules/*
这是.dockerignore
文件的正确语法吗?
有没有其他方法可以防止这些容器变得如此之大?
其他信息:
http://kartar.net/2013/12/building-puppet-apps-inside-docker/
http://danielmartins.ninja/posts/a-week-of-docker.html
答案 0 :(得分:28)
.dockerignore
是为了防止在执行docker build
时将文件添加到发送到docker守护程序的初始构建上下文中,它不会创建排除文件的全局规则在Dockerfile生成的所有图像中。
重要的是要注意每个RUN
语句将生成一个新图像,该图像的父图像是由其上方的Dockerfile语句生成的图像。尝试将RUN
语句折叠为单个语句以缩小图像大小:
RUN librarian-puppet install &&\
puppet apply --modulepath=/modules -e "class { 'buildslave': jenkins_slave => true,}" &&\
librarian-puppet clean
答案 1 :(得分:19)
.dockerignore
的格式应该等于.gitignore
的格式。查看sample file和泊坞窗documentation。
该文件应该是由换行符分隔的排除模式列表(相对于.dockerignore
文件的路径)。
所以你应该尝试以下.dockerignore
:
modules/*
开头的/
可能是错误的,因为它只对文件的根目录有效(但不适用于子目录,所以可能没有/
的递归版本做得更好)。
答案 2 :(得分:8)
既不:
@ECHO Off
SETLOCAL enabledelayedexpansion
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\????-*-????-??-*.txt" '
) DO (
SET "filename=%%a"
CALL :newname !filename:-= !
IF DEFINED newdir (
ECHO MD "!newdir!" 2>NUL
ECHO MOVE "%sourcedir%\%%a" "%destdir%\!newdir!\"
)
)
GOTO :EOF
:newname
IF "%5" neq "" shift&GOTO newname
SET "newdir=%1-%2"
IF "%newdir:~4,1%" equ "-" IF "%newdir:~7%" equ "" IF "%newdir:~6,1%" neq "" GOTO :EOF
SET "newdir="
GOTO :eof
,也不
modules/*
对我不起作用,docker一直用不必要的文件污染图像,直到我这样设置:
modules
也适用于:
**/modules
答案 3 :(得分:3)
一种不同的方式,创建一个较小的图像,是run librarian-puppet in the host,而不是Docker,所以你不要以图书馆员,红宝石,宝石,...安装在图像中。
我以jenkins slave using Puppet的622MB图片和image without Puppet的480MB图片结束。
答案 4 :(得分:2)
http://docs.docker.com/articles/dockerfile_best-practices/
在我看来,你的方法是倒退的(同意@csanchez),你应该从木偶生成你的docker容器,而不是在容器中运行puppet ......
此外,您应该&&
安装/应用/清除线路...每个docker命令创建一个增量映像...如果有临时/资源文件属于centos {{1} }命令,你也应该这样做。
yum
我真的建议在容器中避免使用SELINUX,它不会在容器内提供任何。更不用说,根据你想要创造的东西,比起centos6有更小的起点。我相信ubuntu较小,debian:喘不过小,甚至是高山的小起点。
值得注意的是,如果您使用支持虚拟挂载的文件系统,您的文件大小可以为多个实例重复使用相同的基本映像,因此它不会增长更多
答案 5 :(得分:1)
.dockerignore
文件类似于.gitignore
语法。以下是一些示例规则:
# Ignore a file or directory in the context root named "modules"
modules
# Ignore any files or directories within the subdirectory named "modules"
# in the context root
modules/*
# Ignore any files or directories in the context root beginning with "modules"
modules*
# Ignore any files or directories one level down from the context root named
# "modules"
*/modules
# Ignore any files or directories at any level, including the context root,
# named modules
**/modules
# Ignore every file in the entire build context (see next rule for how this
# could be used)
*
# Re-include the file or directory named "src" that may have been previously
# excluded. Note that you cannot re-include files in subdirectories that have
# been previously excluded at a higher level
!src
请注意,“构建上下文”是您在构建命令末尾传递的目录,通常为.
,以指示当前目录。该目录从Docker客户端打包,不包括您用.dockerignore
忽略的所有文件,并发送到docker守护程序执行构建。即使守护程序与客户端位于同一主机上,构建也只能在此上下文中工作,而不能直接在文件夹中工作。
只有一个.dockerignore
用于构建,它必须在构建上下文的根目录中。如果它位于您的主目录中(假设您是从子目录构建的),它将不起作用,并且它也不会从构建上下文的子目录运行。
要测试当前构建上下文中的内容并验证.dockerignore
文件的行为,可以复制/粘贴以下内容(假设您没有名为test-context
的图像,它将被覆盖,然后删除):
# create an image that includes the entire build context
docker build -t test-context -f - . <<EOF
FROM busybox
COPY . /context
WORKDIR /context
CMD find .
EOF
# run the image which executes the find command
docker container run --rm test-context
# cleanup the built image
docker image rm test-context
答案 6 :(得分:0)
优化容器图片大小是 .dockerignore 背后的主要目标,因为它的目的与 .gitignore 相似,因为它可以减少延迟和响应时间,同时提供服务。对于Puppet,SaltStack或Ansible等部署自动化来说确实如此。由于较大的映像大小和较低的网络带宽,为服务执行部署定义的时间戳可能会失败。因此.dockerignore有助于使图像的大小尽可能小。
您可以将它放入我们在docker build命令末尾指定的构建上下文目录。该文件遵循文件和目录的glob模式,以从最终构建映像中排除这些模式。
假设我有一个目录。 img / 进入我的构建环境,我想在构建图像时将其排除,我只需将以下行添加到.dockerignore文件中,
.img
并且,如果我想要排除所有文件开头。然后简单地添加一行,
.*
(注意:不要混淆Unix glob模式与正则表达式不同)
此外,我还会从构建环境中排除更多我的文件,
.*
docs
my-stack.dab
docker-compose.overrride.yml
test*
*.md
!README.md
此处, *。md 行排除所有降价文件(我的项目中有很多降价文件)。但是,我想要包含 README.md 而不包含其他降价文件。作为上面的最后一行,我们在!中添加了README.md,或者在排除所有其他markdown文件时将其排除。
因此,借助 .dockerignore ,我们可以减少构建图像的开销,并利用它来缩小图像尺寸。
答案 7 :(得分:0)
我认为,针对您的用例的最佳解决方案是在docker文件中使用Multi-stage build。您的Dockerfile必须位于一个空目录中,并且您在一次性容器中运行puppet。
从上面的链接:
对于多阶段构建,您可以在自己的数据库中使用多个FROM语句 Dockerfile。每个FROM指令可以使用不同的基数,并且每个 他们中的一个开始了构建的新阶段。您可以有选择地复制 从一个阶段到另一个阶段的文物,留下了一切 不需要最后一张图片。