Пример сборки frontend-сервиса
Dockerfile
FROM node:20.11.1-bookworm as node
ARG ENDPOINT=prod
ARG NPM_TOKEN
ARG SENTRY_URL=""
WORKDIR /opt/react_client
COPY package.json .npmrc ./
RUN npm install
COPY . .
RUN NPM_TOKEN=$NPM_TOKEN ENDPOINT=$ENDPOINT SENTRY_URL=$SENTRY_URL npm run build
FROM nginx:mainline-alpine-otel as nginx
COPY --from=node /opt/react_client/static/ /opt/react_client/static/
COPY nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
Что делает Dockerfile
- Стейдж node: устанавливает зависимости и собирает приложение
ARG— объявляет build-time аргументы дляdocker build --build-arg.npmrcсодержит//nexus...:_authToken=${NPM_TOKEN}для доступа к приватному npm реджистри-
npm run buildсобирает статику с нужнымENDPOINT -
Стейдж nginx: берёт собранную статику и настраивает nginx
Как переменные попадают в билд
В .gitlab-ci.yml:
variables:
SERVICE_NAME: bi-frontend
DOCKERFILE_PATH: ./Dockerfile
BUILD_ARGS: ""
CI_TRIGGER_SOURCE: app
Для конкретного окружения:
- if: '$CI_COMMIT_BRANCH == "stage"'
variables:
STAND: stage
NAMESPACE: planning
BUILD_ARGS: "--build-arg ENDPOINT=stage --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}"
HELM_SET_ARGS: >-
--set universal-chart.services.frontend.image.name.stage=${IMAGE_NAME}
--set universal-chart.global.env=stage
BUILD_ARGS подставляется в команду сборки:
docker build -f ${DOCKERFILE_PATH} ${BUILD_ARGS} -t ${IMAGE_NAME} .
Про NPM_TOKEN и чувствительные данные
NPM_TOKEN,NPM_NEXUS_TOKEN,SENTRY_URL— чувствительные данные- Передаются из переменных на уровне группы
- В
.gitlab-ci.ymlиспользуются как${NPM_NEXUS_TOKEN}без явного указания значений
Полный flow сборки образа
-
workflow.rules выбирает переменные для ветки
-
build job (extends
.base_docker): docker loginвcr.yandexчерезSAREX_REGISTRY_KEY- Команда:
bash docker build -f ./Dockerfile \ --build-arg ENDPOINT=stage \ --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN} \ -t ${IMAGE_NAME} . -
docker push ${IMAGE_NAME} -
build_chart упаковывает и публикует helm chart
-
deploy job:
bash helm upgrade -i bi-frontend .helm --atomic -n=${NAMESPACE} \ -f .helm/values.yaml ${HELM_SET_ARGS}
values.yaml для frontend
universal-chart:
global:
env: stage
services:
frontend:
enabled: true
deployment:
enabled: true
name:
_default: bi-frontend
replicaCount:
_default: 1
port:
_default: 80
resources:
requests:
cpu:
_default: "100m"
memory:
_default: 128Mi
probes:
liveness:
enabled:
_default: true
type:
_default: httpGet
httpGet:
path:
_default: /
port:
_default: 80
periodSeconds:
_default: 10
readiness:
enabled:
_default: true
type:
_default: httpGet
httpGet:
path:
_default: /
port:
_default: 80
image:
name:
_default: cr.yandex/crp3ccidau046kdj8g9q/bi-frontend:latest
stage: cr.yandex/crp3ccidau046kdj8g9q/bi-frontend:stage
pullPolicy:
_default: IfNotPresent
service:
enabled: true
name:
_default: bi-frontend-service
port:
_default: 80
targetPort:
_default: 80
type:
_default: ClusterIP
imagePullSecrets:
enabled:
_default: false
name:
_default: dockerhub
envs: []
volumes:
_default: []
commitSha: ""
gitlabUri: ""
gitlabJobUrl: ""
owner: "team-abc"
HELM_SET_ARGS для frontend
Обратите внимание на путь к образу — для frontend используется services.frontend:
HELM_SET_ARGS: >-
--set universal-chart.services.frontend.image.name.stage=${IMAGE_NAME}
--set universal-chart.global.env=stage
--set universal-chart.services.frontend.commitSha=${CI_COMMIT_SHA}
--set universal-chart.services.frontend.gitlabUri=${CI_PROJECT_URL}
--set universal-chart.services.frontend.gitlabJobUrl=${CI_JOB_URL}
--set universal-chart.services.frontend.owner=${CI_PROJECT_NAMESPACE}
Это отличается от backend, где используется services.main.
Кастомные джобы для frontend
Пример сборки отдельного образа для contour:
build_contour_tag:
variables:
CONTAINER_IMAGE_CONTOUR_TAG: cr.yandex/.../frontend-dev:contour_${CI_COMMIT_TAG}
extends: .base_docker
script:
- docker build --build-arg NPM_TOKEN=${NPM_TOKEN} --build-arg ENDPOINT=contour -f Dockerfile.contour -t ${CONTAINER_IMAGE_CONTOUR_TAG} .
- docker push ${CONTAINER_IMAGE_CONTOUR_TAG}
rules:
- if: '$CI_COMMIT_TAG'
allow_failure: false
Эта джоба:
- Определяет свои rules независимо от workflow
- Использует отдельный Dockerfile
- Запускается только для тегов