簡體   English   中英

Dockerfile COPY 和 RUN 在一層

[英]Dockerfile COPY and RUN in one layer

我有一個用於准備 Docker 映像的腳本。 我在 Dockerfile 中有這個:

COPY my_script /
RUN bash -c "/my_script"

my_script文件包含我不希望出現在圖像中的秘密(完成后它會自行刪除)。

問題是盡管被刪除了文件仍然保留在圖像中,因為 COPY 是一個單獨的層。 我需要的是 COPY 和 RUN 影響同一層。

如何復制和運行腳本以便兩個操作都影響同一層?

看一下多階段

使用多階段構建

通過多階段構建,您可以在Dockerfile中使用多個FROM語句。 每個FROM指令可以使用不同的基礎,並且每個都開始構建的新階段。 您可以有選擇地將工件從一個階段復制到另一個階段, 從而在最終圖像中留下不需要的所有內容 為了展示它是如何工作的,讓我們改編上一部分中的Dockerfile以使用多階段構建。

Dockerfile:

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"]  

從18.09開始,您可以使用docker build --secret在構建過程中使用秘密信息。 機密會安裝到構建環境中,並且不會存儲在最終映像中。

RUN --mount=type=secret,id=script,dst=/my_script \
    bash -c /my_script
$ docker build --secret id=script,src=my_script.sh

該腳本不需要刪除自身。

我想您可以使用一種解決方法來做到這一點:

my_script放入本地http服務器(例如,使用python -m SimpleHTTPServer ,然后可以使用http://http_server_ip:8000/my_script訪問該文件

然后,在Dockerfile中使用next:

RUN curl http://http_server_ip:8000/my_script > /my_script && chmod +x /my_script && bash -c "/my_script"

這種解決方法確保文件在同一層中添加和刪除,當然,您可能需要在Dockerfile添加curl安裝。

可以通過BuildKit處理:

# syntax=docker/dockerfile:experimental
FROM ...
RUN --mount=type=bind,target=/my_script,source=my_script,rw \
    bash -c "/my_script"

然后,您將使用:

DOCKER_BUILDKIT=1 docker build -t my_image .

這聽起來也像您正在嘗試向構建中注入秘密,例如從私有git repo中提取。 BuildKit還允許您指定:

# syntax=docker/dockerfile:experimental
FROM ...
RUN --mount=type=secret,target=/creds,id=cred \
    bash -c "/my_script -i /creds"

然后,您將使用:

DOCKER_BUILDKIT=1 docker build -t my_image --secret id=creds,src=./creds .

使用這兩個BuildKit選項時,mount命令實際上從未將文件添加到映像中。 它僅使文件在該單個RUN步驟中可用作綁定安裝。 只要該RUN步驟不會將密鑰輸出到映像中的另一個文件,該密鑰就永遠不會注入到映像中。

有關BuildKit實驗語法的更多信息,請參見: https : //github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md

我認為RUN --mount=type=bind,source=my_script,target=/my_script bash /my_script可以解決您的問題。

一、准備BuildKit

export DOCKER_CLI_EXPERIMENTAL=enabled
export DOCKER_BUILDKIT=1
docker buildx create --name mybuilder --driver docker-container
docker buildx use mybuilder

然后,編寫您的 Dockerfile。

# syntax = docker/dockerfile:experimental
FORM debian
## something

RUN --mount=type=bind,source=my_script,target=/my_script bash -c /my_script 

第一個 lint 必須是# syntax = docker/dockerfile:experimental因為它是實驗性功能。

而這種方法在與 docker 一起玩時不起作用,但在我的電腦上工作......

我的電腦是 Ubuntu 20.04 和 docker 19.03.12

然后,用

docker buildx build --platform linux/amd64 -t user/imgname -f ./Dockerfile . --push

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM