Warm tip: This article is reproduced from serverfault.com, please click

Setup different user permissions on files copied in Dockerfile

发布于 2020-12-10 07:37:59

I have this Dockerfile setup:

FROM node:14.5-buster-slim AS base
WORKDIR /app


FROM base AS production
ENV NODE_ENV=production

RUN chown -R node:node /app
RUN chmod 755 /app
USER node
... other copies
COPY ./scripts/startup-production.sh ./
COPY ./scripts/healthz.sh ./

CMD ["./startup-production.sh"]

The problem I'm facing is that I can't execute ./healthz.sh because it's only executable by the node user. When I commented out the two RUN and the USER commands, I could execute the file just fine. But I want to enforce the executable permissions only to the node for security reasons.

I need the ./healthz.sh to be externally executable by Kubernetes' liveness & rediness probes.

How can I make it so? Folder restructuring or stuff like that are fine with me.

Questioner
Milkncookiez
Viewed
0
David Maze 2020-12-10 19:33:30

In most cases, you probably want your code to be owned by root, but to be world-readable, and for scripts be world-executable. The Dockerfile COPY directive will copy in a file with its existing permissions from the host system (hidden in the list of bullet points at the end is a note that a file "is copied individually along with its metadata"). So the easiest way to approach this is to make sure the script has the right permissions on the host system:

# mode 0755 is readable and executable by everyone but only writable by owner
chmod 0755 healthz.sh
git commit -am 'make healthz script executable'

Then you can just COPY it in, without any special setup.

# Do not RUN chown or chmod; just
WORKDIR /app
COPY ./scripts/healthz.sh .

# Then when launching the container, specify
USER node
CMD ["./startup-production.sh"]

You should be able to verify this locally by running your container and manually invoking the health-check script

docker run -d --name app the-image
# possibly with a `docker exec -u` option to specify a different user
docker exec app /app/healthz.sh && echo OK

The important thing to check is that the file is world-executable. You can also double-check this by looking at the built container

docker run --rm the-image ls -l /app/healthz.sh

That should print out one line, starting with a permission string -rwxr-xr-x; the last three r-x are the important part. If you can't get the permissions right another way, you can also fix them up in your image build

COPY ./scripts/healthz.sh .
# If you can't make the permissions on the original file right:
RUN chmod 0755 *.sh