Docker контейнеризация

Контейнеризация Kepler.gl приложения начинается с понимания того, что библиотека представляет собой React-компонент с высокой зависимостью от окружения сборки, браузерного рендеринга и ресурсов клиента. В отличие от серверных решений, основная логика визуализации выполняется в браузере, однако Docker используется для стандартизации сборки, доставки и запуска веб-приложения, в которое встроен Kepler.gl.

Kepler.gl интегрируется в React-приложение как UI-компонент, работающий поверх состояния Redux. Типичная структура включает:

  • фронтенд на React
  • Redux store для управления слоями и данными
  • модуль загрузки геоданных (CSV, GeoJSON, JSON)
  • визуальный слой Kepler.gl
  • сервер статики (или SSR-платформа)

Контейнеризация в данном контексте решает задачи:

  • воспроизводимой сборки
  • изоляции зависимостей Node.js и npm
  • унифицированного деплоя
  • запуска в облачной инфраструктуре

Подготовка проекта к контейнеризации

Перед созданием контейнера важно обеспечить корректную сборку фронтенда. Kepler.gl чувствителен к версиям зависимостей React и Webpack, поэтому фиксирование версий является обязательным шагом.

Пример структуры проекта:

/app
  /src
    index.js
    store.js
    map-config.js
  package.json
  package-lock.json
  webpack.config.js

В package.json фиксируются ключевые зависимости:

  • react
  • react-dom
  • redux
  • kepler.gl
  • styled-components (часто используется внутри экосистемы)

Особое внимание уделяется совместимости версий Redux и Kepler.gl, поскольку несоответствие приводит к ошибкам подключения store.

Dockerfile для production-сборки

Основой контейнеризации является многоступенчатая сборка, позволяющая отделить этап компиляции от этапа исполнения.

FROM node:20-alpine AS build

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

RUN npm run build

На этапе build выполняется сборка React-приложения в статические файлы. Далее создаётся минимальный runtime-образ.

FROM nginx:1.25-alpine

COPY --from=build /app/build /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

Такой подход позволяет значительно уменьшить размер итогового образа и ускорить его запуск.

Конфигурация Nginx

Kepler.gl-приложение работает как SPA, поэтому сервер должен корректно обрабатывать маршрутизацию.

Базовая конфигурация nginx:

server {
  listen 80;
  server_name localhost;

  root /usr/share/nginx/html;

  location / {
    try_files $uri /index.html;
  }

  gzip on;
  gzip_types text/plain application/javascript text/css application/json;
}

Ключевой момент — директива try_files, обеспечивающая корректную работу React Router.

Docker Compose для комплексного развертывания

При наличии дополнительных сервисов (API для геоданных, обработка файлов, авторизация) используется docker-compose.

version: '3.9'

services:
  frontend:
    build: .
    ports:
      - "3000:80"
    restart: always

  api:
    build: ./api
    ports:
      - "4000:4000"

В такой архитектуре Kepler.gl работает как фронтенд-клиент, получающий данные через REST или GraphQL API.

Передача данных в Kepler.gl внутри контейнера

Kepler.gl требует правильной инициализации состояния. Обычно данные передаются через Redux action:

import { addDataToMap } from 'kepler.gl/actions';

dispatch(
  addDataToMap({
    datasets: {
      info: {
        label: 'dataset',
        id: 'data_1'
      },
      data: geojsonData
    },
    options: {
      centerMap: true,
      readOnly: false
    }
  })
);

В контейнеризированной среде данные чаще всего загружаются:

  • из внешнего API
  • из смонтированного volume
  • из статического JSON внутри образа

Использование volumes для данных

При работе с большими геоданными нецелесообразно пересобирать контейнер при каждом изменении файлов. Используются Docker volumes:

docker run -v $(pwd)/data:/app/data kepler-app

Это позволяет динамически обновлять датасеты без пересборки образа.

Оптимизация производительности контейнера

