Pin dependency versions and add constraints.txt

Exact versions for direct dependencies, full pip freeze of the tested
image as constraints, both Dockerfiles install with -c constraints.txt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ayurishchevandClaude Sonnet 5 committed 2026-09-21 07:47:02 +03:00
1 parent bcf8156085
commit c99665542a
8 files changed
+89 -13

No files matched your search

+2 -2
View File
@@ -6,8 +6,8 @@ ENV PYTHONUNBUFFERED=1 \
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY requirements.txt constraints.txt ./
RUN pip install --no-cache-dir -c constraints.txt -r requirements.txt
COPY api_server.py cidr_collector.py collector_daemon.py db.py formatters.py storage.py healthcheck.py ./
+2 -2
View File
@@ -2,8 +2,8 @@ FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt requirements-dev.txt ./
RUN pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt
COPY requirements.txt requirements-dev.txt constraints.txt ./
RUN pip install --no-cache-dir -c constraints.txt -r requirements.txt -r requirements-dev.txt
COPY . .
+8 -3
View File
@@ -19,7 +19,8 @@ The system consists of **two independent processes**: the collector daemon (`col
```bash
mkdir -p /opt/ripe_collector
cd /opt/ripe_collector
# Copy files: cidr_collector.py, api_server.py, storage.py, requirements.txt, config.json
# Copy files: *.py (api_server, cidr_collector, collector_daemon, db, formatters, storage, healthcheck),
# requirements.txt, constraints.txt, config.json
```
2. **Create a Virtual Environment**:
@@ -30,7 +31,7 @@ The system consists of **two independent processes**: the collector daemon (`col
3. **Install Dependencies**:
```bash
source venv/bin/activate
pip install -r requirements.txt
pip install -c constraints.txt -r requirements.txt # exact versions, see "Dependency versions" below
deactivate
```
@@ -57,6 +58,10 @@ The system consists of **two independent processes**: the collector daemon (`col
7. **Repository:** `main` branch, remote `origin` = `https://artstore.rxmsk.ru/ayurishchev/ripe-cidr-collector.git`. Committed: code, tests, Docker files, `config.json` (initial sources), `.env.example`, `docs/`. Not committed (`.gitignore`): `venv/`, `.env`, databases `*.db*`, collected data `data.json` / `fqdn_data.json`, `graphify-out/`, service files. Every change follows the plan -> implementation -> summary flow in `docs/` and gets its own commit.
### Dependency versions
`requirements.txt` / `requirements-dev.txt` list direct dependencies with exact versions (`==`); `constraints.txt` is the full `pip freeze` (including transitive packages) of the image the tests pass on. Both Dockerfiles install with `-c constraints.txt`. To update: change the versions in a container, run the tests, regenerate `constraints.txt` (`docker run --rm --entrypoint pip <test-image> freeze > constraints.txt`) and commit all three files together.
---
## 2. Running the Collector
@@ -476,7 +481,7 @@ docker compose down # stop; data stays in the volume
### Notes and risks
- **Port 8000 is published without TLS**, so `X-API-Key` travels in clear text. Restrict access with a firewall or put a TLS reverse proxy in front (bind the port to `127.0.0.1` by changing `ports` in `docker-compose.yml`).
- The image installs unpinned dependencies from `requirements.txt`; rebuilds may pick up newer versions.
- Dependencies are pinned (see "Dependency versions" below), so rebuilds give the same libraries. The base image `python:3.11-slim` is not pinned by digest: Python patch releases arrive on rebuild.
- Files written by the services in the volume (`config.json`, `status.json`) have mode `600`; both services run as the same user.
- `docker compose` uses the image name `ripe-cidr-collector`; `Dockerfile.test` is used only for running the tests (section 1, step 5).
+26
View File
@@ -0,0 +1,26 @@
annotated-doc==0.0.5
annotated-types==0.8.0
anyio==4.15.1
APScheduler==3.11.3
certifi==2026.7.22
charset-normalizer==3.5.1
click==8.5.0
fastapi==0.141.1
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.20
iniconfig==2.3.0
packaging==26.3
pluggy==1.6.0
pydantic==2.13.5
pydantic_core==2.46.5
Pygments==2.21.0
pytest==9.1.1
requests==2.34.2
starlette==1.6.0
typing-inspection==0.4.4
typing_extensions==4.16.0
tzlocal==5.4.4
urllib3==2.8.0
uvicorn==0.53.0
+25
View File
@@ -0,0 +1,25 @@
# План: закрепление версий зависимостей (п. 1.2 рекомендаций)
## Цель
Сборка образа и запуск тестов воспроизводимы: завтрашняя сборка использует те же версии библиотек, что и сегодняшняя (риск 2 анализа). Обновление библиотек становится осознанным действием.
## Дизайн
- **Версии берутся из образа, на котором сейчас проходят 18 тестов** (`pip freeze` в контейнере, Python 3.11), поэтому поведение не меняется.
- `requirements.txt` и `requirements-dev.txt`: только прямые зависимости с точной версией (`==`), файлы остаются читаемыми.
- прод: `requests`, `fastapi`, `uvicorn`, `APScheduler`;
- разработка: `pytest`, `httpx`.
- `constraints.txt` (новый): полный список всех установленных пакетов, включая транзитивные (`starlette`, `pydantic`, `urllib3` и др.). Оба Dockerfile ставят пакеты с `-c constraints.txt`, поэтому закреплены и косвенные зависимости.
- Базовый образ `python:3.11-slim` не закрепляется по дайджесту (патчи безопасности Python приходят автоматически); это осознанный компромисс, указан в README.
- Порядок обновления (в README): поднять версии в контейнере, прогнать тесты, обновить `constraints.txt` из `pip freeze`, коммит.
## Изменения
1. `requirements.txt`, `requirements-dev.txt`: точные версии.
2. `constraints.txt`: новый файл.
3. `Dockerfile`, `Dockerfile.test`: копирование `constraints.txt`, установка с `-c`.
4. `README.md`: ручная установка с `-c constraints.txt`, порядок обновления версий.
5. Тестов не добавляется (код не меняется).
## Проверка
- Сборка обоих образов, 18 тестов проходят.
- В прод-образе `pip freeze` совпадает с закреплёнными версиями (нет лишних пакетов вроде `pytest`).
- Импорт `api_server` и `collector_daemon` в прод-образе.
+20
View File
@@ -0,0 +1,20 @@
# Итоги: закрепление версий зависимостей (п. 1.2)
План: `docs/plan-pin-dependencies.md`.
## Сделано
- `requirements.txt` и `requirements-dev.txt`: прямые зависимости с точными версиями. Прод: `requests==2.34.2`, `fastapi==0.141.1`, `uvicorn==0.53.0`, `APScheduler==3.11.3`. Разработка: `pytest==9.1.1`, `httpx==0.28.1`.
- `constraints.txt` (новый, 26 пакетов): полный `pip freeze` образа, на котором проходили тесты, включая транзитивные пакеты (`starlette`, `pydantic`, `urllib3` и др.).
- `Dockerfile` и `Dockerfile.test` ставят пакеты с `-c constraints.txt`.
- README: ручная установка с `-c constraints.txt`, список копируемых файлов приведён в соответствие с кодом (был неполным), раздел «Dependency versions» с порядком обновления, замечание об образе исправлено.
## Проверка
- Оба образа собраны без кэша, 18 тестов проходят.
- Прод-образ: пакеты полностью совпадают с `constraints.txt`, `pytest` и `httpx` в нём нет; `api_server`, `collector_daemon`, `db`, `healthcheck` импортируются.
- Версии взяты из того, что уже стояло и проходило тесты, поведение не менялось.
## Замечания
- Базовый образ `python:3.11-slim` не закреплён по дайджесту: патчи Python приходят при пересборке (осознанный компромисс).
- Закрепление даёт воспроизводимость, но не обновляет уязвимые версии само: проверку обновлений нужно делать вручную (порядок в README).
- Не проверялась сборка на другой архитектуре: часть пакетов (`pydantic_core`) содержит бинарные сборки под платформу.
- `docker compose up` не запускался повторно: образ собран тем же Dockerfile, стенд не менялся.
+2 -2
View File
@@ -1,2 +1,2 @@
pytest
httpx
pytest==9.1.1
httpx==0.28.1
+4 -4
View File
@@ -1,4 +1,4 @@
requests
fastapi
uvicorn
APScheduler
requests==2.34.2
fastapi==0.141.1
uvicorn==0.53.0
APScheduler==3.11.3