Docker: лучшие практики и самые используемые команды

Как NexTool запускает и сопровождает GLPI в Docker для клиентов: архитектура с отдельными томами, docker-compose для продакшена, команды, которые мы действительно используем в поддержке, и лучшие практики (фиксированный тег, запуск не от root, secrets и резервное копирование томов).

В этой статьеРазделов: 4

Docker перестал быть модой и стал стандартным способом, которым мы поставляем и сопровождаем GLPI для клиентов. Вместо установки PHP, MariaDB и веб-сервера прямо в операционную систему мы упаковываем GLPI и его зависимости в версионируемые контейнеры — это делает установку воспроизводимой, откат тривиальным, а обслуживание предсказуемым. В этом руководстве собраны команды, которые мы действительно используем в повседневном сопровождении, и практики, которые мы применяем, чтобы безопасно запускать службу поддержки (Service Desk) в продакшене.

Как мы запускаем GLPI в Docker

Архитектура, которую мы стандартизировали, намеренно компактна: один контейнер для приложения GLPI (PHP-FPM и веб-сервер), один для СУБД MariaDB и, когда объём заявок это оправдывает, Redis для сессий и кэша. Всё оркестрируется одним docker-compose.yml за обратным прокси с TLS. Данные, которые должны пережить любое пересоздание контейнера, — база данных, загруженные файлы и конфигурация — хранятся в именованных томах, а не внутри контейнера. Именно это разделение между кодом (образ, одноразовый) и состоянием (том, бесценный) превращает обновление версии GLPI в операцию на несколько минут, а не на целую ночь.

Артефакт: стек GLPI, который мы разворачиваем

Это каркас compose, который поднимается при каждом внедрении, уже с отдельными томами и без учётных данных открытым текстом внутри файла:

# docker-compose.yml - production GLPI stack
services:
  glpi:
    image: glpi/glpi:11.0        # pinned tag, never 'latest'
    restart: unless-stopped
    depends_on:
      - glpidb
    volumes:
      - glpi_files:/var/glpi     # uploaded files and GLPI configuration
    networks: [ edge, internal ]

  glpidb:
    image: mariadb:11.4
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: glpi
      MARIADB_USER: glpi
      MARIADB_PASSWORD_FILE: /run/secrets/db_password   # password via secret, never plaintext
    volumes:
      - glpi_db:/var/lib/mysql   # the database lives here, outside the container
    networks: [ internal ]
    secrets: [ db_password ]

volumes:
  glpi_files:
  glpi_db:

networks:
  edge:      # exposed to the reverse proxy
  internal:  # private database, no external route
    internal: true

secrets:
  db_password:
    file: ./secrets/db_password.txt   # file 600, outside git

Команды, которые мы действительно используем в сопровождении

В повседневной поддержке небольшой набор команд решает большинство задач. Вот те, что команда набирает почти не задумываясь:

КомандаКогда мы используем её при сопровождении GLPI
docker compose up -dПоднимает или обновляет стек после изменения compose или тега образа
docker compose logs -f glpiОтслеживает ошибку в реальном времени, когда клиент сообщает о сбое
docker compose exec glpi bashВходит в контейнер, чтобы выполнить php bin/console (cron, кэш, миграция)
docker compose psПроверяет, запущены ли приложение и СУБД, прежде чем открывать инцидент
docker statsДиагностирует пиковую нагрузку на CPU и память, когда жалуются на медленную работу
docker compose down (без -v)Пересоздаёт стек с сохранением томов; -v удалил бы базу данных

Типичная — и дорогая — ошибка, которую мы видели у тех, кто работает без осторожности, — выполнить docker compose down -v, думая, что это просто перезапустит контейнеры. Флаг -v удаляет тома, а вместе с ними и всю базу данных GLPI. При сопровождении мы считаем -v деструктивной командой: она не фигурирует ни в одной операционной процедуре, а любая резервная копия тома проверяется перед любым обслуживанием, которое хотя бы близко к ней подходит.

Лучшие практики, которые мы применяем в продакшене

  • Фиксированный тег, никогда latest — мы фиксируем версию образа (например, glpi/glpi:11.0, mariadb:11.4), чтобы pull не принёс неожиданную версию посреди обслуживания.
  • Не root и минимальные привилегии — приложение не работает от root, а СУБД находится в сети internal, без внешнего маршрута, и доступна только контейнеру GLPI.
  • Secrets вне compose — пароль СУБД передаётся через Docker secret или файл, смонтированный только для чтения, а не через environment: открытым текстом, закоммиченным в git.
  • Том — это святое — база данных, файлы и конфигурация в именованных томах, с ежедневным логическим дампом базы данных, проверенным реальным восстановлением (резервная копия, которую ни разу не восстанавливали, — не резервная копия).
  • Компактные и просканированные образы — slim-основа и сканирование Trivy или Docker Scout, чтобы не тащить известные CVE в продакшен.

Деталь, которую знают только те, кто сопровождает GLPI в контейнерах: обновление версии GLPI — это не просто смена тега образа. После docker compose up -d с новым образом нужно запустить миграцию базы данных через консоль внутри контейнера, иначе приложение поднимется со ссылкой на старую схему и вернёт ошибку 500 на первом же экране. Поэтому наша процедура обновления всегда выстраивает один и тот же порядок: резервная копия тома базы данных, смена тега, up -d, миграция и только затем открытие доступа пользователям. Когда клиент использует плагин NexTool, этот же запуск перезагружает модули экосистемы, поэтому мы также проверяем работоспособность интеграций (очереди вебхуков, синхронизацию), прежде чем признать среду стабильной.

Если ваш GLPI всё ещё установлен прямо на сервер, без отдельных томов и проверенных резервных копий, NexTool внедрит и будет сопровождать эту среду в Docker правильно — с версионируемым стеком, предсказуемыми обновлениями и наблюдаемостью рядом со службой поддержки. Свяжитесь с нами по поводу сопровождения GLPI в контейнерах.


Проверено командой NexTool Solutions.

Часто задаваемые вопросы

Потому что стек в контейнерах воспроизводим, а состояние (база данных, файлы, конфигурация) изолировано в томах. Это делает обновление версии предсказуемым, откат тривиальным, а обслуживание — операцией на несколько минут вместо ручной установки, которую трудно повторить в другой среде.

В повседневной работе мы используем docker compose up -d (поднять/обновить), docker compose logs -f glpi (отслеживать ошибку в реальном времени), docker compose exec glpi bash (запустить консоль GLPI), docker compose ps (проверить, работают ли приложение и СУБД) и docker stats (диагностировать пиковую нагрузку на CPU и память).

Сама по себе docker compose down останавливает и удаляет контейнеры, но сохраняет именованные тома — база данных остаётся нетронутой. Данные удаляет флаг -v (docker compose down -v), который удаляет и тома. Мы считаем -v деструктивной командой, и она никогда не входит в регламентные процедуры.

Резервировать нужно состояние, а не образ. Мы делаем ежедневный логический дамп базы данных (из контейнера MariaDB) и копию тома с загруженными файлами и конфигурацией. И главное — проверяем восстановление: резервная копия, которую ни разу не восстанавливали, не считается резервной копией.

Порядок важен: сначала резервная копия тома базы данных, затем смена тега образа, docker compose up -d, миграция базы данных через консоль внутри контейнера и только потом открытие доступа. Если пропустить миграцию, приложение поднимется со старой схемой и будет возвращать ошибку 500.

Нужна помощь?