Running gulp in Docker compose - does not create files - node.js

I have issues where gulp is not making any files. It says finished, but no file is being created.
If I log in to my docker instance using:
docker exec -t -i myservice-service /bin/bash
and if I run the gulp command, then it creates it properly
Then all the files defined in the gulpfile.js are created. In other words, public/dist/ is populated with the main.js and other css files.
This is my Dockerfile.
FROM node:9
RUN mkdir -p /usr/src/app
RUN mkdir -p /usr/src/logs
WORKDIR /usr/src/app
# GULP Installation
RUN npm install -g gulp
RUN npm install gulp
COPY package*.json /usr/src/app/
COPY .npmrc /usr/src/app/
RUN cd /usr/src/app/ && npm install && npm install -g nodemon
COPY . /usr/src/app
RUN chown -R node:node /usr/src/app && chown -R node:node /usr/src/logs
USER node
EXPOSE 3000
RUN gulp
CMD ["npm", "run-script", "start" ]
And this is my composer file (development):
version: "3"
services:
myservice-service:
build: .
image: myservice-service
container_name: myservice-service
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
environment:
- NODE_ENV=dev
ports:
- 3000:3000
command: nodemon --delay 2 ./bin/www
I run it as:
docker-compose -f docker-compose.development.yml up --build
When I run it like that, it does not create any files. I get the same output on the screen, when I run the command manually.
I have spent hours trying to make it work, I tried with setting permissions and what not, but it just does not work.
My expectation was to have public/dist/ populated with files.
Any help is appreciated.
UPDATE. It works, but I have doubts:
I manage to make it work by using command inside the composerfile itself.
So in my case:
command: bash -c "gulp && nodemon --delay 2 ./bin/www"
In my reasoning, gulp should be done inside the Dockerfile itself, not on the composer files. But then again, it is out of my scope of knowledge.

The Dockerfile is run at build time and will COPY all the files in your local directory into the container, then run gulp and create any files.
You then mount the local folder over the docker containers file system, pretty much overwriting what was done in the docker file with the original files, as gulp ran on the files in the container, it did not effect the original files so you are undoing the changes.
The solutions are either to do as as you have mentioned in your question (add it to the command in docker-compose.yml or run it via docker-compose exec) or write a custom entrypoint script that will run gulp and then the command, something like:
bin/entrypoint.sh
#!/bin/sh
gulp
exec "$#"
Dockerfile
FROM node:9
COPY bin/entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh
RUN mkdir -p /usr/src/app
RUN mkdir -p /usr/src/logs
WORKDIR /usr/src/app
# GULP Installation
RUN npm install -g gulp
RUN npm install gulp
COPY package*.json /usr/src/app/
COPY .npmrc /usr/src/app/
RUN cd /usr/src/app/ && npm install && npm install -g nodemon
COPY . /usr/src/app
RUN chown -R node:node /usr/src/app && chown -R node:node /usr/src/logs
USER node
EXPOSE 3000
ENTRYPOINT ["/entrypoint.sh"]
CMD ["npm", "run-script", "start" ]
This will make your build a little less predictable though as it will run gulp each time the container starts (e.g. after every deployment) if you use the same Dockerfile in dev and production.

Related

expo build:web docker cannot find correct entry point

