将内容从主机 OS 复制到 Docker 图像而不重建图像

Copy contents from host OS into Docker image without rebuilding image

我正在构建一个新映像,并将主机 OS 文件夹 D:\Programs\scrapy 中的内容复制到其中,如下所示:docker build . -t scrapy

Dockerfile

FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy
COPY scrapy to /root/scrapy

    

现在,当我将新内容添加到主机 OS 文件夹“D:\Programs\scrapy”时,我还想将其添加到图像文件夹“root/scrapy”,但我不知道我想建立一个全新的形象(需要相当长的时间)。 那么如何保留现有图像并覆盖图像文件夹“root/scrapy”的内容。
另外:我不想每次 运行 容器时都复制新内容(所以不是在 运行 时),我只想拥有一个单独的命令,用于将更多文件添加到现有图像,然后 运行 另一个基于该图像的新容器。

我在这里查看:How to update source code without rebuilding image(但不确定 OP 是否尝试与我做同样的事情)

更新 1

正在检查 and docker --volume format for Windows

我尝试了以下命令,均导致错误:

docker: Error response from daemon: invalid volume specification: ''. See 'docker run --help'.

其中 <pathiused> 例如 D:/Programs/scrapy:/root/scrapy

docker run -v //D/Programs/scrapy:/root/scrapy scrapy

docker run -v scrapy:/root/scrapy scrapy

docker run -it -v //D/Programs/scrapy:/root/scrapy scrapy

docker run -it -v scrapy:/root/scrapy scrapy

根据@Makariy 的反馈使用 cp 命令进行更新

docker images -a 给出:

REPOSITORY                             TAG        IMAGE ID       CREATED        SIZE
scrapy                                 latest     e35e03c8cbbd   29 hours ago   5.71GB
<none>                                 <none>     2089ad178feb   29 hours ago   5.71GB
<none>                                 <none>     6162a0bec2fc   29 hours ago   5.7GB
<none>                                 <none>     116a0c593544   29 hours ago   5.7GB
mcr.microsoft.com/windows/servercore   ltsc2019   d1724c2d9a84   5 weeks ago    5.7GB

I 运行 docker run -it scrapy 然后 docker container ls 给出:

CONTAINER ID   IMAGE     COMMAND                    CREATED              STATUS              PORTS     NAMES
1fcda458a14c   scrapy    "c:\windows\system32…"   About a minute ago   Up About a minute             thirsty_bassi

如果我 运行 docker cp D:\Programs\scrapy scrapy:/root/scrapy 我得到:

Error: No such container:path: scrapy:\root

所以在一个单独的 PowerShell 实例中,我然后 运行 docker cp D:\Programs\scrapy thirsty_bassi:/root/scrapy 在 PowerShell 中没有显示任何输出,所以我认为它应该做一些事情。

但是在我的容器实例中,当我转到 /root/scrapy 文件夹时,我只能看到构建图像时已经添加的文件,而不是我想要添加的新文件。

另外,我想我是在这里向容器中添加文件,但是没有办法将它添加到图像中吗?不重建整个图像?

更新 2

我的文件夹结构:

D:\Programs
    Dockerfile
    \image_addons
    Dockerfile
        \scrapy

PS D:\Programs>docker build . -t scrapybase

成功构建95676d084e28
成功标记 scrapybase:latest

PS D:\Programs\image_addons> docker build -t scrapy .

Step 2/2 : COPY scrapy to /root/scrapy COPY failed: file not found in build context or excluded by .dockerignore: stat to: file does not exist

Dockerfile A

FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR /root/scrapy

Dockerfile B

FROM scrapybase
COPY scrapy to /root/scrapy

对于您的场景:

docker run -v D:/test:/root/test your-image

中提供了很多有价值的详细信息

如果你想要它又快又脏,请回答

docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt

快速更新一个文件: 如果您不必构建代码(我不知道您使用的是什么语言),您可以使用初始代码构建一些基本图像,并且当您只想更改一个文件时(我再次假设您不这样做)不需要为此再次编译你的项目,否则如果你这样做是不可能的,因为 compiled programming language):

FROM previous-version-image:latest
COPY myfile dest/to/file

那么因为你的 CMDENTRYPOINT 是从前面的阶段保存下来的,所以不需要声明它们。 (如果您不记得使用 docker history <docker-image-name> 查看虚拟 docker 图像文件到此阶段)。

注意不要重复使用这个方法,否则你会得到一个非常大的图像,有很多无用的图层。仅将其用于快速测试和调试。

说明

通常人们使用它在 docker 容器上进行前端开发,但基本思想仍然存在,您创建基本工作图像并安装依赖项并设置目录布局,最后一个 Dockerfile 命令是开发服务器启动命令。

示例:

Docker 文件:

# pull the base image
FROM node:slim

# set the working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# copy dependencies files
COPY package.json ./

COPY package-lock.json ./

# install app dependencies
RUN npm install

# add app
COPY . ./

# start development server
CMD ["npm", "start"]

启动命令:

docker run -it --rm \
-v ${PWD}:/app \       <mount current working directory in host to container in path /app>
-v /app/node_modules \ <or other dependency directory if exists>
-p 80:3000 \           <ports if needs exposing>
ps-container:dev

我不确定该用例是否 100% 适合您,因为它需要一直使用 bind-mount 安装代码,并且在需要导出时必须导出为另一方面,它允许您快速更改图像和源代码目录,而无需在每次添加新内容时等待构建图像,并最终构建包含所有所需内容的最终图像。

问题提供代码的更多相关示例:

如您所见,主机上有一个包含一些文本的文件

使用 bind-mount 访问文件的命令:

docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt

希望您能从我在这里提供的内容中找到适合您的内容。

感谢 this tutorial and this example 提供示例和信息。

编辑:

假设您的原始 Dockerfile 如下所示:

FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py

这将在我们将添加图层并更改 python 文件的基础上构建您的初始图像。 我们将使用的下一个 Dockerfile(我们称之为 Dockerfile.fix 文件)将复制我们想要更改的文件,而不是图像中已有的文件

FROM previous-image-name
COPY app.py .

现在,在使用这个 Dockerfile 构建之后,最终图像 Dockerfile 看起来(有点)像这样:

FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py
FROM previous-image-name
COPY app.py .

每次我们想要更改文件时,我们都会使用第二个 Dockerfile

您也可以使用 docker cp,将文件从您的主机手动复制到 运行 容器

docker cp ./path/to/file containername:/another/path

Docs

如果 Docker 图像不重建(至少是部分重建),则无法更改它。但是你不必重建全部,你可以重建复制你的scrapy内容的图层。

您可以优化构建以拥有两个图像:

  • 第一张图片是您不想每次都重建的静态图片。我们称它为 scrapy-base.
  • 第二张也是最后一张图片基于第一张图片 scrapy-base,仅用于复制您的动态 scrapy 内容

scrapy-base的Docker文件:

FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy

并将其构建为:

docker build -t scrapy-base .

这条命令只需要运行一次。如果您只更改本地 scrapy 文件夹的内容,则不必构建此映像。 (如您所见,构建根本没有使用它)

scrapy 的 Docker 文件:

FROM scrapy-base

COPY scrapy /root/scrapy

使用构建命令:

docker build -t scrapy .

这第二个构建命令将重新使用之前的静态图像并且只复制内容而无需重建整个图像。即使有很多文件,它也应该很快。您不需要 运行ning 容器。