如何使用一個(gè) Dockerfile 文件描述多個(gè)鏡像
我們知道在 Docker v17.05 版本后就開始支持多階段構(gòu)建 (multistage builds)了,使用多階段構(gòu)建我們可以加速我們的鏡像構(gòu)建,在一個(gè) Dockerfile 文件中分不同的階段來處理鏡像。
例如,如下所示的多階段構(gòu)建的 Dockerfile 文件:
FROM?golang:1.9-alpine?as?builder
RUN?apk?--no-cache?add?git
WORKDIR?/go/src/github.com/go/helloworld/
RUN?go?get?-d?-v?github.com/go-sql-driver/mysql
COPY?app.go?.
RUN?CGO_ENABLED=0?GOOS=linux?go?build?-a?-installsuffix?cgo?-o?app?.
FROM?alpine:latest?as?prod
RUN?apk?--no-cache?add?ca-certificates
WORKDIR?/root/
COPY?--from=0?/go/src/github.com/go/helloworld/app?.
CMD?["./app"]
構(gòu)建鏡像
$?docker?build?-t?go/helloworld:3?.
這樣構(gòu)建出來的鏡像容量也非常小。
除此之外,Docker 多階段構(gòu)建還可以只構(gòu)建某一階段的鏡像,比如我們一個(gè)項(xiàng)目中由于需求可能會最終打包成多個(gè) Docker 鏡像,我們當(dāng)然可以為每一個(gè)鏡像單獨(dú)編寫一個(gè) Dockerfile,但是這樣還是比較麻煩。遇到這種需求我們就可以直接使用多階段構(gòu)建來解決。如下所示的 Dockerfile:
#
#?BUILD?ENVIRONMENT
#?-----------------
ARG?GO_VERSION
FROM?golang:${GO_VERSION}?as?builder
RUN?apt-get?-y?update?&&?apt-get?-y?install?upx
WORKDIR?/workspace
COPY?go.mod?go.mod
COPY?go.sum?go.sum
RUN?go?mod?download
#?Copy?the?go?source
COPY?main.go?main.go
COPY?api/?api/
COPY?controllers/?controllers/
COPY?internal/?internal/
COPY?webhooks/?webhooks/
COPY?version/?version/
COPY?cmd/?cmd/
ENV?CGO_ENABLED=0
ENV?GOOS=linux
ENV?GOARCH=amd64
ENV?GO111MODULE=on
#?Do?an?initial?compilation?before?setting?the?version?so?that?there?is?less?to
#?re-compile?when?the?version?changes
RUN?go?build?-mod=readonly?"-ldflags=-s?-w"?./...
ARG?VERSION
#?Compile?all?the?binaries
RUN?go?build?-mod=readonly?-o?manager?main.go
RUN?go?build?-mod=readonly?-o?proxy?cmd/proxy/main.go
RUN?go?build?-mod=readonly?-o?backup-agent?cmd/backup-agent/main.go
RUN?go?build?-mod=readonly?-o?restore-agent?cmd/restore-agent/main.go
RUN?upx?manager?proxy?backup-agent?restore-agent
#
#?IMAGE?TARGETS
#?-------------
FROM?gcr.io/distroless/static:nonroot?as?controller
WORKDIR?/
COPY?--from=builder?/workspace/manager?.
USER?nonroot:nonroot
ENTRYPOINT?["/manager"]
FROM?gcr.io/distroless/static:nonroot?as?proxy
WORKDIR?/
COPY?--from=builder?/workspace/proxy?.
USER?nonroot:nonroot
ENTRYPOINT?["/proxy"]
FROM?gcr.io/distroless/static:nonroot?as?backup-agent
WORKDIR?/
COPY?--from=builder?/workspace/backup-agent?.
USER?nonroot:nonroot
ENTRYPOINT?["/backup-agent"]
FROM?gcr.io/distroless/static?as?restore-agent
WORKDIR?/
COPY?--from=builder?/workspace/restore-agent?.
USER?root:root
ENTRYPOINT?["/restore-agent"]
我們可以看到在這一個(gè) Dockerfile 中我們使用多階段構(gòu)建定義了很多個(gè) Targets,當(dāng)我們在構(gòu)建鏡像的時(shí)候就可以通過 --target 參數(shù)來明確指定要構(gòu)建的 Targets 即可,比如我們要構(gòu)建 controller 這個(gè)目標(biāo)鏡像,則直接使用下面的命令構(gòu)建即可:
$?docker?build?--target?controller?\
??--build-arg?GO_VERSION=${GO_VERSION}?\
??--build-arg?VERSION=$(VERSION)?\
??--tag?${DOCKER_REPO}/${DOCKER_IMAGE_NAME_PREFIX}controller:${DOCKER_TAG}?\
??--file?Dockerfile?.
同樣要構(gòu)建其他的目標(biāo)鏡像則將 target 的參數(shù)值替換成階段定義的值即可。這樣我們就用一個(gè) Dockerfile 文件定義了多個(gè)鏡像。
?點(diǎn)擊屏末?|?閱讀原文?|?即刻學(xué)習(xí)評論
圖片
表情
