一层Dockerfile COPY和RUN

时间:2019-07-04 10:27:48

标签: docker

我有一个用于准备Docker映像的脚本。我在Dockerfile中有这个文件:

COPY my_script /
RUN bash -c "/my_script"

my_script文件包含图像中不需要的秘密(完成后会自动删除)。

问题在于,由于COPY是一个单独的图层,因此尽管删除了该文件仍保留在图像中。我需要的是COPY和RUN都影响同一层。

如何复制和运行脚本,以便两个动作都影响同一层?

5 个答案:

答案 0 :(得分:1)

看看multi-stage

使用多阶段构建

  

对于多阶段构建,您可以在自己的数据库中使用多个FROM语句   Dockerfile。每个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"]  

答案 1 :(得分:1)

从18.09开始,您可以在构建过程中使用docker build --secret使用秘密信息。这些秘密将被安装到构建环境中,并且不会存储在最终映像中。

conda install plotly
RUN --mount=type=secret,id=script,dst=/my_script \
    bash -c /my_script

该脚本不需要删除自身。

答案 2 :(得分:0)

我想您可以使用一种解决方法来做到这一点:

my_script放置在本地http服务器中,例如使用python -m SimpleHTTPServer,然后可以使用http://http_server_ip:8000/my_script来访问文件

然后,在Dockerfile中使用下一步:

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

此解决方法确保文件在同一层中添加和删除,当然,您可能需要在curl中添加Dockerfile安装。

答案 3 :(得分:0)

这可以通过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仓库中提取。 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

答案 4 :(得分:0)

我认为BuildKit中的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 

第一个皮棉必须为#语法= docker / dockerfile:experimental ,因为它是实验性功能。

此方法不适用于docker的Play,但可以在我的计算机上使用...

我的计算机使用带有docker 19.03.12的Ubuntu 20.04

然后,用

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