WIth a custom PATH, globally installed modules do not work.
Full docker file
# specify the node base image with your desired version node:<version>
FROM node:8.9.3-alpine
# replace this with your application's default port
EXPOSE 5000
RUN mkdir /home/node/.npm-global
RUN npm config set prefix "/home/node/.npm-global"
RUN PATH=/home/node/.npm-global/bin:$PATH
# Tini the "zombie reaper" is now available at /sbin/tini
# Whatever you put in the CMD [] section is what Tini will run as its default args
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
# Install app dependencies
COPY . /home/node/app/
# BACKEND - Install global packages, local packages and build the app.
# This command is continued from the previous line due to the `\`
RUN cd /home/node/app/backend-nodejs \
&& npm run install:docker \
&& npm run build:production
# FRONTEND - Install local packages and build the app.
RUN cd /home/node/app/frontend \
&& npm run install:globals:production \ <--- this installs `npm-run-all` globally which exposes `run-s`
&& npm run install:packages \
&& npm run build:production:aot;
# Run your program under Tini
# Start the app
CMD ["home/node/app/backend-nodejs/node_modules/.bin/cross-env", "NODE_ENV=localhost", "node", "home/node/app/build/server.js"]
# At the end, set the user to use when running this image
USER node
If I remove
RUN mkdir /home/node/.npm-global
RUN npm config set prefix "/home/node/.npm-global"
RUN PATH=/home/node/.npm-global/bin:$PATH
Then run-s becomes available. So how do we change the PATH?
Does it work if you replace this
RUN PATH=/home/node/.npm-global/bin:$PATH
With this?
ENV PATH="=/home/node/.npm-global/bin:${PATH}"
Ideally, your dockerfile would be reorganized to have all the commands that need to run as root on top, then add the USER directive and then do you npm install etc... Running the mkdir as root can create permission troubles.
Alright, so I tried both of your suggestions
#########################################################
# These first commands are all run under the `root` user
#########################################################
# specify the node base image with your desired version node:<version>
FROM node:8.9.3-alpine
# replace this with your application's default port
EXPOSE 5000
# Install Tini and Git
RUN apk add --no-cache tini git
# Tini the "zombie reaper" is now available at /sbin/tini
# Whatever you put in the CMD [] section is what Tini will run as its default args
ENTRYPOINT ["/sbin/tini", "--"]
# Run your program under Tini
# Start the app
CMD ["home/node/app/backend-nodejs/node_modules/.bin/cross-env", "NODE_ENV=localhost", "node", "home/node/app/build/server.js"]
#########################################################
# NOW, the following commands are run under the `node` user
#########################################################
USER node
RUN mkdir /home/node/.npm-global
RUN npm config set prefix "/home/node/.npm-global"
#RUN PATH=/home/node/.npm-global/bin:$PATH
ENV PATH="=/home/node/.npm-global/bin:${PATH}"
# Install app dependencies
COPY . /home/node/app/
# Install global packages, then local packages on frontend, then local packages on backend-nodejs, then build frontend, then build backend.
# This command is continued from the previous line due to the `\`.
RUN cd /home/node/app/frontend \
&& npm run docker:install
And I still got
> npm install npm-run-all echo-cli cross-env node-gyp typescript -g --no-optional --depth 0
/home/node/.npm-global/bin/cross-env -> /home/node/.npm-global/lib/node_modules/cross-env/dist/bin/cross-env.js
/home/node/.npm-global/bin/cross-env-shell -> /home/node/.npm-global/lib/node_modules/cross-env/dist/bin/cross-env-shell.js
/home/node/.npm-global/bin/echo-cli -> /home/node/.npm-global/lib/node_modules/echo-cli/dist/index.js
/home/node/.npm-global/bin/node-gyp -> /home/node/.npm-global/lib/node_modules/node-gyp/bin/node-gyp.js
/home/node/.npm-global/bin/run-p -> /home/node/.npm-global/lib/node_modules/npm-run-all/bin/run-p/index.js
/home/node/.npm-global/bin/run-s -> /home/node/.npm-global/lib/node_modules/npm-run-all/bin/run-s/index.js
/home/node/.npm-global/bin/npm-run-all -> /home/node/.npm-global/lib/node_modules/npm-run-all/bin/npm-run-all/index.js
/home/node/.npm-global/bin/tsc -> /home/node/.npm-global/lib/node_modules/typescript/bin/tsc
/home/node/.npm-global/bin/tsserver -> /home/node/.npm-global/lib/node_modules/typescript/bin/tsserver
+ [email protected]
+ [email protected]
+ [email protected]
+ [email protected]
+ [email protected]
added 220 packages in 7.891s
sh: run-s: not found
npm ERR! file sh
npm ERR! code ELIFECYCLE
By the way, did I organize I properly? Should the COPY command be under root or node?
Ah, I think there was a typo in my example (extra "=")
Try
ENV PATH="/home/node/.npm-global/bin:${PATH}"
hey, good job, that worked!! I was wondering about that =. run-s works fine now in my home directory.
But now I get another issue.
> npm install --quiet --depth 0
npm WARN checkPermissions Missing write access to /home/node/app/frontend
npm ERR! path /home/node/app/frontend
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall acces
So it appears that my node user can't write into its own home directory?
#########################################################
# These first commands are all run under the `root` user
#########################################################
# specify the node base image with your desired version node:<version>
FROM node:8.9.3-alpine
# replace this with your application's default port
EXPOSE 5000
# Install Tini and Git
RUN apk add --no-cache tini git
# Tini the "zombie reaper" is now available at /sbin/tini
# Whatever you put in the CMD [] section is what Tini will run as its default args
ENTRYPOINT ["/sbin/tini", "--"]
# Run your program under Tini
# Start the app
CMD ["home/node/app/backend-nodejs/node_modules/.bin/cross-env", "NODE_ENV=localhost", "node", "home/node/app/build/server.js"]
#########################################################
# NOW, the following commands are run under the `node` user
#########################################################
USER node
RUN mkdir /home/node/.npm-global
RUN npm config set prefix "/home/node/.npm-global"
ENV PATH="/home/node/.npm-global/bin:${PATH}"
# Install app dependencies
COPY . /home/node/app/
# Install global packages, then local packages on frontend, then local packages on backend-nodejs, then build frontend, then build backend.
# This command is continued from the previous line due to the `\`.
RUN cd /home/node/app/frontend \
&& npm run docker:install
Everything works fine if I don't use the custom global prefig and install path. Is there really a good benefit for doing this?
I got it working. I had to tell root to chown the directory over to node so node could work with the files
#########################################################
# These first commands are all run under the `root` user
#########################################################
# specify the node base image with your desired version node:<version>
FROM node:8.9.3-alpine
# replace this with your application's default port
EXPOSE 80
# Install Binary dependencies
RUN apk add --no-cache tini git python make gcc g++
# Tini the "zombie reaper" is now available at /sbin/tini
# Whatever you put in the CMD [] section is what Tini will run as its default args
ENTRYPOINT ["/sbin/tini", "--"]
# Run your program under Tini
# Start the app
CMD ["/home/node/app/backend-nodejs/node_modules/.bin/cross-env", "NODE_ENV=localhost", "node", "/home/node/app/build/server.js"]
# Install app dependencies
COPY . /home/node/app/
# Fix permissions so user Node can work with files
RUN chown -R node:node /home/node/app
#########################################################
# NOW, the following commands are run under the `node` user
#########################################################
USER node
# Set NPM global install path into home directory so permissions are correct
RUN mkdir /home/node/.npm-global
RUN npm config set prefix "/home/node/.npm-global"
ENV PATH="/home/node/.npm-global/bin:${PATH}"
# Install global packages, then local packages on frontend, then local packages on backend-nodejs, then build frontend, then build backend.
WORKDIR /home/node/app/frontend
RUN npm run docker:install
WORKDIR /home/node/app/
Thanks for the help guys.
It's weird that you would need this line: RUN chown -R node:node /home/node/app
@IAMtheIAM if you move your USER command before the COPY command you wouldn't need to use RUN chown
if you move your USER command before the COPY command you wouldn't need to use RUN chown
You also need COPY --chown, which is only available in docker v17.0.9.0-ce or higher.
COPY-chown is the best work-around that covers most docker versions.
There was a reason why I put the COPY before the USER commands, to get the build working right. I'll have to look again but either way it works :-D
Most helpful comment
Does it work if you replace this
With this?