Kepler.gl работает с WebGL, поэтому основная нагрузка ложится на клиентский браузер, однако контейнеризация может влиять на скорость загрузки приложения.

Ключевые оптимизации:

Минимизация размера образа

Использование alpine-образов снижает размер контейнера до десятков мегабайт.

Сжатие статики

Включение gzip и brotli на уровне nginx ускоряет загрузку больших JavaScript-бандлов.

Кэширование

location /static/ {
  expires 1y;
  add_header Cache-Control "public, immutable";
}

Это особенно важно для файлов webpack build.

Переменные окружения

Хотя Kepler.gl не зависит напрямую от backend-конфигурации, в контейнере часто используются переменные окружения для управления поведением приложения:

  • REACT_APP_API_URL — адрес API
  • REACT_APP_MAPBOX_TOKEN — токен Mapbox (если используется кастомный стиль карт)
  • REACT_APP_ENV — режим работы (development/production)

Передача:

docker run -e REACT_APP_API_URL=https://api.example.com kepler-app

Интеграция с Mapbox в контейнерной среде

Kepler.gl часто использует Mapbox GL для рендеринга карт. В контейнере важно правильно передавать токен:

const mapConfig = {
  mapboxApiAccessToken: process.env.REACT_APP_MAPBOX_TOKEN
};

Ошибки конфигурации приводят к пустой карте без базового слоя, при этом приложение остаётся функциональным, но визуально неполным.

Многоэтапная сборка с кэшированием зависимостей

Для ускорения CI/CD процессов используется разделение установки зависимостей:

FROM node:20-alpine AS deps

WORKDIR /app
COPY package*.json ./
RUN npm ci

Далее:

FROM node:20-alpine AS build

WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npm run build

Такой подход позволяет использовать Docker layer caching, что существенно ускоряет повторные сборки.

Развёртывание в облачной среде

Контейнер с Kepler.gl может быть развернут в:

  • Kubernetes
  • Docker Swarm
  • AWS ECS
  • Google Cloud Run

В Kubernetes обычно используется следующая схема:

  • Deployment для фронтенда
  • Service типа ClusterIP или LoadBalancer
  • Ingress для маршрутизации

Пример Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kepler-frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: kepler
  template:
    metadata:
      labels:
        app: kepler
    spec:
      containers:
        - name: frontend
          image: kepler-app:latest
          ports:
            - containerPort: 80

Безопасность контейнеризации

При работе с Kepler.gl важно учитывать:

  • отсутствие выполнения серверного кода внутри фронтенда
  • изоляцию API ключей (не хранить секреты в образе)
  • использование read-only файловой системы для nginx-контейнера
  • ограничение прав пользователя внутри контейнера

Дополнительно применяется запуск nginx не от root:

USER nginx

Логирование и диагностика

Контейнерная среда упрощает сбор логов через stdout/stderr. Nginx-логи направляются в стандартные потоки:

access_log /dev/stdout;
error_log /dev/stderr;

Это позволяет интегрировать контейнер с системами мониторинга:

  • Prometheus
  • Grafana
  • ELK stack

Типовые проблемы контейнеризации Kepler.gl

Белый экран при запуске

Причины:

  • неправильный base path в webpack
  • отсутствие index.html fallback
  • ошибка сборки React

Ошибки WebGL

Причины:

  • запуск в среде без GPU ускорения
  • ограничение браузерного окружения в headless режиме

Потеря данных при пересборке

Причины:

  • отсутствие volumes
  • хранение данных внутри ephemeral слоя контейнера

Практика организации production-сборки

В стабильной конфигурации применяется следующая модель:

  • отдельный этап сборки
  • минимальный runtime-образ nginx
  • внешнее API для данных
  • конфигурация через environment variables
  • статическая раздача build-артефактов

Такая структура обеспечивает предсказуемость поведения приложения независимо от среды выполнения и упрощает масштабирование при увеличении нагрузки на визуализацию геоданных.