I am currently trying to build a complete website using docker compose, with a frontend (Vue), a backend (Nest), and a db (Postgresql). I would like to keep the same code for dev and prod purposes by using Docker's multi-stage builds, but still bind volumes to make dev easier.
My problem is for Vue. I need the volume to be bound for dev purpose, thus I need to use CMD [...] instruction to get the files "synced" on dev stage, thus not letting me add a second stage for serving using nginx or stuff like that when I'm running a build. Here is an example of what I would like to be able to make work.
# Dev / Build stage
FROM bitnami/node:18 as first-stage
RUN echo "{ <all my env vars> }" > .env.json && \
mkdir -p /secrets && \
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /secrets/key.pem -out /secrets/cert.pem -subj "<subject>" && \
chown 1000:1000 /secrets/key.pem && \
chown 1000:1000 /secrets/cert.pem && \
yarn install --ignore-engines
# Here is the problem, I get my volume mounted in /app from docker-compose, but I can't
# access it from the container using `RUN` because when mounting the volume,
# the container's volume content is wiped out and replaced by host's volume content (am I right ?)
# Using `CMD` to get the volume mounted and synced prevents me from having a
# second stage in my Dockerfile, so this option is unsuccessful too
# VUE_PHASE can be "serve" for dev purpose or "build" for prod, depends on env variable provided by compose
RUN yarn run ${VUE_PHASE}
# This phase should be synced with host's volume, and should "never end" in dev
# environment (vue-cli serve has supposedly no end) (I am aware that if serving ends
# unexpectedly, nginx will start building, but I do not know how to shutdown
# the container here if in serving stage)
# Serving stage
FROM bitnami/nginx:1.23 as serving-stage
COPY --from=first-stage /app/dist /app
# [ ... ] Other nginx related stuff
I tried to use a second container for nginx, but it seems odd to me as multi-stage build are a good option. By the way when I add my nginx container and make it depend on vue container, my compose logs in console are not shown until nginx container starts, seems a bit weird (and problematic when in dev phase because no log is shown)
Here is a part of my docker compose file
version: '3'
networks:
n_backend:
driver: bridge
name: n_backend
n_frontend:
driver: bridge
name: n_frontend
services:
# [ ... ] nest and postgresql containers
s_vuejs:
build:
context: ./website/frontend/vuejs/
image: 's_vuejs'
networks:
- n_backend
- n_frontend
ports:
- "${FRONTEND_EXPOSED_HTTP}:${FRONTEND_PORT_HTTP}"
- "${FRONTEND_EXPOSED_HTTPS}:${FRONTEND_PORT_HTTPS}"
volumes:
- ./website/frontend/vuejs/bind:/app
restart: "no"
environment:
# [ ... ]
# Below is the "second container option"
s_nginx_frontend:
build:
context: ./website/frontend/nginx/
image: 's_nginx'
networks:
- n_frontend
ports:
- "${FRONTEND_EXPOSED_HTTP}:${NGINX_PORT_HTTP}"
- "${FRONTEND_EXPOSED_HTTPS}:${NGINX_PORT_HTTPS}"
volumes:
- ./website/frontend/vuejs/bind/dist:/app
- ./website/frontend/nginx/my_server_block.conf:/opt/bitnami/nginx/conf/server_blocks/my_server_block.conf:ro
restart: unless-stopped
# If I do not add the `depends_on` directive, logs are ok, if I do, they wait until nginx starts
depends_on:
s_vuejs:
condition: service_completed_successfully
Thank y'all !
EDIT: I have been able to make the "second container option" work using docker compose profiles, enabling nginx's container with a prod profile, but I think this is still not optimal...