容器内文件系统的更改未反映在Docker卷中的主机上

时间:2019-04-27 21:02:09

标签: docker docker-compose

我正在使用TypeScript编写的Express服务器。项目的流程是,我有一个npm build脚本,该脚本将项目文件保存在src文件夹中,并将其编译到dist文件夹中。这两个文件夹都位于根目录下。该项目有效,但是尽管尝试将所有内容移至docker,尽管我正在安装卷并且容器中存在构建文件(dist目录),但更改未反映在主机上。 (我将Windows + VirtualBox用于Docker)

我提到了thisthis问题。我看到他们的情况是相同的,但是他们的解决方案似乎对我不起作用。我确保我使用的是答案中提到的类似技术,但它们似乎没有用。

项目的目录结构:

├── Backend
│   ├── src/
│   │   ├── controllers/
│   │   ├── models/
│   │   ├── routes/
│   │   ├── services/
│   │   ├── index.ts
│   │   └── server.ts
│   ├── dist/ (Created upon compilation)
│   │   ├── controllers/
│   │   ├── data/ (Created upon starting the server)
│   │   ├── models/
│   │   ├── routes/
│   │   ├── services/
│   │   ├── index.js
│   │   └── server.js
│   ├── Dockerfile
│   ├── package.json
│   ├── tsconfig.json
│   ├── tslint.json
│   └── .env
├── Frontend/ (This part is an independent application)
├── docker-compose.yml
└── README.md

服务器启动时,会在%proj_root%/Backend/dist中创建一个名为data的目录,该目录用于通过txt文件向应用程序提供输入。从我在Dockerfile中输入的ls命令可以明显看出,编译工作正常,但是容器内部所做的更改(dist目录的创建)未反映在主机上。在主机上,dist目录为空,因为没有server.js文件,导致服务器崩溃。

这是我的docker-compose.yml:

version: "3"
services:
  backend:
    build:
      context: ./Backend/
    volumes:
      - ./Backend/dist:/app/dist
      - /app/node_modules
      - ./Backend:/app
  frontend:
    build:
      context: ./Frontend
    ports:
      - "3001:8080"
    volumes:
      - /app/node_modules
      - ./Frontend:/app

这是用于后端服务的Dockerfile:

FROM node:8
WORKDIR /app
COPY ./package.json .
RUN npm install
COPY . . # Copying everything to enable standalone usage
RUN ls # Logging before tsc build
RUN npm run build
RUN ls /app/dist # Logging after tsc build. All the built files are visible.
CMD ["npm", "run", "start"]

运行docker-compose up后,应在容器(/app/dist)中创建一个dist文件夹,并在主机上以%proj_root%/Backend/dist的形式反映出来

我知道我可以创建一个脚本来编译TS,然后运行docker-compose,但这对我来说似乎是一种骇人听闻的方法。有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

您显示的docker-compose.yml设置有两个独立的作用。首先,它使用您单独提供的Dockerfile构建Docker映像。其次,它获取该映像,装入卷并应用其他设置,并根据这些设置运行容器。 Docker映像构建序列会忽略所有其他设置;您在Dockerfile中所做的任何操作都无法更改主机系统上的文件。

运行容器时,volumes:设置中的任何内容都将完全替换,该图像中的内容将完全传递。这始终是单向“推入容器”的方式:主机的Backend目录的内容替换容器中的/app;匿名卷的内容替换其node_modules,而主机的list目录的内容替换/app/dist

对此有一个特殊情况例外。启动容器时,如果卷安装为空,则映像中的内容将复制到卷中。仅当卷树中完全没有任何东西时,才会发生这种情况。如果dist主机目录或node_modules匿名卷中已有内容,则它将替换映像中的内容,即使映像中已更改(或更改了该卷中的内容),Docker也无法告诉)。

作为一种一次性的解决方法,如果您

rm -rf dist

然后,下次启动容器时,Docker将注意到dist目录为空,并从映像中重新填充它。

我建议只完全删除这些volumes:设置。如果您正在积极开发软件,请在主机上进行操作:使用典型的OS软件包管理器可以很容易地安装Node,将Node解释器隐藏在容器中不会混淆您的IDE,并且您不会点击这类问题。在进行部署时,您可以按原样使用Docker映像,而无需单独分发映像内的代码。

答案 1 :(得分:0)

TLDR;
挂载目录而不是挂载文件!

我正在使用docker-compose,这个简单的article帮助我解决了这个问题。