问题描述
我有一个具有多阶段构建的图像,用于编译一些文件并将其复制到我的最终图像中。
我还在主机上的应用程序目录和容器内部之间设置了一个卷。
但是当我启动容器时,编译后的文件不在这里。据我了解,卷是如何工作的,这是非常有意义的:容器将其目录的内容替换为主机上目录的内容,在该主机上,不会生成已编译的文件,因为它们是在容器构建时生成的。
但是我想知道是否有一种方法可以在启动时保留卷并在容器中保存编译的文件。我以为我做错了。
为了向您提供有关我的需求的更多信息,我想从一个nodejs图像中的.css
编译.scss
个文件,然后将已编译的.css
复制到以下文件夹中的/app/<my_app>/static/css/
我的应用docker图片。
这是我项目的结构:
- docker-compose.yml
- production.env
- web/
- - Dockerfile
- - build/
- - - scss/
- - app/
- - - <my_app>/
- - - - static/
- - - - - css/
docker-compose.yml
version: '3'
services:
web:
build: web/
ports:
- "5000:5000"
env_file:
- ./production.env
volumes:
- ./web/app:/app
Dockerfile
FROM node:alpine as builder
workdir /build
copY build/ .
RUN npm install && mkdir -p css
RUN npm run scss # Compile .scss files to .css into /build/css/ folder
FROM python:alpine
workdir /app
copY app/ .
copY --from=builder /build/css ./<my_app>/static/css
/* ... Some instructions ... */
CMD flask run
在这里,当我构建容器时,css文件尚不存在,它们会被编译并复制到最终映像中。启动映像时,由于./web/app:/app之间存在一个卷,因此映像的内容将替换为主机中的内容,因此缺少.css文件。
解决方法
卷安装仅在运行时发生; Dockerfile
构建完成之后。
在构建容器映像时,不会将卷安装应用于容器映像。
例如WORKDIR /app
中的Dockerfile
假定在/app
构建步骤中,随着图像的建立,存在(或创建)python:alpine
。看来这是在Dockerfile
中创建为空的,而随后的COPY /app .
没有任何作用。
在构建映像之后以及用于创建容器时,将应用/app
卷装载。
最后,我自己找到了一个解决方案,所以我在此处发布答案,希望对其他人有所帮助。
我放弃了多阶段构建,并尝试创建专用于scss编译的映像。
这是此图片的Dockerfile
:
FROM node:alpine
WORKDIR /build
COPY package.json ./
RUN mkdir -p ./scss ./css
RUN npm install
CMD npm run scss
请注意,我使用node-sass模块在nodejs环境中编译scss。
现在,它仅编译来自scss/
的文件,并将输出放入css/
。但是这些文件夹中什么都没有。
我编辑docker-compose.yml
以在开始时运行此新映像,并将应用程序的静态文件夹中的两个卷设置为名为{的新映像的容器中的scss/
和css/
文件夹{1}}。因此,scss
将开始运行时,此新服务将使用web
中的文件作为源来填充static/css
。
static/scss
最后,它可行。
运行version: '3'
services:
web:
build: web/
ports:
- "5000:5000"
depends_on:
- scss
env_file:
- ./production.env
volumes:
- ./web/app:/app
scss:
build: scss/
env_file:
- ./production.env
volumes:
- ./web/app/<my_app>/static/css:/build/css
- ./web/app/<my_app>/static/scss:/build/scss
之后,css文件就在这里。 $ docker-compose up -d
映像的容器未运行,因为它是单次命令,而不是正确的服务,但是如果您对scss
文件进行了一些更改并且您想要再次编译.scss
。