Установка
Установка ПО РУБИН-Т выполняется путём развёртывания набора Docker-контейнеров на серверном оборудовании. Сборка компонентов из исходного кода не требуется: все компоненты поставляются в виде готовых образов контейнеров.
Состав контейнеров и их назначение описаны в разделе Описание технической архитектуры.
1. Системные требования
| Рабочие места пользователей | Серверное оборудование | |
|---|---|---|
| Операционная система | ОС, поддерживающие современные браузеры | Ubuntu 24.04 |
| Процессор | 2-ядерный | 4-ядерный с тактовой частотой от 2.4 ГГц |
| Оперативная память | от 4 Гб | от 32 Гб |
| Жёсткий диск | от 50 Гб | от 1 Тб SSD |
| Веб-браузер | Яндекс.Браузер, Google Chrome, Mozilla Firefox, Microsoft Edge (версии не старше одного года) | — |
Требования зависят от размеров и наполнения данными, с которыми будет работать ПО РУБИН-Т. При использовании подсистемы видеонаблюдения объём дискового пространства рассчитывается исходя из числа камер и глубины хранения видеоархива, а для распознавания в реальном времени рекомендуется наличие графического ускорителя.
2. Подготовка сервера
2.1 Установка Docker
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Проверка установки:
docker --version
docker compose version
2.2 Создание каталога установки
sudo mkdir -p /opt/rubin-t
cd /opt/rubin-t
В этом каталоге размещаются файл описания сервисов docker-compose.yml и файл
переменных окружения .env.
2.3 Доступ к реестру образов
Образы публикуются в закрытом реестре. Учётные данные предоставляются поставщиком ПО.
docker login <адрес-реестра>
| Параметр | Назначение |
|---|---|
<адрес-реестра> | Адрес реестра образов контейнеров, предоставленный поставщиком |
| Имя пользователя | Учётная запись для доступа к реестру |
| Пароль | Пароль или токен доступа к реестру |
3. Файл переменных окружения
Значения переменных задаются в файле .env в каталоге установки. Файл содержит
пароли и ключи и должен быть доступен только владельцу:
touch /opt/rubin-t/.env
chmod 600 /opt/rubin-t/.env
Значения переменных в настоящем разделе намеренно не приводятся. Пароли, ключи
и адреса задаются при установке и не должны совпадать со значениями из примеров
или тестовых стендов. Файл .env не подлежит передаче по открытым каналам
и включению в системы контроля версий.
3.1 Реестр образов и версия
| Переменная | Назначение |
|---|---|
REGISTRY | Адрес реестра образов контейнеров |
IMAGE_TAG | Тег (версия) устанавливаемых образов |
3.2 Прикладная база данных
| Переменная | Назначение |
|---|---|
POSTGRES_DB | Имя прикладной базы данных |
POSTGRES_USER | Имя пользователя СУБД для прикладной базы |
POSTGRES_PASSWORD | Пароль пользователя СУБД для прикладной базы |
3.3 База данных телематики
| Переменная | Назначение |
|---|---|
TRACCAR_DB_NAME | Имя базы данных сервера телематики |
TRACCAR_DB_USER | Имя пользователя СУБД для базы телематики |
TRACCAR_DB_PASSWORD | Пароль пользователя СУБД для базы телематики |
3.4 База данных графа УДС
| Переменная | Назначение |
|---|---|
OSM_DB_NAME | Имя базы данных сервиса графа улично-дорожной сети |
OSM_DB_USER | Имя пользователя СУБД для базы графа УДС |
OSM_DB_PASSWORD | Пароль пользователя СУБД для базы графа УДС |
3.5 Брокер сообщений
| Переменная | Назначение |
|---|---|
RABBITMQ_USER | Имя пользователя брокера сообщений |
RABBITMQ_PASSWORD | Пароль пользователя брокера сообщений |
RABBITMQ_VHOST | Виртуальный хост брокера, в котором создаются очереди ПО |
3.6 Сервер приложений
| Переменная | Назначение |
|---|---|
RAILS_ENV | Режим работы сервера приложений; для промышленной эксплуатации — production |
RAILS_MASTER_KEY | Ключ расшифровки зашифрованных настроек приложения. Предоставляется поставщиком ПО; без него сервер приложений не запускается |
DATABASE_URL | Строка подключения к прикладной базе данных в формате postgis://<пользователь>:<пароль>@<хост>:<порт>/<база> |
RABBITMQ_URL | Строка подключения к брокеру сообщений в формате amqp://<пользователь>:<пароль>@<хост>:<порт>/<виртуальный хост> |
ADMIN_PASSWORD | Пароль учётной записи администратора, создаваемой при первичной инициализации базы данных |
COOKIE_SECURE | Признак передачи сессионных cookie только по защищённому соединению. Устанавливается в true при работе по HTTPS |
TRACCAR_API_BASE | Базовый адрес API сервера телематики |
TRACCAR_USERNAME | Имя учётной записи для доступа к API сервера телематики |
TRACCAR_PASSWORD | Пароль учётной записи для доступа к API сервера телематики |
OSM_SSO_SECRET | Общий секрет сквозной авторизации между сервером приложений и сервисом графа УДС. Должен совпадать со значением, заданным сервису графа |
3.7 Сервер телематики
| Переменная | Назначение |
|---|---|
CONFIG_USE_ENVIRONMENT_VARIABLES | Признак чтения конфигурации сервера телематики из переменных окружения |
DATABASE_DRIVER | Класс JDBC-драйвера СУБД |
TRACCAR_DATABASE_URL | JDBC-строка подключения к базе телематики |
DATABASE_USER | Имя пользователя СУБД для сервера телематики |
DATABASE_PASSWORD | Пароль пользователя СУБД для сервера телематики |
3.8 Сервис графа УДС
| Переменная | Назначение |
|---|---|
OSM_DATABASE_URL | Строка подключения к базе данных графа УДС |
RAILS_RELATIVE_URL_ROOT | Префикс пути, по которому сервис публикуется за обратным прокси-сервером |
PIDFILE | Путь к файлу идентификатора процесса |
3.9 Подсистема видеонаблюдения
| Переменная | Назначение |
|---|---|
FRIGATE_RTSP_USER | Имя пользователя для подключения к видеопотокам камер по протоколу RTSP |
FRIGATE_RTSP_PASSWORD | Пароль для подключения к видеопотокам камер по протоколу RTSP |
FRIGATE_MQTT_USER | Имя пользователя для публикации событий видеоаналитики в брокер сообщений |
FRIGATE_MQTT_PASSWORD | Пароль для публикации событий видеоаналитики в брокер сообщений |
3.10 Веб-сервер
| Переменная | Назначение |
|---|---|
RAILS_APP | Адрес и порт сервера приложений для обратного проксирования |
OSM_BACKEND | Адрес и порт сервиса графа УДС |
FRIGATE_BACKEND | Адрес и порт подсистемы видеонаблюдения |
GO2RTC_BACKEND | Адрес и порт сервиса публикации видеопотоков |
TRACCAR_BACKEND | Адрес и порт сервера телематики |
RABBITMQ_BACKEND | Адрес и порт панели управления брокером сообщений |
SWAGGER_BACKEND | Адрес и порт сервиса описания прикладного API |
HTTP_PORT | Порт, на котором веб-интерфейс публикуется на сервере |
4. Файл описания сервисов
В каталоге установки создаётся файл docker-compose.yml. Значения всех
параметров подставляются из файла .env.
x-app-env: &app-env
RAILS_ENV: ${RAILS_ENV}
RAILS_MASTER_KEY: ${RAILS_MASTER_KEY}
DATABASE_URL: ${DATABASE_URL}
RABBITMQ_URL: ${RABBITMQ_URL}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
COOKIE_SECURE: ${COOKIE_SECURE}
TRACCAR_API_BASE: ${TRACCAR_API_BASE}
TRACCAR_USERNAME: ${TRACCAR_USERNAME}
TRACCAR_PASSWORD: ${TRACCAR_PASSWORD}
OSM_SSO_SECRET: ${OSM_SSO_SECRET}
x-app-common: &app-common
image: ${REGISTRY}/sl-api:${IMAGE_TAG}
restart: always
environment:
<<: *app-env
depends_on:
migrate:
condition: service_completed_successfully
database:
condition: service_healthy
rabbitmq:
condition: service_started
x-osm-env: &osm-env
RAILS_ENV: ${RAILS_ENV}
DATABASE_URL: ${OSM_DATABASE_URL}
OSM_SSO_SECRET: ${OSM_SSO_SECRET}
RAILS_RELATIVE_URL_ROOT: ${RAILS_RELATIVE_URL_ROOT}
PIDFILE: ${PIDFILE}
services:
database:
image: ${REGISTRY}/postgis:16-master
container_name: db
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 20s
timeout: 5s
retries: 20
start_period: 30s
database-traccar:
image: ${REGISTRY}/timescale-pg16:${IMAGE_TAG}
container_name: db_traccar
restart: always
environment:
POSTGRES_DB: ${TRACCAR_DB_NAME}
POSTGRES_USER: ${TRACCAR_DB_USER}
POSTGRES_PASSWORD: ${TRACCAR_DB_PASSWORD}
TIMESCALEDB_TELEMETRY: "off"
volumes:
- db_traccar_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TRACCAR_DB_USER} -d ${TRACCAR_DB_NAME}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s
database-osm:
image: ${REGISTRY}/timescale-pg16:${IMAGE_TAG}
container_name: db_osm
restart: always
environment:
POSTGRES_DB: ${OSM_DB_NAME}
POSTGRES_USER: ${OSM_DB_USER}
POSTGRES_PASSWORD: ${OSM_DB_PASSWORD}
TIMESCALEDB_TELEMETRY: "off"
volumes:
- db_osm_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${OSM_DB_USER} -d ${OSM_DB_NAME}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s
rabbitmq:
image: ${REGISTRY}/rabbitmq:${IMAGE_TAG}
container_name: rabbitmq
restart: always
command: >
sh -c "rabbitmq-plugins enable --offline rabbitmq_management rabbitmq_mqtt &&
rabbitmq-server"
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST}
volumes:
- rabbitmq_data:/var/lib/rabbitmq
migrate:
image: ${REGISTRY}/sl-api:${IMAGE_TAG}
container_name: migrate
restart: "no"
environment:
<<: *app-env
depends_on:
database:
condition: service_healthy
rabbitmq:
condition: service_started
command: bundle exec rails db:prepare
osm-migrate:
image: ${REGISTRY}/openstreetmap-website:${IMAGE_TAG}
container_name: osm-migrate
restart: "no"
environment:
<<: *osm-env
tmpfs:
- /tmp/pids
depends_on:
database-osm:
condition: service_healthy
command: bundle exec rails db:prepare
traccar:
image: ${REGISTRY}/traccar:${IMAGE_TAG}
container_name: traccar
restart: always
environment:
CONFIG_USE_ENVIRONMENT_VARIABLES: ${CONFIG_USE_ENVIRONMENT_VARIABLES}
DATABASE_DRIVER: ${DATABASE_DRIVER}
DATABASE_URL: ${TRACCAR_DATABASE_URL}
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
depends_on:
database-traccar:
condition: service_healthy
frigate:
image: ${REGISTRY}/frigate:stable
container_name: frigate
restart: always
environment:
FRIGATE_RTSP_USER: ${FRIGATE_RTSP_USER}
FRIGATE_RTSP_PASSWORD: ${FRIGATE_RTSP_PASSWORD}
FRIGATE_MQTT_USER: ${FRIGATE_MQTT_USER}
FRIGATE_MQTT_PASSWORD: ${FRIGATE_MQTT_PASSWORD}
volumes:
- frigate_config:/config
- frigate_media:/media/frigate
osm-web:
image: ${REGISTRY}/openstreetmap-website:${IMAGE_TAG}
container_name: osm-web
restart: always
environment:
<<: *osm-env
tmpfs:
- /tmp/pids
depends_on:
osm-migrate:
condition: service_completed_successfully
command: bundle exec rails s -p 3000 -b 0.0.0.0
app:
<<: *app-common
container_name: app
command: bundle exec rails server -b 0.0.0.0 -p 3000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/up"]
interval: 30s
timeout: 10s
retries: 10
start_period: 20s
worker:
<<: *app-common
container_name: worker
command: bundle exec rails solid_queue:start
position-consume:
<<: *app-common
container_name: position-consume
command: bundle exec rake rabbitmq:consume:positions
position-cache-consume:
<<: *app-common
container_name: position-cache-consume
command: bundle exec rake rabbitmq:consume:position_cache
event-consume:
<<: *app-common
container_name: event-consume
command: bundle exec rake rabbitmq:consume:events
video-consume:
<<: *app-common
container_name: video-consume
command: bundle exec rake rabbitmq:consume:frigate
web:
image: ${REGISTRY}/sl-web:${IMAGE_TAG}
container_name: web
restart: always
environment:
RAILS_APP: ${RAILS_APP}
OSM_BACKEND: ${OSM_BACKEND}
FRIGATE_BACKEND: ${FRIGATE_BACKEND}
GO2RTC_BACKEND: ${GO2RTC_BACKEND}
TRACCAR_BACKEND: ${TRACCAR_BACKEND}
RABBITMQ_BACKEND: ${RABBITMQ_BACKEND}
SWAGGER_BACKEND: ${SWAGGER_BACKEND}
ports:
- "${HTTP_PORT}:80"
depends_on:
app:
condition: service_healthy
osm-web:
condition: service_started
volumes:
db_data:
db_traccar_data:
db_osm_data:
rabbitmq_data:
frigate_config:
frigate_media:
5. Порядок установки
5.1 Загрузка образов
cd /opt/rubin-t
docker compose pull
Команда загружает образы всех сервисов из реестра.
| Переменная | Назначение в команде |
|---|---|
REGISTRY | Адрес реестра, из которого загружаются образы |
IMAGE_TAG | Версия загружаемых образов |
5.2 Запуск серверов баз данных и брокера сообщений
docker compose up -d database database-traccar database-osm rabbitmq
| Переменная | Назначение в команде |
|---|---|
POSTGRES_DB | Имя создаваемой прикладной базы данных |
POSTGRES_USER | Имя создаваемого пользователя прикладной базы |
POSTGRES_PASSWORD | Пароль пользователя прикладной базы |
TRACCAR_DB_NAME | Имя создаваемой базы телематики |
TRACCAR_DB_USER | Имя пользователя базы телематики |
TRACCAR_DB_PASSWORD | Пароль пользователя базы телематики |
OSM_DB_NAME | Имя создаваемой базы графа УДС |
OSM_DB_USER | Имя пользователя базы графа УДС |
OSM_DB_PASSWORD | Пароль пользователя базы графа УДС |
RABBITMQ_USER | Имя создаваемого пользователя брокера сообщений |
RABBITMQ_PASSWORD | Пароль пользователя брокера сообщений |
RABBITMQ_VHOST | Виртуальный хост брокера, создаваемый при запуске |
Дождитесь перехода серверов баз данных в состояние healthy:
docker compose ps
5.3 Инициализация схем баз данных
docker compose run --rm migrate
| Переменная | Назначение в команде |
|---|---|
DATABASE_URL | Подключение к прикладной базе, схема которой создаётся |
RAILS_MASTER_KEY | Ключ расшифровки настроек приложения |
RAILS_ENV | Режим работы, определяющий набор применяемых настроек |
ADMIN_PASSWORD | Пароль учётной записи администратора, создаваемой при первичной инициализации |
docker compose run --rm osm-migrate
| Переменная | Назначение в команде |
|---|---|
OSM_DATABASE_URL | Подключение к базе графа УДС, схема которой создаётся |
RAILS_ENV | Режим работы сервиса графа УДС |
PIDFILE | Путь к файлу идентификатора процесса |
Контейнеры миграций завершают работу после выполнения и не остаются запущенными.
5.4 Запуск сервера телематики и подсистемы видеонаблюдения
docker compose up -d traccar frigate
| Переменная | Назначение в команде |
|---|---|
CONFIG_USE_ENVIRONMENT_VARIABLES | Чтение конфигурации сервера телематики из переменных окружения |
DATABASE_DRIVER | Класс JDBC-драйвера, используемого сервером телематики |
TRACCAR_DATABASE_URL | Подключение сервера телематики к своей базе данных |
DATABASE_USER | Имя пользователя СУБД для сервера телематики |
DATABASE_PASSWORD | Пароль пользователя СУБД для сервера телематики |
FRIGATE_RTSP_USER | Учётная запись подключения к видеопотокам камер |
FRIGATE_RTSP_PASSWORD | Пароль подключения к видеопотокам камер |
FRIGATE_MQTT_USER | Учётная запись публикации событий видеоаналитики в брокер |
FRIGATE_MQTT_PASSWORD | Пароль публикации событий видеоаналитики в брокер |
5.5 Запуск сервера приложений и обработчиков
docker compose up -d app worker \
position-consume position-cache-consume event-consume video-consume
Запускаемые сервисы:
| Сервис | Назначение |
|---|---|
app | Сервер приложений, обрабатывающий запросы прикладного API |
worker | Фоновые и периодические задачи: статистика, прогнозы, уведомления, синхронизация |
position-consume | Потребитель очереди позиций ТС |
position-cache-consume | Потребитель очереди кеша текущих позиций |
event-consume | Потребитель очереди событий мониторинга |
video-consume | Потребитель очереди сообщений видеоаналитики |
| Переменная | Назначение в команде |
|---|---|
RAILS_ENV | Режим работы сервера приложений и обработчиков |
RAILS_MASTER_KEY | Ключ расшифровки настроек приложения |
DATABASE_URL | Подключение к прикладной базе данных |
RABBITMQ_URL | Подключение к брокеру сообщений, из очередей которого читают потребители |
COOKIE_SECURE | Передача сессионных cookie только по защищённому соединению |
TRACCAR_API_BASE | Адрес API сервера телематики для синхронизации геозон и объектов |
TRACCAR_USERNAME | Учётная запись доступа к API сервера телематики |
TRACCAR_PASSWORD | Пароль доступа к API сервера телематики |
OSM_SSO_SECRET | Общий секрет сквозной авторизации с сервисом графа УДС |
5.6 Запуск сервиса графа УДС и веб-сервера
docker compose up -d osm-web web
| Переменная | Назначение в команде |
|---|---|
OSM_DATABASE_URL | Подключение сервиса графа УДС к своей базе данных |
RAILS_RELATIVE_URL_ROOT | Префикс пути публикации сервиса графа за обратным прокси |
OSM_SSO_SECRET | Общий секрет сквозной авторизации с сервером приложений |
PIDFILE | Путь к файлу идентификатора процесса сервиса графа |
RAILS_APP | Адрес сервера приложений, на который веб-сервер проксирует запросы API |
OSM_BACKEND | Адрес сервиса графа УДС для проксирования |
FRIGATE_BACKEND | Адрес подсистемы видеонаблюдения для проксирования |
GO2RTC_BACKEND | Адрес сервиса публикации видеопотоков для проксирования |
TRACCAR_BACKEND | Адрес сервера телематики для проксирования |
RABBITMQ_BACKEND | Адрес панели управления брокером сообщений |
SWAGGER_BACKEND | Адрес сервиса описания прикладного API |
HTTP_PORT | Порт сервера, на котором публикуется веб-интерфейс |
5.7 Запуск всех сервисов одной командой
После первичной инициализации весь состав запускается одной командой:
docker compose up -d
Команда использует все переменные, перечисленные в разделе 3.
6. Проверка работоспособности
Состояние контейнеров:
docker compose ps
Все сервисы должны находиться в состоянии running, а сервер приложений
и серверы баз данных — в состоянии healthy.
Проверка доступности сервера приложений:
docker compose exec app curl -f http://localhost:3000/up
Просмотр журнала сервиса:
docker compose logs -f app
Веб-интерфейс открывается в браузере по адресу сервера и порту, заданному
переменной HTTP_PORT. Вход выполняется под учётной записью администратора,
пароль которой задан переменной ADMIN_PASSWORD.
После первого входа пароль администратора необходимо изменить.
7. Публикация по защищённому соединению
Для промышленной эксплуатации веб-интерфейс публикуется по протоколу HTTPS.
Терминирование защищённого соединения выполняется внешним обратным
прокси-сервером, направляющим запросы на порт, заданный переменной HTTP_PORT.
При работе по HTTPS переменная COOKIE_SECURE устанавливается в true, после
чего сервер приложений перезапускается:
docker compose up -d --force-recreate app worker
| Переменная | Назначение в команде |
|---|---|
COOKIE_SECURE | Новое значение признака защищённых cookie, применяемое при пересоздании контейнеров |
Обратный прокси-сервер должен передавать заголовки Upgrade и Connection —
без них не работают соединения WebSocket, по которым доставляются данные
реального времени.
8. Обновление
cd /opt/rubin-t
# 1. Задать новую версию в переменной IMAGE_TAG файла .env
# 2. Загрузить образы новой версии
docker compose pull
# 3. Применить миграции схем баз данных
docker compose run --rm migrate
docker compose run --rm osm-migrate
# 4. Перезапустить сервисы на новых образах
docker compose up -d
| Переменная | Назначение в командах обновления |
|---|---|
IMAGE_TAG | Версия, на которую выполняется обновление |
REGISTRY | Реестр, из которого загружаются образы новой версии |
DATABASE_URL, OSM_DATABASE_URL | Базы данных, к схемам которых применяются миграции |
RAILS_MASTER_KEY | Ключ расшифровки настроек при выполнении миграций |
Перед обновлением выполняется резервное копирование баз данных.
9. Резервное копирование и восстановление
Резервная копия прикладной базы данных:
docker compose exec -T database \
pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc > backup_app.dump
| Переменная | Назначение в команде |
|---|---|
POSTGRES_USER | Пользователь СУБД, от имени которого выполняется выгрузка |
POSTGRES_DB | Имя выгружаемой прикладной базы данных |
Аналогично выполняется резервное копирование базы телематики (сервис
database-traccar, переменные TRACCAR_DB_USER и TRACCAR_DB_NAME) и базы
графа УДС (сервис database-osm, переменные OSM_DB_USER и OSM_DB_NAME).
Восстановление:
docker compose exec -T database \
pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean < backup_app.dump
| Переменная | Назначение в команде |
|---|---|
POSTGRES_USER | Пользователь СУБД, от имени которого выполняется восстановление |
POSTGRES_DB | Имя восстанавливаемой базы данных |
Видеоархив и конфигурация подсистемы видеонаблюдения хранятся в томах
frigate_media и frigate_config и копируются средствами резервного
копирования файловой системы.
10. Остановка и удаление
Остановка с сохранением данных:
docker compose down
Остановка с удалением данных:
docker compose down -v
Ключ -v удаляет тома с базами данных и видеоархивом. Операция необратима;
применяйте её только при полном удалении установки.
Версия для печати
⬇ Скачать PDF