![](/img/trans.png)
[英]Dockerfile: COPY/ADD and RUN with rm in a single layer
[英]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.