Home > Blockchain >  What should I change in this Dockerfile to differentiate host and container user permissions?
What should I change in this Dockerfile to differentiate host and container user permissions?

Time:01-09

With the aim of avoiding root user running in the container, I've got the following Dockerfile:

FROM public.ecr.aws/docker/library/node:14-alpine AS deps

RUN apk add --no-cache libc6-compat curl \
 && addgroup --system --gid 1001 app_user \
 && adduser --system --uid 1001 app_user

RUN mkdir /app \
  && chown -R app_user:app_user /app
USER app_user
WORKDIR /app

COPY --chown=app_user:app_user package*.json yarn.lock ./
RUN yarn install --production=false --pure-lockfile --ignore-engines

FROM public.ecr.aws/docker/library/node:14-alpine AS builder
WORKDIR /app

COPY --chown=app_user:app_user components pages public queries styles lib @types ./
COPY --chown=app_user:app_user tsconfig.json constants.js next.config.js .babelrc ./
COPY --chown=app_user:app_user scripts/cache/ ./scripts/cache

COPY --chown=app_user:app_user --from=deps /usr/src/app/package.json ./
COPY --chown=app_user:app_user --from=deps /usr/src/app/node_modules ./node_modules

ENV CACHE_REFRESH_SECRET_TOKEN=$CACHE_REFRESH_SECRET_TOKEN

RUN CODEBUILD_BUILD_ID=$CODEBUILD_BUILD_ID DEBUG=graphql:errors,graphql:queries,cache:redis DEBUG_COLORS=true npm run build

EXPOSE 8080 6379
ENTRYPOINT [ "npm", "start"]

Line COPY --chown=app_user:app_user package*.json yarn.lock ./ won't fail, but once reaching the line COPY --chown=app_user:app_user components pages public queries styles lib @types ./ it'll err out with the following message:

unable to convert uid/gid chown string to host mapping: can't find uid for user app_user: no such user: app_user

I'm a bit strange as I think I'm following directions from docs and multiple guides. What should be corrected?

CodePudding user response:

In multistage of docker build you can not re-use the same user so in each FROM you must re-create it.

