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"]