Dockerfile
入门门槛不高,能够参照 官方文档,很快就能上手写出一个能够构建出镜像的Dockerfile
。linux
继续深究,会发现Dockerfile
实际上是有一些讲究的,今天要分享的是Dockerfile
里的一些规范与技巧。git
咱们以
docker build
为引子一一道来golang
docker build
命令从Dockerfile
文件和上下文环境context
中构建image
。docker
context
是一个指定位置的路径path
或者URL
下的一系列文件path
是本地文件系统中的一个目录。URL是一个Git仓库的位置。context
会被递归的处理,一个路径path
包含其下的全部子路径URL
包含对应的仓库以及全部的子模块一个简单的构建命令使用当前的目录做为上下文环境
context
bash
docker build .
复制代码
Dockerfile
默认放在代码的根路径,且不带后缀名工具
代码的根路径必须有.dockerignore
文件,且.dockerignore
文件内容中必须忽略.git
目录,范例以下:ui
# comment
.git
*/temp*
*/*/temp*
temp?
*.md
!README.md
复制代码
Rule | Behavior |
---|---|
# comment | 注释 |
/temp | 如 /somedir/temporary.txt |
//temp* | 如 /somedir/subdir/temporary.txt |
temp? | 如 tempa、tempb |
*.md !README.md | 除了README.md以外的全部md文件 |
更多规则可参考 Docker官方文档spa
在代码根目录放置Dockerfile
后,经过docker build -f Dockerfile .
能够构建镜像,镜像中须要包含这次的构建产物,因此须要在Dockerfile
中增长编译打包步骤,此步骤只是为了作编译打包使用,势必不能影响最终镜像构建的分层,因此Dockerfile须要采用多个 FROM 指令的方式。code
From
指令的意义:多个FROM
指令并非为了生成多根的层关系,最后生成的镜像,仍以最后一条FROM
为准,以前的FROM
会被抛弃,那么以前的FROM
又有什么意义呢?server
每一条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 / 复制代码