# PCP local Docker bundle

Локальный bundle предназначен для запуска PCP на машине с Docker без GitLab Config Repo, Kubernetes и Helm.

В bundle входят backend-сервисы PCP, кроме `tle-monitoring-service`; отдельный frontend
`pcp-tgu-ops-ui` также не включается.

## Состав

- `docker-compose.yml` - локальная схема запуска.
- `.env.example` - пример параметров запуска.
- `.env` - создаётся сборочным скриптом в итоговом архиве.
- `config-repo/` - локальный Spring Cloud Config repository.
- `images/` - Docker images, сохранённые через `docker save`.
- `scripts/import-images.sh` - импорт Docker images и запуск базовых сервисов.
- `scripts/init-db.sh` - создание баз данных в одном Postgres контейнере.
- `scripts/start.sh` - запуск инфраструктуры, config-server и приложений.
- `scripts/stop.sh` - остановка compose stack.
- `scripts/status.sh` - статус контейнеров.

## Локальный запуск без архива

Для запуска на той же машине, где собираются images, архив и `docker save` не нужны.
Используйте один скрипт:

```bash
./deploy/local-bundle/run-local.sh start
```

Скрипт:

- создаёт `.env` из `.env.example`, если его ещё нет;
- собирает `bootJar` в Gradle offline mode;
- собирает локальные Docker images `pcp/<service>:<PCP_IMAGE_TAG>`;
- запускает `docker compose`.

Для вашего allinone Postgres/Kafka/Camunda перед первым запуском настройте
`deploy/local-bundle/.env`:

```env
USE_EXTERNAL_INFRA=true
PCP_DOCKER_NETWORK=allinone_camunda
PCP_DOCKER_NETWORK_EXTERNAL=true
PCP_POSTGRES_HOST=postgres
PCP_POSTGRES_PORT=5432
PCP_KAFKA_HOST=kafka
PCP_KAFKA_PORT=9092
EXTERNAL_POSTGRES_CONTAINER=allinone-postgres-1
EXTERNAL_KAFKA_CONTAINER=allinone-kafka-1
CAMUNDA_CLIENT_ENABLED=true
CAMUNDA_GRPC_ADDRESS=http://orchestration:26500
```

Команды:

```bash
./deploy/local-bundle/run-local.sh start
./deploy/local-bundle/run-local.sh status
./deploy/local-bundle/run-local.sh logs
./deploy/local-bundle/run-local.sh stop
```

## Пересборка одного сервиса

После первого запуска всего стека можно пересобирать и перезапускать только один сервис:

```bash
./deploy/local-bundle/services/pcp-request-service.sh
```

Это выполнит:

- `bootJar` только для `pcp-request-service`;
- `docker build` только для `pcp/pcp-request-service:<PCP_IMAGE_TAG>`;
- `docker compose up -d --no-deps --force-recreate pcp-request-service`.

Доступны wrapper-скрипты в `deploy/local-bundle/services/` для каждого сервиса.
То же самое можно вызвать через общий скрипт:

```bash
./deploy/local-bundle/run-service.sh pcp-request-service
./deploy/local-bundle/run-service.sh pcp-request-service build
./deploy/local-bundle/run-service.sh pcp-request-service logs
./deploy/local-bundle/run-service.sh pcp-request-service stop
```

## Сборка архива

Из корня репозитория:

```bash
./deploy/local-bundle/build-local-bundle.sh
```

Можно задать версию:

```bash
LOCAL_BUNDLE_VERSION=1.0.0-local ./deploy/local-bundle/build-local-bundle.sh
```

Результат будет создан в:

```bash
deploy/local-bundle/build/pcp-local-bundle-<version>.tar.gz
```

Скрипт сборки:

- собирает `bootJar` для разворачиваемых сервисов;
- запускает Gradle в offline mode по умолчанию;
- собирает Docker images сервисов;
- сохраняет PCP service images в один `images/pcp-services.tar`;
- по умолчанию не сохраняет публичные infra images, чтобы не раздувать архив;
- копирует `docker-compose.yml`, `config-repo`, scripts и документацию;
- формирует итоговый `tar.gz`.

Публичные images `postgis/postgis` и `apache/kafka` будут скачаны на целевой машине командой `docker compose up`, если их нет локально.

Если нужен полностью offline bundle, включите сохранение infra images:

```bash
INCLUDE_INFRA_IMAGES=true ./deploy/local-bundle/build-local-bundle.sh
```

По умолчанию сборка `bootJar` выполняется последовательно, чтобы не упираться в heap Kotlin compiler daemon на локальной машине. Параметры можно переопределить:

```bash
GRADLE_MAX_WORKERS=1 \
GRADLE_JVMARGS="-Xmx2g -Dfile.encoding=UTF-8" \
KOTLIN_DAEMON_JVMARGS="-Xmx3g -XX:MaxMetaspaceSize=768m" \
./deploy/local-bundle/build-local-bundle.sh
```

Gradle offline mode включён по умолчанию:

```bash
GRADLE_OFFLINE=true ./deploy/local-bundle/build-local-bundle.sh
```

Если нужно один раз прогреть локальный Gradle cache, временно отключите offline mode:

