Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Dockerfile that attempts to run the app as non-root user. This creates a `node` user & sets permissions on app files. Note you cannot `chown` files in a docker 'volume' during the build process, but you can at runtime (as part of your `CMD`) but in that case you can't use the `USER` command to change the UID before `CMD` runs.
# Node.js app Docker file
# Some basic build instructions:
# ```
# # you should delete node_modules b/c you don't want that copied during 'ADD'
# docker build -t thom-nic/node-bootstrap .
# # run a shell in the container to inspect the environment (as root):
# docker run --rm -itu root thom-nic/node-bootstrap /bin/bash
# ```
FROM dockerfile/nodejs
MAINTAINER Thom Nichols ""
RUN useradd -ms /bin/bash node
# copy the nice dotfiles that dockerfile/ubuntu gives us:
RUN cd && cp -R .bash_profile .bashrc .gitconfig .profile scripts /home/node
ADD . /home/node/app
RUN chown -R node:node /home/node
USER node
ENV HOME /home/node
WORKDIR /home/node/app
#ENV NODE_ENV production
RUN npm install
CMD ["npm", "start"]
Copy link

thom-nic commented Jun 18, 2014

To be clear, all commands appear to run fine (node user looks OK) however files in /data and /home/node are still all owned by root. chown doesn't appear to have any affect.

Copy link

thom-nic commented Jun 22, 2014

Above comment was for revision 1 of my Dockerfile. The latest revision correctly chowns app files.

Copy link

thom-nic commented Oct 30, 2014

Note that lines 22 and 23 mean the npm install call is run as the node user. I have bower installed as a local dependency (not -g) and use npm's postinstall hook to install bower assets:

relevant bits of my package.json

"devDependencies": {
    "bower": "~1.3",
    "grunt": "~0.4",
    "grunt-cli": "~0.1",
    "grunt-contrib-less": "~0.11",
    "grunt-contrib-uglify": "~0.5"
// others...
  "scripts": {
    "postinstall": "bower install && grunt assets"

This means I don't need extra npm install -g lines in the dockerfile.

Copy link

benbotto commented Feb 7, 2017

@thom-nic First off, thank you for the gist. I'm trying to accomplish something similar and stumbled across your SO post, and I wound up here.

It seems to me that one wouldn't want the files to be owned by the user that the application runs under (node in this case). As a hypothetical, let's say that part of the node application allows the user to upload files. Furthermore, assume that the upload code fails to properly sanitize the upload path, thereby allowing users to control the destination. If node owns the files, then a malicious user exploiting the upload vulnerability would be able to effectively overwrite application code. This scenario is a common attack vector.

If you consider webservers like apache and nginx, for the very reason outlined above you wouldn't want the application files to be owned by the same user as the webserver runs under, right? (e.g. granting ownership of php files to www-user is a security issue.) In the Dockerfile, it therefore seems like root should own the files, and the node user should run the application.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment