Docker入门11 - Dockerfile - 镜像多步骤构建

189 阅读4分钟

镜像的创建

Build指令
format: docker build [OPTIONS] PATH | URL | -\

Build 过程

1.使用docker build 命令来创建镜像。\
2.该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下所有数据作为上下文(Context)发送给Docker服务端。
3.Docker服务端在校验Dockerfile格式通过后,逐条执行其中定义的指令,碰到ADDCOPY和RUN指令会生成一层新的镜像。
4.如果创建镜像成功,会返回最终镜像的ID。

Tips: 由于build命令会加载目录下所有的文件当做上下文,为了防止上下文过大,build时间过长,我们需要指定的目录下,只包含镜像创建所需文件。

父子镜像
docker中的镜像往往会有继承关系,我们可以使用基础镜像或者普通镜像当作父镜像。
基础镜像的定义文件中往往不会有FROM指令,或者是FROM scratch,是作为根镜像存在.

继承关系 image.png

Build Ignore
docker build也提供了类似gitignore的文件,我们可以通过.dockerignore文件(每一行添加一条匹配模式)来让Docker忽略匹配路径或文件,在创建镜像时候不将无关数据发送到服务端。

.dockerignore

*/temp*
*/*/temp*
tmp?
Dockerfile

通配符参数
dockerignore文件中模式语法支持Golang风格的路径正则格式:
“*”表示任意多个字符;
“? ”代表单个字符;
“! ”表示不匹配(即不忽略指定的路径或文件)。

Build 多步骤镜像创建
当我们需要build 包含Java/Go这种需要编译的应用的镜像时,我们往往采用多步骤镜像创建的方式,

优点
可以在保证最终生成的运行环境镜像保持精简的情况下,使用单一的Dockerfile,降低维护复杂度。

我们会将环境变量镜像分为编译环境变量和运行环境变量
编译环境镜像:包括完整的编译引擎、依赖库等,往往比较庞大。作用是编译应用为二进制文件;
运行环境镜像:利用编译好的二进制文件,运行应用,由于不需要编译环境,体积比较小.

Dockerfile Go multi stage build的完整例子

1. main.go文件

[root@yz117 go]# cat main.go
package main
import(
    "fmt"
)

func main() {
    fmt.Println("Hello Docker")
}

2.Dockerfile

[root@yz117 go]# cat Dockerfile 
# define stage as builder, use golang image as compile binary file: app
FROM golang:1.9 as builder
RUN mkdir -p /go/src/test
WORKDIR /go/src/test
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

#use simple image alpine as run env file
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
#copy file from the build stage
COPY --from=builder /go/src/test/app .

CMD ["./app"]

3.Docker build

[root@yz117 go]# docker build -t 1761218/test-multistage:latest .
Sending build context to Docker daemon  3.072kB
Step 1/10 : FROM golang:1.9 as builder
1.9: Pulling from library/golang
55cbf04beb70: Pull complete 
1607093a898c: Pull complete 
9a8ea045c926: Pull complete 
d4eee24d4dac: Pull complete 
9c35c9787a2f: Pull complete 
8b376bbb244f: Pull complete 
0d4eafcc732a: Pull complete 
186b06a99029: Pull complete 
Digest: sha256:8b5968585131604a92af02f5690713efadf029cc8dad53f79280b87a80eb1354
Status: Downloaded newer image for golang:1.9
 ---> ef89ef5c42a9
Step 2/10 : RUN mkdir -p /go/src/test
 ---> Running in e41bc76d581b
Removing intermediate container e41bc76d581b
 ---> 78bc2fd4e1fa
Step 3/10 : WORKDIR /go/src/test
 ---> Running in 95e37f1d3de2
Removing intermediate container 95e37f1d3de2
 ---> 3f5cfa40093a
Step 4/10 : COPY main.go .
 ---> 97dbf1e69295
Step 5/10 : RUN CGO_ENABLED=0 GOOS=linux go build -o app .
 ---> Running in ac3b08461ed3
Removing intermediate container ac3b08461ed3
 ---> 823eace3b04d
Step 6/10 : FROM alpine:latest
latest: Pulling from library/alpine
df9b9388f04a: Already exists 
Digest: sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454
Status: Downloaded newer image for alpine:latest
 ---> 0ac33e5f5afa
Step 7/10 : RUN apk --no-cache add ca-certificates
 ---> Running in 621fad808eae
fetch https://dl-cdn.alpinelinux.org/alpine/v3.15/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.15/community/x86_64/APKINDEX.tar.gz
(1/1) Installing ca-certificates (20211220-r0)
Executing busybox-1.34.1-r5.trigger
Executing ca-certificates-20211220-r0.trigger
OK: 6 MiB in 15 packages
Removing intermediate container 621fad808eae
 ---> 557ffe46ff07
Step 8/10 : WORKDIR /root/
 ---> Running in b27663fc3f51
Removing intermediate container b27663fc3f51
 ---> ba46832e3ad3
Step 9/10 : COPY --from=builder /go/src/test/app .
 ---> fb0d5ed4f374
Step 10/10 : CMD ["./app"]
 ---> Running in 6d84e31224ab
Removing intermediate container 6d84e31224ab
 ---> f9464cd0b57d
Successfully built f9464cd0b57d
Successfully tagged 17612180197/test-multistage:latest

4. Docker run

[root@yz117 go]# docker run --rm 1761218/test-multistage:latest 
Hello Docker

5.查看镜像
我们可以看到使用精简镜像作为运行环境常见的镜像大小仅有不到8MB。

[root@yz117 go]# docker images | grep 176
1761218/test-multistage latest f9464cd0b57d 57 minutes ago   7.93MB

build支持参数速查

image.png