NOOB to building an expo web app. I’m trying to build a docker container with my expo web app. After I run “expo build:web” and the build successfully finishes, I get a run error when I try to execute.
I have a custom entry point defined in my app.json: “entryPoint”: “./index.js”,
When I run the app in the docker container and connect to http://localhost:19006 I get:
./node_modules/expo/AppEntry.js:3
Module not found: Can't resolve '../../App'
I can see the entry point defined in the “asset-manifest.json” file. But I don’t know the steps to call that as my starting point and why it’s trying to use “../../App” instead.
Here is my Dockerfile if it helps:
FROM node:12.20.2 as build
ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV
ARG PORT=19006
ENV PORT $PORT
EXPOSE $PORT 19001 19002
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH /home/node/.npm-global/bin:$PATH
RUN npm i --unsafe-perm -g npm#latest expo-cli#latest sharp-cli
RUN mkdir /opt/web && chown node:node /opt/web
WORKDIR /opt/web
ENV PATH /opt/web/.bin:$PATH
USER node
COPY package.json ./
COPY .env.production ./.env
COPY ./private ./private
RUN yarn install --silent
RUN ls -al
WORKDIR /opt/web/app
COPY ./web-build .
RUN ls -al
ENTRYPOINT ["npm", "run"]
CMD ["web"]
I figured it out!
In my package.json file, I had the line:
"main": "node_modules/expo/AppEntry.js",
I changed it to:
"main": "index.js",
This worked in yarn start mode but not in production so I never gave it another look.
I also had to change the docker file a little by using "serve":
FROM node:12.20.2 as build
ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV
ARG PORT=19006
ENV PORT $PORT
EXPOSE $PORT 19001 19002
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH /home/node/.npm-global/bin:$PATH
RUN npm i --unsafe-perm -g npm#latest expo-cli#latest serve
RUN mkdir /opt/web && chown node:node /opt/web
WORKDIR /opt/web
ENV PATH /opt/web/.bin:$PATH
USER node
COPY package.json ./
COPY .env.production ./.env
COPY ./private ./private
RUN yarn install --silent
RUN ls -al
WORKDIR /opt/web/app
COPY ./web-build .
RUN ls -al
CMD ["serve","--no-port-switching","-p","19006"]

Can't build Node container with volume with package.json file to run npm install

How does Docker build containers? I can't figure it out. I want:
build a container
pass local folder in it
install npm in the container (using dockerfile) in the volume folder( so, I can see it on my local drive)
run a command in my yaml config file
I've tried to list content of folders with ls command, but the /src/ is always empty (prints: src)
My docker-compose.yml:
version: '3'
services:
node:
build:
context: .
dockerfile: Dockerfile.node
volumes:
- ./src:/src
command: run develop
tty: true
My Dockerfile.node:
FROM node:12
WORKDIR /src
COPY ./src/package*.json ./src/
RUN ls
RUN cd ./src
RUN ls
RUN npm install
RUN ls
On the RUN npm install command I got this error:
npm WARN saveError ENOENT: no such file or directory, open '/src/package.json'
I start project with command docker-compose up --build
My folder structure is:
/
src
--package.json
docker-compose.yml
Dockerfile.node
Please help, thank you in advance.
cd ./src only available in the current RUN command, as Dockerfile each command run in a separate shell, so when it comes to run npm install at this time your working is WORKDIR that is /src not the one you are expecting using cd .src which should be /src/src.
RUN pwd
#/src
RUN cd ./src #here /src/src
RUN ls
#/src <-- back to WORKDIR, while you are expecting /src/src
RUN npm install
In short, there is WORKDIR in dockerfile not cd.
You have to option, change command
RUN cd ./src && npm i
or change the copy command and leave the rest as it is.
COPY ./src/package*.json .

Use dockerfile to build npm project

I have Dockerfile like:
FROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
RUN npm run build
I need compiled files on my local drive not in docker container.
VOLUME looks like I need I think, but dunno how to do it, to make the build and share those build files.
can someone help me ? thanks!
Assuming npm run build in your Dockerfile produces a build directory, you can get it locally using a volume indeed
docker build -t <yourcontainername> .
docker run \
-v ${PWD}/build:/home/node/app/build \
-it <yourcontainername>
You can use
docker cp <containerId>:/file/path/within/container /host/path/target

Docker Compose gulp is not found in $PATH

