FROM <you nodejs image> AS node_base
WORKDIR /application
USER node
FROM node_base AS node_modules_prod
COPY --chown=node:node package.json .yarnrc yarn.lock ./
RUN --mount=type=secret,id=npm_token,target=/run/secrets/npm_token,uid=10064,gid=10064 \
--mount=type=cache,sharing=locked,target=/home/node/.cache/yarn,id=yarn_cache,uid=10064,gid=10064 \
--mount=type=tmpfs,target=/tmp/ \
export NPM_TOKEN=`cat /run/secrets/npm_token` && \
yarn install --frozen-lockfile --non-interactive --no-progress --prod
FROM node_modules_prod AS node_modules_dev
RUN --mount=type=secret,id=npm_token,target=/run/secrets/npm_token,uid=10064,gid=10064 \
--mount=type=cache,sharing=locked,target=/home/node/.cache/yarn,id=yarn_cache,uid=10064,gid=10064 \
--mount=type=tmpfs,target=/tmp/ \
export NPM_TOKEN=`cat /run/secrets/npm_token` && \
yarn install --frozen-lockfile --non-interactive --no-progress
FROM node_modules_dev AS build
COPY --chown=node:node ./ ./
RUN --mount=type=secret,id=npm_token,target=/run/secrets/npm_token,uid=10064,gid=10064 \
--mount=type=cache,sharing=locked,target=/home/node/.cache/yarn,id=yarn_cache,uid=10064,gid=10064 \
--mount=type=tmpfs,target=/tmp/ \
export NPM_TOKEN=`cat /run/secrets/npm_token` && \
yarn build
FROM node_modules_prod AS app
COPY --from=build /application/.output/server /application/.output/server
COPY --from=build /application/.output/public /application/.output/public
COPY --from=build /application/.output/nitro.json /application/.output/nitro.json
ENTRYPOINT ["/usr/bin/tini","--"]
CMD ["/usr/bin/node",".output/server/index.mjs"]
Используем multistage сборку, финальный образ делаем только из prod зависимостей. Обычно мы публикуем node_module_dev шаг в регистри, его потом можно использовать для различных QA job или линтинга, но в финальном образе dev зависимости естественно не нужны.
mount=type=secret - позволяет безопасно монтировать секрет, полученный например в job ранее, обычно это CI_JOB_TOKEN, который является временным и живет в рамках job. Он обладает правами того, кто ее запустил. А также с использованием данного подхода будет автоматически очищен, после сборки.
mount=type=cache - это кэширование с помощью buildkit. Тут создается временный монтируемый каталог в контейнере на этапе сборки. Сам кэш лежит на ноде (если это настроено на раннере), про него более подробно я писал тут.
sharing=locked - гарантирует, что кэш обновляется только одной сборкой в момент времени.
#docker