如何使用一個 Dockerfile 文件描述多個鏡像


我們知道在 Docker v17.05 版本后就開始支持多階段構建 (multistage builds)了,使用多階段構建我們可以加速我們的鏡像構建,在一個 Dockerfile 文件中分不同的階段來處理鏡像。

例如,如下所示的多階段構建的 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"]

構建鏡像

$ docker build -t go/helloworld:3 .

這樣構建出來的鏡像容量也非常小。

除此之外,Docker 多階段構建還可以只構建某一階段的鏡像,比如我們一個項目中由於需求可能會最終打包成多個 Docker 鏡像,我們當然可以為每一個鏡像單獨編寫一個 Dockerfile,但是這樣還是比較麻煩。遇到這種需求我們就可以直接使用多階段構建來解決。如下所示的 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"]

我們可以看到在這一個 Dockerfile 中我們使用多階段構建定義了很多個 Targets,當我們在構建鏡像的時候就可以通過 --target 參數來明確指定要構建的 Targets 即可,比如我們要構建 controller 這個目標鏡像,則直接使用下面的命令構建即可:

$ 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 .

同樣要構建其他的目標鏡像則將 target 的參數值替換成階段定義的值即可。這樣我們就用一個 Dockerfile 文件定義了多個鏡像。

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM