通常而言,镜像的构成包括两部分,一是基础镜像,一是在基础镜像之上进行的各种文件和指令操作。如果想要制作出满足最佳实践的应用镜像,应选取精简的没有安全漏洞(或者尽可能少漏洞)的基础镜像,也要保证Dockerfile的内容遵守制定好的编写规范。
在有了模板文件编写规范后,应通过管理手段和技术手段来确保规范的落实。其中技术手段包括但不限于利用DevOps研发平台内嵌规范,通过自动化来减少开发人员的工作量,减少推行规范过程中遇到的摩擦。也可以通过质量门禁来限制未遵守规范的镜像流转到后续环节。
附一个机翻的dockerfile文件检查规范,仅供参考。各企业应基于自身实践建立对应规范。
检查项 | 严重级别 | 描述 |
---|---|---|
WORKDIR 没有使用绝对路径 | Error | 通过使用绝对路径,当前一个WORKDIR指令改变时,你不会遇到问题。您通常也不知道容器的WORKDIR上下文。 |
在容器中使用没有意义的指令 | Info | 对于一些POSIX命令,在Docker容器中运行它们是没有意义的,因为它们被绑定到主机上,或者是其他危险的(如´shutdown´,´service´,´ps´,´free´,´top´,´kill´,´mount´,´ifconfig´)。交互式工具也没有多大意义(´nano´,´vim´)"。 |
以root用户结束 | Warning | 如果攻击者可以访问容器,切换到根用户会带来一定的安全风险。为了减轻这种情况,在以root用户身份运行所需命令后,切换回非特权用户。 |
使用cd切换到一个目录 | Warning | 应该使用WORKDIR切换到一个目录。只在子shell中使用cd。大多数命令可以使用绝对路径,在大多数情况下不需要更改目录。如果你真的需要改变当前的工作目录,Docker提供了WORKDIR指令。 |
使用sudo | Error | 不要使用sudo,因为它会导致不可预测的行为。使用gosu之类的工具来强制执行根目录。 |
使用了'apt-get'或者'dist-upgrade'进行升级 | Error | 您应该避免运行apt-get升级或运行apt-get发行版升级,因为来自基本映像的许多“基本”包不会在非特权容器中升级。如果基本映像中包含的包过时了,您应该联系它的维护者。参考:https://docs.docker.com/engine/articles/dockerfile_best-practices/" |
FROM基础镜像未指定版本 | Warning | FROM基础镜像需要指定版本。建议总是使用一个指定版本的镜像,例如ubuntu:12.04。这样你就能准确地知道使用的是哪个镜像。 |
基础镜像使用latest版本镜像 | Warning | 不要使用latest版本镜像。使用latest很容易出现错误,如果镜像一直在更新。建议总是使用一个指定版本的镜像。 |
安装package时未指定版本 | Warning | 安装package时应该指定版本,应该使用apt-get install =,版本固定会强制构建检索特定的版本,而不管缓存中有什么。这样可以减少由于所需包中未预料到的更改而导致的失败。" |
在安装完成后未删除apt-get列表 | Info | 在安装完成后应该删除apt-get列表,清理apt缓存并删除/var/lib/apt/lists有助于降低图像大小。 |
使用ADD 将本地文件基本复制到容器中 | Info | 虽然ADD和COPY在功能上相似,但一般来说,COPY是首选。这是因为它比ADD更透明。COPY只支持将本地文件基本复制到容器中,而ADD有一些不那么明显的特性(如仅本地tar提取和远程URL支持)。因此,ADD的最佳用法是将本地tar文件自动提取到图像中,如ADD rootfs.tar.xz /。参考: https://docs.docker.com/engine/articles/dockerfile_best-practices/" |
超出端口范围0~65535. | Error | 参考: https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers" |
安装package未使用'-y'参数" | Warning | 应该使用'-y'开关来避免手动输入,例:'apt-get -y install '。如果没有'--assume-yes'选项,构建可能会在没有人为干预的情况下中断。 |
未使用--no-install-recommends来避免额外的包 | Info | 避免安装您并不明确想要的附加包。 |
nmp指定未版本 | Warning | 应该使用npm install @.版本固定会强制构建检索特定的版本,而不管缓存中有什么。这种技术还可以减少由于所需包中未预料到的更改而导致的失败。" |
使用apk upgrade | Error | 您应该避免运行apk upgrade,因为来自父映像的许多“essential”包不会在非特权容器中升级。如果父映像中包含的包过时了,您应该联系它的维护者。如果你知道有一个特定的包foo需要更新,使用’apk --no-cache add foo‘自动更新。 |
apk add 未指定版本 | Warning | 版本固定强制构建检索有限范围的版本,或者确切的特定版本,而不管缓存中有什么。这种技术还可以减少由于所需包中未预料到的更改而导致的失败。 |
apk未使用--no-cache | Info | 在Alpine Linux 3.3中,apk有一个新的——no-cache选项。它允许用户安装带有索引的包,该索引会实时更新和使用,而不会缓存到本地:这避免了在安装包时使用——update和删除/var/cache/apk/*。 |
COPY 超过2个参数最后一个参数没有以/结尾. | Error | 如果指定了多个资源(直接或使用通配符),则必须是一个目录,并且必须以斜杠/结束. 参考: https://docs.docker.com/engine/reference/builder/#copy" |
COPY --from 应该引用先前定义的FROM别名 | Warning | 试图从缺失的图像别名进行复制会导致错误。 |
COPY --from 不能引用自己的FROM别名. | Error | 试图从正在运行的指令所在的映像中进行复制会导致错误。 |
FROM 定义重复的别名 | Error | 定义重复的别名会导致错误 |
对CMD和ENTRYPOINT参数使用JSON表示法 | Warning | CMD几乎总是以[" executable ", " param1 ", " param2 "…]的形式使用。 |
MAINTAINER 已被弃用 | Error | MAINTAINER自Docker 1.13.0 起已弃用. |
可以使用Wget或Curl,但不能同时使用。 | Warning | 不要安装两个具有相同效果的工具,避免额外的混乱。 |
找到多个ENTRYPOINT指令 | Error | 如果列出了多个ENTRYPOINT,那么只有最后一个ENTRYPOINT会生效。 |
使用SHELL修改默认的SHELL. | Warning | Docker提供了一个SHELL指令,它不需要覆盖容器中的/bin/sh |
在运行一个管道之前,设置SHELL选项-o pipefail | Warning | 一些运行命令依赖于使用管道字符将一个命令的输出管道到另一个命令的能力,如下面的示例所示:RUN wget -o - https://some.site 管道 wc -l > /number"。 |
镜像制作类似于虚拟机的镜像(模版)制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大的简化相同环境的部署工作。
收起