Понадобилось расширение PHP для Redis. Простой вопрос — «что сейчас в образе и как его пересобрать» — оказался без ответа: Dockerfile образа был утрачен, состав пришлось восстанавливать по слоям. После этого Dockerfile лежит в git, а сборка заняла шесть попыток — каждая грабля теперь записана прямо в нём.
Это пятая часть цикла «Сервер для WordPress».
Почему вообще свой образ
Официальный образ PHP с Docker Hub хорош, пока хватает его расширений. Нам нужны ещё ffmpeg для обложек видео и phpredis для кэша, и ставить их при каждом запуске контейнера — значит ждать минуты и зависеть от того, доступны ли сейчас зеркала пакетов. Свой образ собирается один раз и лежит в реестре.
Правило: Dockerfile в git
Образ без исходника — чёрный ящик. Чтобы добавить одно расширение, нужно знать всё остальное, что в нём есть, а узнать это можно только раскопкой слоёв. Теперь образ устроен в два этажа:
| Тег | Что внутри |
|---|---|
php:8.3-media-utils-extend | база + ffmpeg и ffprobe (исходник этого этажа утрачен) |
php:8.3-media-utils-extend-redis | поверх: phpredis 6.2.0, igbinary, msgpack; PHP 8.3.24 |
Второй этаж собирается поверх первого — бинарники ffmpeg живут только в нём. Новые изменения — только через Dockerfile в git, никаких «зашёл в контейнер и доставил».
Потолок версии — не там, где ждёшь
Образ построен на Fedora 40 с PHP из репозитория remi. Кажется, что версию PHP ограничивает репозиторий. Нет: для Fedora 40 там есть всё от 8.0 до 8.4. Потолок 8.4 держит сама база — выше только со сменой системы, а база чужая и её исходников у нас нет. Цена зависимости от чужого образа видна только тогда, когда захочешь сделать шаг дальше.
Шесть граблей сборки
--resolve— опцияdnf download, а неdnf install;dnf downloadв Fedora 40 требует плагина:dnf install 'dnf-command(download)';- пакеты PHP связаны точной версией: обновить одну библиотеку нельзя, обновлять весь набор — у нас 15 пакетов;
dnf downloadтянет и 32-битные пакеты, а rpm потом требует 32-битную glibc, которой в образе нет. Лечится--arch x86_64,noarch;- обновление
libzstdломаетlibzstd-devel; расширению хватает уже установленной версии; - часть пакетов уже нужной версии, и
rpm -Uvhбез--replacepkgsна них падает.
Каждая записана комментарием в Dockerfile рядом с местом, где выстрелила. Следующий, кто будет поднимать версию, не потратит на них вечер.
Реестр и токен
# логин — имя пользователя в GitLab, токен — со scope read_registry и write_registry
docker login registry.gitlab.com -u <логин> --password-stdin < token.txt
- токен подавать через
--password-stdin, а не флагом-p— иначе он останется в истории оболочки; - первая отправка может упасть с
blob unknown to registry— это сбой реестра, лечится повтором.
Как добавить расширение теперь
- дописать пакет в список в Dockerfile;
- собрать, проверить
php -mв новом образе; - отправить в реестр с новым тегом;
- сменить тег в compose сайта и пересоздать контейнер PHP — сначала на тесте.
На сервере образ, про который никто не знает, что в нём?
Пришлите, что используете, — соберу образ с Dockerfile в git и понятной процедурой обновления.
// загружаю комментарии…