宜信技术大牛教你如何编写优雅的 Docker file

来源:宜信技术学院

ID:CE_TECH

作者:王聪

Kubernetes要从容器化开始,而容器又需要从Dockerfile开始,本文将介绍如何写出一个优雅的Dockerfile文件。

文章主要内容包括:

感谢公司提供大量机器资源及时间让我们可以实践,感谢在此专题上不断实践的部分项目及人员的支持。

宜信技术大牛教你如何编写优雅的 Docker file


1

Docker容器


1.1 容器的特点

我们都知道容器就是一个标准的软件单元,它有以下特点:

1.2 Docker容器

目前市面上的主流容器引擎有Docker、Rocket/rkt、OpenVZ/Odin等等,而独霸一方的容器引擎就是使用最多的Docker容器引擎。

Docker容器是与系统其他部分隔离开的一系列进程,运行这些进程所需的所有文件都由另一个镜像提供,从开发到测试再到生产的整个过程中,Linux 容器都具有可移植性和一致性。相对于依赖重复传统测试环境的开发渠道,容器的运行速度要快得多,并且支持在多种主流云平台(PaaS)和本地系统上部署。Docker容器很好地解决了“开发环境能正常跑,一上线就各种崩”的尴尬。


宜信技术大牛教你如何编写优雅的 Docker file


Docker容器的特点:


2

Dockerfile


Dockerfile是用来描述文件的构成的文本文档,其中包含了用户可以在使用行调用以组合Image的所有命令,用户还可以使用Docker build实现连续执行多个命令指今行的自动构建。

通过编写Dockerfile生磁镜像,可以为开发、测试团队提供基本一致的环境,从而提升开发、测试团队的效率,不用再为环境不统一而发愁,同时运维也能更加方便地管理我们的镜像。

Dockerfile的语法非常简单,常用的只有11个:


宜信技术大牛教你如何编写优雅的 Docker file


2.1 编写优雅地Dockerfile

编写优雅的Dockerfile主要需要注意以下几点:

只要记住以上三点就能写出不错的Dockerfile。

为了方便大家了解,我们用两个Dockerfile实例进行简单的对比:


FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y apt-utils libjpeg-dev  
python-pip
RUN pip install --upgrade pip
RUN easy_install -U setuptools
RUN apt-get clean


FROM ubuntu:16.04
RUN apt-get update && apt-get install -y apt-utils 
 libjpeg-dev python-pip 
 && pip install --upgrade pip 
 && easy_install -U setuptools 
 && apt-get clean


我们看第一个Dockerfile,乍一看条理清晰,结构合理,似乎还不错。再看第二个Dockerfile,紧凑,不易阅读,为什么要这么写?

从下表可以看出两个Dockerfile所编译出来的镜像大小:


$ docker images | grep ubuntu 
REPOSITORY TAG IMAGE ID CREATED SIZE 
ubuntu 16.04 9361ce633ff1 1 days ago 422MB
ubuntu 16.04-1 3f5b979df1a9 1 days ago 412MB


呃…. 好像并没有特别的效果,但若Dockerfile非常长的话可以考虑减少层次,因为Dockerfile最高只能有127层。


3

使用多阶构建


Docker在升级到Docker 17.05之后就能支持多阶构建了,为了使镜像更加小巧,我们采用多阶构建的方式来打包镜像。在多阶构建出现之前我们通常使用一个Dockerfile或多个Dockerfile来构建镜像。

3.1单文件构建

在多阶构建出来之前使用单个文件进行构建,单文件就是将所有的构建过程(包括项目的依赖、编译、测试、打包过程)全部包含在一个Dockerfile中之下:


FROM golang:1.11.4-alpine3.8 AS build-env
ENV GO111MODULE=off
ENV GO15VENDOREXPERIMENT=1
ENV BUILDPATH=github.com/lattecake/hello
RUN mkdir -p /go/src/${BUILDPATH}
COPY ./ /go/src/${BUILDPATH}
RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v
CMD [/go/bin/hello]


这种的做法会带来一些问题:

以Golang为例,它运行时不依赖任何环境,只需要有一个编译环境,那这个编译环境在实际运行时是没有任务作用的,编译完成后,那些源码和编译器已经没有任务用处了也就没必要留在镜像里。



宜信技术大牛教你如何编写优雅的 Docker file


上表可以看到,单文件构建最终占用了312MB的空间。

3.2 多文件构建

在多阶构建出来之前有没有好的解决方案呢?有,比如采用多文件构建或在构建服务器上安装编译器,不过在构建服务器上安装编译器这种方法我们就不推荐了,因为在构建服务器上安装编译器会导致构建服务器变得非常臃肿,需要适配各个语言多个版本、依赖,容易出错,维护成本高。所以我们只介绍多文件构建的方式。

多文件构建,其实就是使用多个Dockerfile,然后通过脚本将它们进行组合。假设有三个文件分别是:Dockerfile.run、Dockerfile.build、build.sh。

Dockerfile.build


FROM golang:1.11.4-alpine3.8 AS build-env
ENV GO111MODULE=off
ENV GO15VENDOREXPERIMENT=1
ENV BUILDPATH=github.com/lattecake/hello
RUN mkdir -p /go/src/${BUILDPATH}
COPY ./ /go/src/${BUILDPATH}
RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v


Dockerfile.run


FROM alpine:latest
RUN apk –no-cache add ca-certificates
WORKDIR /root
ADD hello .
CMD ["./hello"]


Build.sh


#!/bin/sh
docker build -t –rm hello:build . -f Dockerfile.build
docker create –name extract hello:build
docker cp extract:/go/bin/hello ./hello
docker rm -f extract
docker build –no-cache -t –rm hello:run . -f Dockerfile.run
rm -rf ./hello


执行build.sh完成项目的构建。


宜信技术大牛教你如何编写优雅的 Docker file


从上表可以看到,多文件构建大大减小了镜像的占用空间,但它有三个文件需要管理,维护成本也更高一些。

3.3 多阶构建

最后我们来看看万众期待的多阶构建。

完成多阶段构建我们只需要在Dockerfile中多次使用FORM声明,每次FROM指令可以使用不同的基础镜像,并且每次FROM指令都会开始新的构建,我们可以选择将一个阶段的构建结果复制到另一个阶段,在最终的镜像中只会留下最后一次构建的结果,这样就可以很容易地解决前面提到的问题,并且只需要编写一个Dockerfile文件。这里值得注意的是:需要确保Docker的版本在17.05及以上。下面我们来说说具体操作。

在Dockerfile里可以使用as来为某一阶段取一个别名”build-env”:


FROM golang:1.11.2-alpine3.8 AS build-env


然后从上一阶段的镜像中复制文件,也可以复制任意镜像中的文件:


COPY –from=build-env /go/bin/hello /usr/bin/hello


看一个简单的例子:


FROM golang:1.11.4-alpine3.8 AS build-env
 
ENV GO111MODULE=off
ENV GO15VENDOREXPERIMENT=1
ENV GITPATH=github.com/lattecake/hello
RUN mkdir -p /go/src/${GITPATH}
COPY ./ /go/src/${GITPATH}
RUN cd /go/src/${GITPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -v
 
FROM alpine:latest
ENV apk –no-cache add ca-certificates
COPY --from=build-env /go/bin/hello /root/hello
WORKDIR /root
CMD ["/root/hello"]


执行docker build -t –rm hello3 .后再执行docker images ,然后我们来看镜像的大小:


宜信技术大牛教你如何编写优雅的 Docker file


多阶构建给我们带来很多便利,最大的优势是在保证运行镜像足够小的情况下还减轻了Dockerfile的维护负担,因此我们极力推荐使用多阶构建来将你的代码打包成Docker 镜像。

【超全整理】《Linux云计算从入门到精通》系列实战笔记全放送 | Linux运维部落​

www.magedu.com

希望大家有所帮助,祝愿大家学有所成。获取更多技术知识点+v156 5219 9186,欢豆在线解答哦~

展开阅读全文

页面更新:2024-03-11

标签:优雅   组合   层级   编译器   容器   组件   进程   操作系统   阶段   过程   环境   文件   测试   资源   技术   科技   空间

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top