```bash
GRADLE_OFFLINE=false ./deploy/local-bundle/build-local-bundle.sh
```

Важно: `GRADLE_OFFLINE=true` отключает сетевой резолв зависимостей Gradle, но Docker всё равно
должен иметь локально доступный base image. Для local bundle сервисные Dockerfile собираются с
локальным override:

```text
LOCAL_BUNDLE_RUNTIME_IMAGE=bellsoft/liberica-openjre-alpine:21.0.5
```

Поэтому перед полностью offline Docker-сборкой подтяните или импортируйте:

```bash
docker pull bellsoft/liberica-openjre-alpine:21.0.5
```

Для полностью переносимого архива с infra images заранее подтяните Postgres/Kafka и включите их
сохранение:

```bash
docker pull postgis/postgis:16-3.4
docker pull apache/kafka:3.7.2
INCLUDE_INFRA_IMAGES=true ./deploy/local-bundle/build-local-bundle.sh
```

## Запуск на локальной машине

Распаковать архив:

```bash
tar -xzf pcp-local-bundle-<version>.tar.gz
cd pcp-local-bundle-<version>
```

Проверить `.env` и при необходимости изменить порты.

Если Postgres/Kafka/Camunda уже подняты внешним allinone compose, например в сети
`allinone_camunda`, включите external infra mode в `.env`:

```env
USE_EXTERNAL_INFRA=true
PCP_DOCKER_NETWORK=allinone_camunda
PCP_DOCKER_NETWORK_EXTERNAL=true
PCP_POSTGRES_HOST=postgres
PCP_POSTGRES_PORT=5432
PCP_KAFKA_HOST=kafka
PCP_KAFKA_PORT=9092
EXTERNAL_POSTGRES_CONTAINER=allinone-postgres-1
EXTERNAL_KAFKA_CONTAINER=allinone-kafka-1
CAMUNDA_CLIENT_ENABLED=true
CAMUNDA_GRPC_ADDRESS=http://orchestration:26500
```

В этом режиме `scripts/start.sh` не поднимает свои `postgres` и `kafka`, а сервисы PCP
подключаются к уже существующим контейнерам через общую Docker network.

Импортировать images:

```bash
./scripts/import-images.sh
```

Создать базы данных:

```bash
./scripts/init-db.sh
```

Запустить приложение:

```bash
./scripts/start.sh
```

`start.sh` также запускает `init-db.sh`, если не задано `SKIP_DB_INIT=true`.

## Остановка и статус

```bash
./scripts/status.sh
./scripts/stop.sh
```

Чтобы удалить volumes с данными Postgres/Kafka:

```bash
./scripts/stop.sh -v
```

## Открытые порты

- Config Server: `http://localhost:38888`
- Spring Boot Admin: `http://localhost:7000`
- Complex Mission: `http://localhost:7002`
- Ballistics: `http://localhost:7003`
- Route Processing: `http://localhost:7004`
- Request Service: `http://localhost:7005`
- Slots Service: `http://localhost:7006`
- UI: `http://localhost:7008`
- Stations: `http://localhost:7009`
- Mission Planning: `http://localhost:7010`
- TGU: `http://localhost:7011`
- Coverage Scheme: `http://localhost:7012`
- Satellite Catalog: `http://localhost:7013`
- Dynamic Plan: `http://localhost:7014`
- Postgres: `localhost:5432`
- Kafka external listener: `localhost:29092`

## Проверка готовности

Config Server:

```bash
curl http://localhost:38888/actuator/health
curl http://localhost:38888/pcp-ui-service/local,docker-local
```

UI:

```bash
curl http://localhost:7008/actuator/health
```

Статус контейнеров:

```bash
./scripts/status.sh
```

## Config Server

В локальном сценарии `spring-cloud-config-server` запускается с:

```text
SPRING_PROFILES_ACTIVE=local
CONFIG_NATIVE_SEARCH_LOCATIONS=file:/config-repo
```

`CONFIG_GIT_URI`, GitLab token и `git clone` не используются.

Сервисы запускаются с профилями:

```text
SPRING_PROFILES_ACTIVE=local,docker-local
SPRING_CLOUD_CONFIG_PROFILE=local,docker-local
SPRING_CLOUD_CONFIG_LABEL=
```

Профиль `local` сохраняет существующие service-specific настройки, а `docker-local` переопределяет IP-адреса на Docker Compose DNS names:

- `postgres`
- `kafka`
- `pcp-ballistics-service`
- `slots-service`
- остальные service names из `docker-compose.yml`

## Базы данных

`scripts/init-db.sh` создаёт только пустые базы данных:

- `pcp_ballistics`
- `pcp_requests`
- `pcp_route_processing`
- `pcp_missions`
- `pcp_slots`
- `pcp_complex_plan`
- `pcp_satellite_catalog`
- `pcp_stations`
- `pcp_tgu`
- `pcp_satellites`

Таблицы, схемы и seed data вручную не создаются. Схемы создаются существующими Flyway migrations внутри сервисов при старте приложений.

`pcp_satellites` добавлена дополнительно, потому что текущий `config-repo/pcp-complex-mission-service.yaml` использует эту БД для `pcp-complex-mission-service`.
