在本地主机的 Docker 中找不到生成的文件

Cannot find generated files in the Docker in the localhost

让我们考虑这样的目录。 (注:一个目录以\结尾)

root\
|
-- some stuff
|
-- application\
|  |
|  -- app_stuff
|  |
|  -- out\
|  |
|  -- main.cpp
|
-- some stuff

我正在尝试通过 docker 构建此应用程序。 Dockerfile 看起来像:

FROM emscripten/emsdk:latest 

RUN apt-get -q update 

RUN mkdir /app

WORKDIR /app

COPY . /app

RUN em++ application/main.cpp -o application/out/app.html

RUN pip3 install aiohttp

RUN pip3 install aiohttp_jinja2

RUN pip3 install jinja2

RUN ls application/out

docker-compose 看起来像:

version: '3.8'

services:
    application:
        build: .
        volumes: 
            - ./application/out:/app/application/out
        command: python3 application/entry.py
        ports: 
            - "8080:8080"

正如您可能在 Dockerfile (RUN em++ application/main.cpp -o application/out/app.html) 中注意到的那样,而 docker 正在处理它,它会在 out 目录中生成新文件。但是,完成后我找不到那些文件。

注意:这些文件出现在application\out容器中。

...
Step 10/10 : RUN ls application/out
 ---> Running in 603f6b99f4b0
app.html
app.js
app.wasm
...

我哪里认错了?

一个Docker-compose卷可以link主机上的目录到容器内的目录。您正在 覆盖 容器内的 /app/application/out 目录,其中包含主机 ./application/out 的卷,有效地擦除任何内容/app/application/out 个来自您构建的图像。

鉴于上下文,我假设您的主机的 ./application/out 目录是空的,并且您正在覆盖容器的 /app/application/out 目录。您可以通过删除 volumes 标记来测试这一点,然后查看应用程序是否能够在之后找到 /app/application/out 下的文件。


与您的问题无关,考虑到您的 apt-get update 命令将在您构建的映像中缓存 Debian 远程存储库列表;这会浪费 space 到您的最终图像。请参阅 this post 关于删除缓存列表的信息。

Dockerfile 给出了如何构建 docker 图像的说明,而不是实时容器中发生的事情。

如果您通过 docker-compose 或通过 docker 运行 命令挂载卷,无论哪种方式,卷都只会在容器创建后挂载。

所以发生的事情是

  • 首先docker创建镜像执行Dockerfile中的命令,并将镜像存储为镜像
  • 然后 docker 将使用存储的图像创建一个容器
  • 然后 docker 将装载您在 docker-compose.yml 文件中定义的卷。 (此时如果目标目录中已经存在任何东西,要么挂载失败,要么将目标目录的原始内容移动到'lost-and-found'目录)
  • 那么入口点或 cmd 命令是 运行(所以这里是 python3 application/entry.py)

因此,如果您需要在主机目录中获取输出文件,您要么需要在入口点脚本中创建这些文件,要么将它们复制到入口点脚本中

因此您可以使用以下内容创建一个名为 myscript.sh 的文件

#!/bin/bash
em++ /app/application/main.cpp -o /app/application/out/app.html
python3 /app/application/entry.py

在您的 Dockerfile 中,您删除行 RUN em++ application/main.cpp -o application/out/app.html 并将其替换为

COPY ./myscript.sh /
ENTRYPOINT /myscript.sh

然后从 docker-compose.yml 文件中删除行 command: python3 application/entry.py

如果您愿意,可以使用 CMD 命令而不是 ENTRYPOINT,这只是个人喜好问题。