I made the changes in lines 17 to 23

  1 FROM public.ecr.aws/docker/library/node:14-alpine AS deps
  2 
  3 RUN apk add --no-cache libc6-compat curl \
  4  && addgroup --system --gid 1001 app_user \
  5  && adduser --system --uid 1001 app_user
  6 
  7 RUN mkdir /app \
  8   && chown -R app_user:app_user /app
  9 USER app_user
 10 WORKDIR /app
 11 
 12 COPY --chown=app_user:app_user package*.json yarn.lock ./
 13 RUN yarn install --production=false --pure-lockfile --ignore-engines
 14 
 15 FROM public.ecr.aws/docker/library/node:14-alpine AS builder
 16 
 17 RUN apk add --no-cache libc6-compat curl \
 18  && addgroup --system --gid 1001 app_user \
 19  && adduser --system --uid 1001 app_user
 20 
 21 RUN mkdir /app \
 22   && chown -R app_user:app_user /app
 23 USER app_user
 24 WORKDIR /app
 25 
 26 ARG NODE_ENV=production
 27 ARG CODEBUILD_RESOLVED_SOURCE_VERSION
 28 ARG CODEBUILD_BUILD_ID
 29 ARG CODEBUILD_BUILD_NUMBER
 30 ARG CODEBUILD_START_TIME
 31 ARG ELASTIC_CACHE_NODE_ADDRESS
 32 ARG CONTENTFUL_SPACE_ID
 33 ARG CONTENTFUL_ENVIRONMENT_ID
 34 ARG CONTENTFUL_DELIVERY_TOKEN
 35 ARG CONTENTFUL_PREVIEW_TOKEN
 36 ARG PREVIEW_MODE_SECRET_TOKEN
 37 ARG BUILD_TRIGGER_SECRET_TOKEN
 38 ARG CACHE_REFRESH_SECRET_TOKEN
 39 ARG BUILD_RSS_SECRET_TOKEN
 40 
 41 ARG NEXT_PUBLIC_ALGOLIA_APPLICATION_ID
 42 ARG NEXT_PUBLIC_ALGOLIA_INDEX_NAME
 43 ARG NEXT_PUBLIC_ALGOLIA_SEARCH_KEY
 44 ARG ALGOLIA_INDEXING_SECRET_TOKEN
 45 
 46 ARG CSP_REPORT_URI
 47 ARG CSP_ENABLED
 48 
 49 ARG POSTS_CSV_SECRET_TOKEN
 50 
 51 ENV CODEBUILD_RESOLVED_SOURCE_VERSION=$CODEBUILD_RESOLVED_SOURCE_VERSION
 52 ENV CODEBUILD_BUILD_ID=$CODEBUILD_BUILD_ID
 53 ENV ELASTIC_CACHE_NODE_ADDRESS=$ELASTIC_CACHE_NODE_ADDRESS
 54 ENV CONTENTFUL_SPACE_ID=$CONTENTFUL_SPACE_ID
 55 ENV CONTENTFUL_ENVIRONMENT_ID=$CONTENTFUL_ENVIRONMENT_ID
 56 ENV CONTENTFUL_DELIVERY_TOKEN=$CONTENTFUL_DELIVERY_TOKEN
 57 ENV CONTENTFUL_PREVIEW_TOKEN=$CONTENTFUL_PREVIEW_TOKEN
 58 ENV PREVIEW_MODE_SECRET_TOKEN=$PREVIEW_MODE_SECRET_TOKEN
 59 ENV BUILD_TRIGGER_SECRET_TOKEN=$BUILD_TRIGGER_SECRET_TOKEN
 60 ENV BUILD_RSS_SECRET_TOKEN=$BUILD_RSS_SECRET_TOKEN
 61 
 62 ENV CSP_REPORT_URI=$CSP_REPORT_URI
 63 ENV CSP_ENABLED=$CSP_ENABLED
 64 
 65 ENV NEXT_PUBLIC_ALGOLIA_APPLICATION_ID=$NEXT_PUBLIC_ALGOLIA_APPLICATION_ID
 66 ENV NEXT_PUBLIC_ALGOLIA_INDEX_NAME=$NEXT_PUBLIC_ALGOLIA_INDEX_NAME
 67 ENV NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=$NEXT_PUBLIC_ALGOLIA_SEARCH_KEY
 68 ENV ALGOLIA_INDEXING_SECRET_TOKEN=$ALGOLIA_INDEXING_SECRET_TOKEN
 69 
 70 ENV POSTS_CSV_SECRET_TOKEN=$POSTS_CSV_SECRET_TOKEN
 71 
 72 ENV NEXT_PUBLIC_CODEBUILD_RESOLVED_SOURCE_VERSION=$CODEBUILD_RESOLVED_SOURCE_VERSION
 73 ENV NEXT_PUBLIC_CODEBUILD_BUILD_ID=$CODEBUILD_BUILD_ID
 74 ENV NEXT_PUBLIC_CTF_ENVIRONMENT_ID=$CONTENTFUL_ENVIRONMENT_ID
 75 ENV NEXT_PUBLIC_CODEBUILD_BUILD_NUMBER=$CODEBUILD_BUILD_NUMBER
 76 ENV NEXT_PUBLIC_CODEBUILD_START_TIME=$CODEBUILD_START_TIME
 77 
 78 COPY --chown=app_user:app_user components pages public queries styles lib @types ./
 79 COPY --chown=app_user:app_user tsconfig.json constants.js next.config.js .babelrc ./
 80 COPY --chown=app_user:app_user scripts/cache/ ./scripts/cache
 81 
 82 COPY --chown=app_user:app_user --from=deps /usr/src/app/package.json ./
 83 COPY --chown=app_user:app_user --from=deps /usr/src/app/node_modules ./node_modules
 84 
 85 ENV CACHE_REFRESH_SECRET_TOKEN=$CACHE_REFRESH_SECRET_TOKEN
 86 
 87 RUN CODEBUILD_BUILD_ID=$CODEBUILD_BUILD_ID DEBUG=graphql:errors,graphql:queries,cache:redis DEBUG_COLORS=true npm run build
 88 
 89 EXPOSE 8080 6379
 90 ENTRYPOINT [ "npm", "start"]

CodePudding user response:

There's no particular requirement that the (non-root) user running the container be the same user that owns the files. It can be a minor security improvement to have the source code owned by root and not world-writable, which will prevent the application from doing things like overwriting its own static images (intentionally or otherwise).

One straightforward approach is to do all of the package installation and building as root in the Dockerfile, and only switch to the non-root user at the very end of the Dockerfile.

FROM public.ecr.aws/docker/library/node:14-alpine AS deps

# Doing the `yarn install` step as root, so no need to create a user here
RUN apk add --no-cache libc6-compat curl

WORKDIR /app
COPY package*.json yarn.lock ./
RUN yarn install --production=false --pure-lockfile --ignore-engines

FROM public.ecr.aws/docker/library/node:14-alpine AS builder

# Create the non-root user, without a specific uid; do not switch yet
RUN adduser --system app_user

# Do the rest of the installation steps, still as root
WORKDIR /app
COPY components pages public queries styles lib @types ./
COPY tsconfig.json constants.js next.config.js .babelrc ./
COPY scripts/cache/ ./scripts/cache

COPY --from=deps /app/package.json /app/yarn.lock ./
COPY --from=deps app/node_modules ./node_modules

RUN yarn build

# As part of the runtime setup, switch to the non-root user now
EXPOSE 8080
USER app_user
CMD ["yarn", "start"]
  • Related