I am trying to compile my assets using Docker for a Laravel project.
So, I have created a service called npm which is built from the following Dockerfile:
FROM node:16-alpine as node
WORKDIR /usr/src
ADD ./resources ./resources
COPY ["package.json", "package-lock.json", "vite.config.js", "./"]
RUN npm install --global cross-env
RUN npm install
RUN npm run build
Also, I am using the following Docker-compose configuration
node:
build:
context: ./
dockerfile: ./services/nodejs/Dockerfile
working_dir: /var/www
container_name: "nodejs"
volumes:
- ./:/var/www
tty: true
depends_on:
- php
Although the service is built successfully, it seems that my host directory (which is non-empty) is overriding the content of my node container. So, eventually I end up with no "node_modules" directory and my compiled assets and resources get lost.
So, what should I do? I think that I can first copy the content of my host folder to the container, then delete the content of my host folder, and then run my scripts and then copy it back. But that seems to be a very time consuming thing to do. What is the best practice for cases like this? I'm sure I'm not the first one that has dockerized a full-stack Laravel project. Thanks in advance
CodePudding user response:
It doesn't look like you COPY
your application code into the container. That leaves you in a position where you need to bind-mount things in, but since the host directory is missing some built parts, the final container image is incomplete.
There's an especially important detail here around using this container as part of your build sequence which I'll get back to.
The first thing to do is to make sure all of the things you need are in the image itself.
FROM node:16-alpine as node
WORKDIR /usr/src
RUN npm install --global cross-env
# run `npm install` first to avoid rebuilds if `package.json` is unchanged
COPY ["package.json", "package-lock.json", "vite.config.js", "./"]
RUN npm install
# then copy in the rest of the application
# (make sure `node_modules` and `build` are in `.dockerignore`)
COPY ./ ./
RUN npm run build
# and explain how to run the container (*)
CMD npm run start
Then in your docker-compose.yml
file, you don't need to specify volumes:
because the code is already in your image. You similarly don't need to declare a working_dir:
because the Dockerfile sets WORKDIR
already. This section of your Compose file can probably be trimmed down to
node:
build:
context: ./
dockerfile: ./services/nodejs/Dockerfile
tty: true # actually needed?
depends_on:
- php
I don't think you actually want this container, though, since
I am trying to compile my assets using Docker for a Laravel project.
In this case you can use this Dockerfile (and it must be the complete self-contained Dockerfile) as part of a multi-stage build. Put this Dockerfile at the start of your PHP application Dockerfile and give it a name, and then you can COPY
the built assets from one stage to another.
FROM node:16-alpine AS node # <-- `AS somename` is important
...
RUN npm run build
# no specific need for a CMD here
FROM php:fpm
...
COPY --from=node /usr/src/build ./static/
Again, since this will get filled in at Docker image build time, it's important to not overwrite the image content with a volumes:
mount.
If you do this then there's not a "Node container" at all, and you can just outright remove this from your docker-compose.yml
file. For this setup you don't need a long-running server, you just need to have Node available to run a compilation step at build time, and including it in a Dockerfile stage is enough for that.