资讯专栏INFORMATION COLUMN

怎样构建一个好的 Docker 镜像

kk_miles / 2872人阅读

摘要:在第三种情况下,我建议在另外一个镜像安装构建工具,基于最小的镜像。做这个的一个简单方式是指定包的版本,当通过包管理器更新的时候。这里有一个怎样做的示例我们所能希望的是,但是这是没有保障的,包仓库从现在开始的一年仍然会是这个版本。

  

本文的原文地址是 What constitutes a good docker image?

  

注:本文不会全部翻译,只会挑选个人认为有价值的部分进行摘取性翻译,如想详细阅读,请看原文

构建一个好的 Docker 镜像 debian 的基础镜像

在撰写本文时,ubuntu:14.04 为 195 MB,然而 debian:wheezy 是 85 MB,但是 Ubuntu 额外的几百兆字节不会给你带来任何价值(我所知道的)。在一些极端情况下,甚至可能你的基础镜像是 2 MB busybox。这可能仅仅实际上是二进制包的静态连接。

没有充足的原因,不要安装构建工具

构建工具占用太多空间,并且从源码构建通常很慢。如果你只是安装别人的软件,通常不需要从源码构建,并且它应该被避免。比如,没有必要安装 python,gcc 等等。为了获取最新版本的 node.js 并运行在一台 Debian 主机上。在 node.js downloads page 这里有一个可用的二进制的压缩包。类似的,redis 可以通过包管理器安装。

至少有几个很好的理由使用构建工具:

你需要一个指定的版本(比如,在 Debian 仓库,redis 版本太老)

你需要使用指定的选项编译

你需要 npm install 安装一些模块来编译进二进制包

在第二种情况下,好好的想清楚,你是否真应该这样做。在第三种情况下,我建议在另外一个 "npm installer" 镜像安装构建工具,基于最小的 node.js 镜像。

不要遗留临时文件

下面的 Dockerfile 结果镜像大小是 109 MB:

FROM debian:wheezy
RUN apt-get update && apt-get install -y wget
RUN wget http://cachefly.cachefly.net/10mb.test
RUN rm 10mb.test

在另一方面,这看似相当的 Dockerfile 结果镜像大小是 99 MB:

FROM debian:wheezy
RUN apt-get update && apt-get install -y wget
RUN wget http://cachefly.cachefly.net/10mb.test && rm 10mb.test

因此看起来如果你在 Dockerfile 的两个步骤之间在磁盘空间留下了一个文件,当你删除这个文件的时候,空间不会被回收。也可以完全避免临时文件,仅仅在命令行之间管道输出。比如:

wget -O - http://nodejs.org/dist/v0.10.32/node-v0.10.32-linux-x64.tar.gz | tar zxf -

将提取压缩文件,并没有把它放在文件系统上。

包管理后进行清理

如果你运行 apt-get update 设置你的容器,它在 /var/lib/apt/lists/ 目录构成了数据,但是一旦镜像完成,这些数据是不需要的。你可以安全的清理那个目录来节约一些兆字节。

这个 Dockerfile 生成一个 99 MB 镜像:

FROM debian:wheezy
RUN apt-get update && apt-get install -y wget

然而这个生成一个 90 MB 的镜像:

FROM debian:wheezy
RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*
指定包的版本

当一个 Docker 镜像是不可变的,一个 Dockerfile 是不保证在运行在不同的时间生成相同的输出。这个问题,当然,是外部状态,并且我们难以控制它。最好在某种程度上最小化你的 Dockerfile 外部状态的影响,这是有可能的。做这个的一个简单方式是指定包的版本,当通过包管理器更新的时候。这里有一个怎样做的示例:

# apt-get update
# apt-cache showpkg redis-server
Package: redis-server
Versions:
2:2.4.14-1
...

# apt-get install redis-server=2:2.4.14-1

我们所能希望的是,但是这是没有保障的,包仓库从现在开始的一年仍然会是这个版本。尽管如此,明确的显示你镜像中依赖的软件版本是不可否认的价值。

组合命令

如果你有一系列的相关命令,最好的方式是在一个命令中串联它们。这是一个更有意义的构建缓存(逻辑分组步骤集中到一个缓存步骤)并使得文件系统层级数量降下来了(我认为通常这是可取的,但是不知道在客观上是否是更好的)。

反斜线符号 在这里帮助你提升可读性:

RUN apt-get update && 
    apt-get install -y 
        wget=1.13.4-3+deb7u1 
        ca-certificates=20130119 
        ...
使用环境变量避免重复

这是我阅读官方的 node.js Docker 镜像的 Dockerfile 学来的一个技巧。此外,这个 Dockerfile 是非常棒的。我唯一的指责就是它是基于一个巨大的 buildpack-deps 镜像,带着各种各样我不需要或不想要的东西。

你可以使用 ENV 定义环境变量,然后在一系列的命令中引用它们。下面,我从链接的 Dockerfile 中转述了摘要:

ENV NODE_VERSION 0.10.32

RUN curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" 
    && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 
    && rm "node-v$NODE_VERSION-linux-x64.tar.gz"

上面这个版本信息,你只需要使用环境变量 NODE_VERSION 定义一次即可,而不用每次都写。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/26355.html

相关文章

  • 轻松搞定|将PHP和Couchbase应用部署为Docker

    摘要:此时,可以构建映像,并将其部署为容器。从执行以下操作以上命令将使用文件中定义的端口,构建对应镜像和部署成为容器。 showImg(https://segmentfault.com/img/remote/1460000010122752); 数人云之前分享了《如何用Docker实现PHP命令行程序的CI/CD》,详细地介绍了整体过程中的思路以及以及注意事项,今天带来的文章将阐述怎样部署一...

    X1nFLY 评论0 收藏0
  • Dockerfile多阶段构建原理和使用场景

    摘要:版本以后,新增了多阶段构建。所谓多阶段构建,实际上是允许一个中出现多个指令。因为多个指令会造成多根,则是无法实现的。会使用一个完全干净的文件系统,不包含任何文件。可以使得最后生成的镜像最小化,其中只包含了程序。 Docker 17.05版本以后,新增了Dockerfile多阶段构建。所谓多阶段构建,实际上是允许一个Dockerfile 中出现多个 FROM 指令。这样做有什么意义呢? ...

    fireflow 评论0 收藏0
  • 记一次Docker构建失败

    摘要:之所以在本地构建,而没有使用仓库的,是因为,我们的镜像采用了国内阿里云的源,再加上某些很奇妙的网络因素,在中自动构建时,升级总会失败。然而,在本地再次构建成功。 见字如晤。 前段时间,Node.js 官方发布了Node 8.9.3 LTS版本,并且官网首页提示新版本有重要安全更新,Important security releases, please update now! ,然后我立...

    joyqi 评论0 收藏0
  • 学习使用DockerDocker-Compose和Rancher搭建部署Pipeline(一)

    摘要:工程师选择了环境中的一台当前没有在负载均衡器中被激活的主机。工程师登陆到这台主机并从注册表中获取新的版本。在生产维护窗口中,更新负载均衡器使其指向更新过的主机。然而将部署代码化的问题仍然存在。 这篇文章是一系列文章的第一篇,在这一系列文章中,我们想要分享我们如何使用Docker、Docker-Compose和Rancher完成容器部署工作流的故事。我们想带你从头开始走过pipeline...

    mikyou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<