Skip to content
страница целиком, в Markdown — вставьте в чат с моделью

Docker-сборки ​

Эта страница описывает структуру, сборку и хранение Docker-образов для сервисов.

Registry ​

Все образы хранятся в отдельном registry рядом с кластером:

registry.amztop.io

Полный путь к образу имеет следующую структуру:

registry.amztop.io/<группа>/<проект>/<сервис>:<тег>

Например:

registry.amztop.io/integrations/hub/backend:dev
registry.amztop.io/integrations/hub/frontend:dev
registry.amztop.io/integrations/auth_service/backend:prod

Первые сегменты пути — это путь проекта в GitLab, и придумать их нельзя: токен на запись выдаётся только на путь существующего проекта. Всё, что после пути проекта, свободно — один проект может держать сколько угодно образов.

Аутентификация в registry ​

Собственной базы учёток у registry нет: токены ему подписывает GitLab, поэтому годятся любые GitLab-креды. CI-задачи аутентифицируются автоматически через $CI_REGISTRY_USER и $CI_REGISTRY_PASSWORD. Для ручной работы с локальной машины:

bash
docker login registry.amztop.io -u <username> -p <token>

Какой токен брать

  • В пайплайне — ничего заводить не нужно, работает эфемерный токен джобы.
  • Ноды, ansible, внешние сервисы — deploy-токен со скоупом read_registry; имя пользователя берётся из карточки токена (gitlab+deploy-token-N).
  • Push извне пайплайна — тот же deploy-токен, но со скоупом write_registry. Только read_registry даст рабочий pull и denied на push.
  • Руками со своей машины — personal access token со скоупами read_registry / write_registry.

Образов не видно в интерфейсе GitLab

GitLab пока знает о своём старом registry, поэтому вкладка Packages & Registry показывает не то, что лежит в registry.amztop.io. Содержимое смотрите через API:

bash
curl -su <логин>:<токен> https://registry.amztop.io/v2/_catalog
curl -su <логин>:<токен> https://registry.amztop.io/v2/integrations/hub/backend/tags/list

Стратегия тегирования образов ​

Образ получает один тег — по имени ветки, из которой собран:

ТегВеткаНазначение
devdevПоследняя сборка для dev-окружения
stagestageПоследняя сборка для stage-окружения
prodmainПоследняя сборка для продакшена

Теги перезаписываются при каждой сборке, и Nomad-джобы ссылаются именно на них. Чтобы Nomad увидел новую сборку под неизменившимся тегом, в джобу передаётся переменная deploy_ts с номером пайплайна — она и делает каждую выкатку уникальной.

bash
# Всегда указывает на последнюю сборку из ветки dev:
docker pull registry.amztop.io/integrations/hub/backend:dev

Откат — это пересборка

Отдельного неизменяемого тега по commit SHA у образов нет, поэтому «вернуть предыдущий образ» по тегу не получится. Штатный откат — автоматический: если канареечная копия не прошла health-чеки, Nomad сам возвращает прошлую версию (auto_revert). Ручной откат делается ревертом коммита и новой сборкой.

Паттерны Dockerfile ​

Сервисы обычно делятся на две категории: только бэкенд и полный стек с фронтендом. Оба используют многоэтапные сборки для минимизации размера итоговых образов.

Бэкенд-сервис (Python / Go) ​

dockerfile
# --- Build stage ---
FROM python:3.12-slim AS builder

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

COPY . .

# --- Runtime stage ---
FROM python:3.12-slim

WORKDIR /app
COPY --from=builder /install /usr/local
COPY --from=builder /app .

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
dockerfile
# --- Build stage ---
FROM golang:1.22-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /bin/server .

# --- Runtime stage ---
FROM alpine:3.19

COPY --from=builder /bin/server /bin/server

EXPOSE 8080
ENTRYPOINT ["/bin/server"]

Фронтенд (Vite + Node) ​

Фронтенд-сборки компилируют статические ресурсы на этапе сборки и раздают их из легковесного образа.

dockerfile
# --- Build stage ---
FROM node:20-alpine AS builder

WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

COPY . .
ARG VITE_API_URL
ENV VITE_API_URL=${VITE_API_URL}
RUN pnpm build

# --- Runtime stage ---
FROM nginx:alpine

COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

Аргументы сборки для фронтенда

Специфичные для окружения значения, такие как VITE_API_URL, должны передаваться во время сборки, поскольку Vite вшивает их в статический JS-бандл. Передавайте их через BUILD_ARGS в CI-задаче:

yaml
BUILD_ARGS: "--build-arg VITE_API_URL=https://api.amzhub.ai"

Полный стек (бэкенд + фронтенд в одном репозитории) ​

Когда бэкенд и фронтенд находятся в одном репозитории, каждый получает отдельную задачу сборки с указанием своего SERVICE_DIR:

yaml
build:backend:
  extends: .docker_build
  tags:
    - new-server
  variables:
    SERVICE_NAME: backend
    SERVICE_DIR: back

build:frontend:
  extends: .docker_build
  tags:
    - new-server
  variables:
    SERVICE_NAME: frontend
    SERVICE_DIR: front
    BUILD_ARGS: "--build-arg VITE_API_URL=https://api.amzhub.ai"

В результате создаются два отдельных образа:

registry.amztop.io/integrations/hub/backend:dev
registry.amztop.io/integrations/hub/frontend:dev

Оба собраны из одного коммита и получают одинаковый тег окружения.

Ограничение платформы ​

Все образы собираются с флагом --platform linux/amd64:

bash
docker build --platform linux/amd64 -t ... .

Это обеспечивается шаблоном .docker_build. Ноды кластера, на которых работает Nomad, используют архитектуру amd64, поэтому даже если CI-раннеры или машины разработчиков основаны на ARM (Apple Silicon), итоговые образы будут корректно работать на целевой инфраструктуре.

Локальное тестирование на ARM Mac

Если вы собираете локально на Mac с чипом M-серии без флага --platform linux/amd64, образ может работать на вашей машине, но упасть на ноде кластера. Всегда указывайте флаг платформы при локальной сборке для тестирования деплоя:

bash
docker build --platform linux/amd64 -t my-service:test .

Контекст сборки и .dockerignore ​

Каждый SERVICE_DIR должен содержать собственный .dockerignore для уменьшения контекста сборки:

gitignore
node_modules
.git
.env
.env.*
*.md
dist
__pycache__
.venv

Компактный контекст сборки ускоряет этап docker build в CI, поскольку меньше данных передаётся демону Docker.

Документация по инфраструктуре