Этот сайт работает на домашнем сервере с 3,2 ГБ памяти, рядом с десятком других проектов. Весь сайт — пять контейнеров, и вместе они занимают около 310 МБ. Разберу, из чего он состоит и какие настройки по умолчанию мы поменяли.

Это первая часть цикла «Сервер для WordPress». Дальше — пул PHP-FPM и его аварии, свой образ PHP, Redis, сеть Docker, почта, сертификаты, диск, крон и сборка.

Пять контейнеров

КонтейнерЧто делаетПамять сейчас
nginxотдаёт статику и кэш страниц, передаёт PHP остальное9 МБ
phpPHP-FPM: WordPress, ajax, крон271 МБ
mariadbбаза23 МБ
redisобъектный кэш WordPress7 МБ
маленький проксивыход к одному внешнему APIменьше 1 МБ

Плюс два общих сервиса на весь сервер: traefik принимает HTTPS и раздаёт запросы сайтам по имени, а планировщик запускает крон каждого сайта раз в минуту (почему крон должен быть системным — во второй части цикла про WordPress на кэшируемом сайте).

Сокеты вместо сети

nginx передаёт запросы в PHP-FPM, а PHP ходит в базу через Unix-сокеты в общих томах, без TCP:

php:
  volumes:
    - phpsocket:/var/run/php       # nginx → PHP-FPM
    - mysqlsocket:/var/run/mysqld  # PHP → MariaDB
// wp-config.php
define('DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock');

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

База на диете

MariaDB по умолчанию рассчитана на сервер, где она одна. У нас база своя у каждого сайта, и память нужно делить. Для небольшого сайта хватает таких настроек:

mariadb:
  command: ["mariadbd",
    "--innodb-buffer-pool-size=16M",
    "--innodb-log-file-size=16M",
    "--performance-schema=OFF",
    "--key-buffer-size=8M",
    "--tmp-table-size=16M",
    "--max-heap-table-size=16M",
    "--max-connections=30",
    "--table-open-cache=64"]

Итог — 23 МБ на базу. Для каталога на десятки тысяч товаров буфер нужен больше: его размер подбирают по объёму активных данных, а не ставят «на всякий случай».

Отключение performance_schema само по себе экономит заметную часть памяти: это внутренняя статистика базы, которая на маленьком сайте никому не нужна.

PHP-FPM: процессы по требованию

[www]
pm = ondemand
pm.max_children = 6
pm.process_idle_timeout = 30s
request_terminate_timeout = 300s
request_slowlog_timeout = 5s
  • ondemand — процессы запускаются при запросах и гаснут через 30 секунд простоя. Для сайта, который почти весь отдаётся из кэша, держать процессы наготове незачем;
  • 6 процессов — потолок, который сервер выдержит вместе с соседями;
  • request_terminate_timeout — предохранитель от зависших запросов. Без него один запрос однажды положил сайт на 5 часов 40 минут — об этом вторая часть;
  • slowlog — стек каждого запроса дольше 5 секунд в журнал.

Для сайта с постоянным трафиком без кэша ondemand не подходит: запуск процесса на каждый всплеск добавляет задержку. Там нужен dynamic с тёплым запасом — и своя грабля, о ней третья часть.

Redis только внутри

Redis подключён к отдельной сети с internal: true: у неё нет выхода наружу, и кроме PHP туда никто не попадает. Пароль у такого Redis — дополнительная мера, а не единственная.

networks:
  redisnet:
    internal: true

Здесь Redis — объектный кэш WordPress, и настроен он противоположно Redis под кэш фрагментов на других наших сайтах. Почему — шестая часть.

Журналы — в системный журнал

logging:
  driver: journald
  options:
    tag: "site-php"

Журналы всех контейнеров попадают в journald с меткой сайта: их не надо ротировать вручную, а нужное ищется одной командой — journalctl -t site-php --since "-1 hour".

Что дальше

Почти все аварии, которые мы разбирали на своих серверах, случились не от нагрузки, а от настроек по умолчанию. С самой дорогой из них — пулом PHP-FPM без предохранителя — начнём завтра.

Нужен сервер под WordPress или навести порядок на текущем?

Пришлите, что у вас сейчас, — соберу стек, который не падает от одного зависшего запроса.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.