繁体   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