I have just started learning docker-compose and I am using a nodejs image. I want to install gulp to create some tasks and have one of them working on the background.
When I run: docker-compose run --rm -d server gulp watch-less
I get this error: ERROR: oci runtime error: container_linux.go:247: starting container process caused "exec: \"gulp\": executable file not found in $PATH"
Here are my file:
# Dockerfile
FROM node:6.10.2
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install --quiet
COPY . /usr/src/app
CMD ["npm", "start"]
# docker-compose.yml
version: "2"
services:
server:
build: .
ports:
- "5000:5000"
volumes:
- ./:/usr/src/app
I also have a .dockerignore to ignore the node_modules folder and the npm-debug.log
EDIT:
When I run docker-compose run --rm server npm install package-name I don't have any problem and the package is installed.
Try adding gulp install in Dockerfile:
# Dockerfile
FROM node:6.10.2
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN npm install -g gulp
COPY package.json /usr/src/app
RUN npm install --quiet
COPY . /usr/src/app
CMD ["npm", "start"]
I have found a solution that works but maybe is not the best solution. I have created an script that runs a gulp task on the package.json and if I run:
docker-compose run --rm server npm run gulp_task it works and does what it has to do.
I find that just referencing gulp via
./node_modules/.bin/gulp
instead of directly works fine. ./node_modules/.bin isn't in the path by default. Another option would be to add that dir to the PATH.

Docker - Override content of linked volume

Having simple Node.js docker container
docker-compose.yml:
app:
build: ./dockerfiles/app
volumes:
- /Users/home/work/app:/usr/app
Dockerfile:
FROM node:6.7-slim
COPY package.json /tmp
RUN cd /tmp && npm install
RUN mkdir -p /usr/app
WORKDIR /usr/app
CMD ["node", "./src/app.js"]
What I want to achieve is container where I have package.json and installed node modules (npm install). Part where I copy package.json and install modules inside container is pretty straighforward, but problem occur, when I want to use these node_modules inside linked app. I can't find any way, how to copy /tmp/node_modules into /usr/app/node_modules
Is there any Docker way ho to do that? If not, can I tell my node app to look for node_modules somewhere else than in root directory?
You can achieve what you want by changing the CMD used when starting the container, either in your Dockerfile, or in the docker-compose.yml file.
Instead of just starting node ./src/app.js, you want to do two things:
Copy the node_modules over.
Start Node
Using the docker-compose.yml, I would do the following:
app:
build: ./dockerfiles/app
volumes:
- /Users/home/work/app:/usr/app
command: >
bash -c "
rm -rf /usr/app/node_modules
&& cp -R /tmp/node_modules /usr/app/node_modules
&& node ./src/app.js
"
This will delete the existing node modules on the mapped-in volume, then copy in the ones from container, and then finally starts the node app. This is going to happen every time the container is started.
As #schovi has mentioned in order to not override the contents of node_modules within the container and the contents of node_modules within the folder of the host machine, it is necessary to create another internal volume in the docker-compose.yml file:
volumes:
- ${APP_PATH}:/usr/app
- /usr/app/node_modules
Doing that makes it safe to copy the files from /tmp/node_modules into /usr/app/node_modules using this instructions.
FROM node
# Node modules
COPY *.json /tmp/
RUN cd /tmp && yarn
# App
RUN mkdir -p /usr/app
WORKDIR /usr/app
RUN cp -a /tmp/node_modules /usr/app/node_modules
ENV NODE_ENV docker
CMD ["run-node", "src/app.js"]
However, I would create first the app folder and install node_modules directly on it, reducing considerably the cache layers and increasing the building speed.
FROM node:12.8.1 #always mind the version
# Node modules
RUN mkdir -p /usr/app
WORKDIR /usr/app
#Mind that point (workdir)
COPY package*.json .
RUN yarn
ENV NODE_ENV docker
CMD ["run-node", "src/app.js"]
I hope it helps! :D
Thing that helped me is following usage of volumes
volumes:
- ${APP_PATH}:/usr/app
# Empty node_modules directory
- /usr/app/node_modules
Then in Dockerfile:
FROM node
# Node modules
COPY *.json /tmp/
RUN cd /tmp && yarn
ENV NODE_PATH /tmp/node_modules:${NODE_PATH}
# App
RUN mkdir -p /usr/app
WORKDIR /usr/app
ENV NODE_ENV docker
CMD ["run-node", "src/app.js"]
This allow me to have node_modules in another directory and app will look for them there.

Resources