I have an image with multi-stage build for compiling some files and copy them into my final image.
I also set a volume between the directory of my app on the host machine and inside the container.
But when I start the container, the compiled files are not here. As I understand how volumes work, it makes perfect sense: the container replaces the content of his directory with the content of the directory on the host machine, where the compiled files are not generated as they are generated by the container when it is building.
But I am wondering if there is a way to keep the volume and have the compiled files in the container when it starts. I assume that I am doing it wrong.
To give you more info about my need, I want to compile .css
files from .scss
inside a nodejs image and I copy the compiled .css
to /app/<my_app>/static/css/
folder of my app docker image.
Here is my project's structure:
- 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
Here, when I build the container the css files do not exist yet, they are compiled, copied to the final image. When I start the image, as there is a volume between ./web/app:/app, the content of the image is replaced with the content in the host machine and so the .css files are missing.
Finally I have found a solution by myself, so I post the answer here hoping it will help someone else.
I abandoned the multi-stage build and try to create an image dedicated to scss compiling.
Here is the Dockerfile
of this image:
FROM node:alpine
WORKDIR /build
COPY package.json ./
RUN mkdir -p ./scss ./css
RUN npm install
CMD npm run scss
Note that I use the module node-sass for compiling scss in a nodejs environment.
For now, it just compiles files from scss/
and puts the output into css/
. But there is nothing in those folders yet.
I edit my docker-compose.yml
to run this new image at start and set two volumes from static folders of my app to scss/
and css/
folder in the container of this new image called scss
. So when web
will start, static/css
will be filled by this new service using files from static/scss
as source.
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
Finally, it works.
After running $ docker-compose up -d
, css files are here. The container of scss
image is not running as it is a one-shot command, not a proper service running, but you can run it again if you made some changes to your .scss
files and you want to compile .css
again.