官网首页 > 新闻资讯 > 行业新闻 >

行业新闻

NEWS

Dockerfile规范与技巧

作者:发布时间:2019-09-02 14:59

更多规则可参考 Docker官方文档

在代码根目录放置Dockerfile后,通过docker build -f Dockerfile .可以构建镜像,镜像中需要包含此次的构建产物,所以需要在Dockerfile中增加编译打包步骤,此步骤只是为了做编译打包使用,势必不能影响最终镜像构建的分层,所以Dockerfile需要采用多个 FROM 指令的方式。

多个FROM指令并不是为了生成多根的层关系,最后生成的镜像,仍以最后一条FROM为准,之前的FROM会被抛弃,那么之前的FROM又有什么意义呢?

每一条FROM指令都是一个构建阶段,多条FROM就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。

最大的使用场景是将编译环境和运行环境分离,比如,之前我们需要构建一个Go语言程序,那么就需要用到go命令等编译环境,我们的Dockerfile可能是这样的:

# Go语言环境基础镜像
FROM golang:1.10.3
# 将源码拷贝到镜像中
COPY server.go /build/
# 指定工作目录
WORKDIR /build
# 编译镜像时,运行 go build 编译生成 server 程序
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server
# 指定容器运行时入口程序 server
ENTRYPOINT ["/build/server"]
复制代码

基础镜像golang:1.10.3是非常庞大的,因为其中包含了所有的Go语言编译工具和库,而运行时候我们仅仅需要编译后的server程序就行了,不需要编译时的编译工具,最后生成的大体积镜像就是一种浪费。

新的解决方案,编译阶段与运行阶段直接在一个Dockerfile就可以解决:

# 编译阶段
FROM golang:1.10.3
COPY server.go /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server
# 运行阶段
FROM scratch
# 从编译阶段的中拷贝编译结果到当前镜像中
COPY --from=0 /build/server /
ENTRYPOINT ["/server"]
复制代码

这个Dockerfile的玄妙之处就在于COPY指令的--from=0参数,从前边的阶段中拷贝文件到当前阶段中,多个FROM语句时,0代表第一个阶段。除了使用数字,还可以给阶段命名,比如:

# 编译阶段 命名为 builder
FROM golang:1.10.3 as builder
# ... 省略
# 运行阶段
FROM scratch
# 从编译阶段的中拷贝编译结果到当前镜像中
COPY --from=builder /build/server /
复制代码
Copyright © 2018 九州备用网址官方网站九州备用网址官方网站-九州备用网站 All Rights Reserved