Docker-сборки
Эта страница описывает структуру, сборку и хранение Docker-образов для сервисов.
Реестр
Все образы хранятся в GitLab Container Registry по адресу:
gitlab.amzgit.com:5050Полный путь к образу имеет следующую структуру:
gitlab.amzgit.com:5050/<group>/<project>/<service>:<tag>Например:
gitlab.amzgit.com:5050/meduza/hub/backend:a1b2c3d4
gitlab.amzgit.com:5050/meduza/hub/frontend:a1b2c3d4
gitlab.amzgit.com:5050/meduza/auth/api:devАутентификация в реестре
CI-задачи аутентифицируются автоматически через $CI_REGISTRY_USER и $CI_REGISTRY_PASSWORD. Для ручного получения образов (например, с KVM-хоста или локальной машины):
docker login gitlab.amzgit.com:5050 -u <username> -p <access_token>Personal Access Token
Используйте GitLab Personal Access Token с правом read_registry для получения образов. В CI-сборках GitLab предоставляет учётные данные автоматически — настройка не требуется.
Стратегия тегирования образов
Каждый образ получает два тега при сборке в CI:
| Тег | Формат | Назначение |
|---|---|---|
| Commit SHA | a1b2c3d4 | Неизменяемый идентификатор, привязанный к конкретному коду. Используется Nomad при деплое. |
| Окружение | prod / stage / dev | Мутабельный указатель на последнюю сборку для данного окружения. Удобен для быстрого локального тестирования. |
Тег commit SHA используется Nomad для деплоя. Тег окружения — это удобный алиас, который перезаписывается при каждом пуше в соответствующую ветку.
# These point to the same image after a deploy from dev branch:
docker pull gitlab.amzgit.com:5050/meduza/hub/backend:a1b2c3d4
docker pull gitlab.amzgit.com:5050/meduza/hub/backend:devМутабельные теги окружений
Теги dev, stage и prod перезаписываются при каждой сборке. Никогда не ссылайтесь на эти теги в Nomad-файлах или продакшн-инфраструктуре. Для деплоев всегда используйте commit SHA.
Паттерны Dockerfile
Сервисы обычно делятся на две категории: только бэкенд и полный стек с фронтендом. Оба используют многоэтапные сборки для минимизации размера итоговых образов.
Бэкенд-сервис (Python / Go)
# --- 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"]# --- 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)
Фронтенд-сборки компилируют статические ресурсы на этапе сборки и раздают их из легковесного образа.
# --- 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-задаче:
BUILD_ARGS: "--build-arg VITE_API_URL=https://api.amzhub.ai"Полный стек (бэкенд + фронтенд в одном репозитории)
Когда бэкенд и фронтенд находятся в одном репозитории, каждый получает отдельную задачу сборки с указанием своего SERVICE_DIR:
build:backend:
extends: .docker_build
variables:
SERVICE_NAME: backend
SERVICE_DIR: back
build:frontend:
extends: .docker_build
variables:
SERVICE_NAME: frontend
SERVICE_DIR: front
BUILD_ARGS: "--build-arg VITE_API_URL=https://api.amzhub.ai"В результате создаются два отдельных образа:
gitlab.amzgit.com:5050/meduza/hub/backend:a1b2c3d4
gitlab.amzgit.com:5050/meduza/hub/frontend:a1b2c3d4Оба имеют одинаковый тег commit SHA, так как собраны из одного коммита.
Ограничение платформы
Все образы собираются с флагом --platform linux/amd64:
docker build --platform linux/amd64 -t ... .Это обеспечивается шаблоном .docker_build. KVM-хосты, на которых работает Nomad, используют архитектуру amd64, поэтому даже если CI-раннеры или машины разработчиков основаны на ARM (Apple Silicon), итоговые образы будут корректно работать на целевой инфраструктуре.
Локальное тестирование на ARM Mac
Если вы собираете локально на Mac с чипом M-серии без флага --platform linux/amd64, образ может работать на вашей машине, но упасть на KVM-хосте. Всегда указывайте флаг платформы при локальной сборке для тестирования деплоя:
docker build --platform linux/amd64 -t my-service:test .Контекст сборки и .dockerignore
Каждый SERVICE_DIR должен содержать собственный .dockerignore для уменьшения контекста сборки:
node_modules
.git
.env
.env.*
*.md
dist
__pycache__
.venvКомпактный контекст сборки ускоряет этап docker build в CI, поскольку меньше данных передаётся демону Docker.