# syntax=docker/dockerfile:1.7
#
# Собирается из чистого клона: ни бинарника, ни frontend/dist в репозитории
# нет, и раньше этот Dockerfile их просто ждал готовыми. Хостинги, которые
# собирают образ сами, так не умеют, поэтому сборка целиком здесь.
#
# Шаги те же, что делал build-docker.sh, - он теперь сводится к docker build.

# --- фронтенд -------------------------------------------------------------
# Собирается с КОРНЕМ репозитория в контексте: index.html обоих приложений
# тянет /static/public/static/*.css абсолютным путём, и без симлинка на
# /static сборка падает с ENOENT.
FROM node:22-alpine AS frontend
ARG VERSION=dev
WORKDIR /repo
# Зависимости - отдельным слоем: они меняются куда реже кода, и пересобирать
# их на каждую правку вёрстки незачем. Кеш-маунты для этого не годятся:
# хостинги требуют в их имени свой префикс, то есть привязку к сервису.
COPY frontend/package.json frontend/pnpm-lock.yaml ./frontend/
WORKDIR /repo/frontend
RUN corepack enable && pnpm install --frozen-lockfile --prefer-offline
WORKDIR /repo
COPY . .
WORKDIR /repo/frontend
RUN ln -sfn /repo/static /static \
 && VITE_APP_VERSION="$VERSION" pnpm build:main \
 && VITE_APP_VERSION="$VERSION" pnpm build:widget

# --- бинарник -------------------------------------------------------------
FROM golang:1.25-alpine AS backend
ARG VERSION=dev
WORKDIR /src
RUN apk add --no-cache git
# Зависимости отдельным слоем: они меняются куда реже кода.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
COPY --from=frontend /repo/frontend/dist ./frontend/dist
RUN go install github.com/knadh/stuffbin/... \
 && CGO_ENABLED=0 go build -buildvcs=false \
      -ldflags="-X 'main.buildString=$VERSION' -X 'main.versionString=$VERSION' -X 'github.com/abhinavxd/libredesk/internal/version.Version=$VERSION' -s -w" \
      -o libredesk cmd/*.go \
 && stuffbin -a stuff -in libredesk -out libredesk frontend/dist i18n schema.sql static

# --- исходники ------------------------------------------------------------
# AGPL-3.0 §13: всякому, кто работает с изменённым libredesk по сети, надо
# предложить его исходники - ровно те, из которых собран этот образ. Архив
# собирается из того же контекста сборки, что и бинарник, а не из гита:
# незакоммиченная правка иначе попала бы в бинарник, но не в исходники.
# Лишнее контекст уже отсекает .dockerignore (.git, node_modules, сборки).
# Отдаётся самим приложением по /source; в поставке лежит ещё и рядом с
# образом (deploy/release.sh) - это §6.
FROM alpine:3.18 AS source
WORKDIR /src
COPY . .
RUN tar -czf /source.tar.gz -C /src .

# --- рантайм --------------------------------------------------------------
FROM alpine:3.18
# poppler-utils - ради pdftotext: клиент грузит в базу знаний PDF, а чистый Go
# на колонках и таблицах даёт кашу. Качество извлечения тут прямо определяет,
# сможет ли бот ответить. Цена - около 15 МБ образа.
RUN apk --no-cache add ca-certificates tzdata poppler-utils
WORKDIR /libredesk
COPY --from=backend /src/libredesk .
COPY --from=source /source.tar.gz ./source.tar.gz
# Значения по умолчанию. Всё, что отличается у конкретной установки,
# задаётся переменными LIBREDESK_* - они перекрывают файл.
COPY config.sample.toml config.toml
EXPOSE 9000

# Установка схемы, миграции, запуск - одной цепочкой. Апстримный CMD запускает
# только последнее звено, из-за чего свежая база остаётся без схемы, а
# обновлённый образ - без миграций; compose поэтому и переопределял команду.
# Раз это единственный правильный способ запуска, пусть он и будет здесь:
# хостинг команду не задаёт, а два способа запуска - это два способа сломать.
CMD ["sh", "-c", "./libredesk --install --idempotent-install --yes \
  && ./libredesk --upgrade --yes \
  && ./libredesk"]
