博客作为学习笔记记录,若有理解,表述错误,欢迎指出。
docker 多阶镜像(multi-stage)是为了解决多个容器镜像之间文件拷贝等问题,多阶镜像有几个常用的场景:
1. debug: 用于调试dockerfile的特定阶段
2. 用于测试和debug阶段
Q: 为什么要用多阶镜像
在以前,如果需要从一个容器里把编译好的文件放到另外一个容器执行,需要分开两步操作。
举个栗子:
1、 编译工程的docker,对应dockerfile:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go .
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app
2、运行程序的docker
FROM
alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]
3、 将编译的程序拷到运行的docker里运行
#!/bin/sh
# 构建app可执行文件的docker镜像,运行临时docker容器
# 并把app可执行文件拷贝到host上,
# 删除临时docker容器
echo Building alexellis2/href-counter:build
docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \
-t alexellis2/href-counter:build . -f Dockerfile.build
docker container create --name extract alexellis2/href-counter:build
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app
docker container rm -f extract
# 构建app执行环境的docker镜像,运行执行环境容器
# 并把app可执行文件拷贝到运行环境docker容器中,
# 删除host上app
echo Building alexellis2/href-counter:latest
docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app
这样做也能实现app到运行环境执行,但会有什么问题呢:
问题1:分开操作,麻烦
问题2:需编多个镜像,然后把app拷出来,占用disk空间
A: 使用多阶镜像构建方式
使用多阶镜像后,前面那个操作,可以简化成这样:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
分析以上dockerfile:
1、 每个阶段stage都可以用不同base image
2、只会保留最后一个stage的镜像,前面的都会摒弃
3、可以在后面的stage使用前面stage的东西,eg:
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
4、 每个阶段以正数索引,从0开始,也可以通过FROM xxx as
FROM golang:1.7.3 as builder
…
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
5、在多阶中,可以分阶段build,eg:
$ docker build --target builder -t alexellis2/href-counter:latest .
用途:
A、 debug
B、testing
C、只编某个阶段的镜像
6、 COPY --from=xxx,源image没有限制,eg:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
from 镜像来源:
a. 本地image name
b. 本地image tag
c. docker registry上的image,tag ID
REF:
https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage