Как перенести WordPress сайт в Docker

WordPress в Docker

Ни один из моих блогов на WordPress не установлен в Docker контейнерах, и об этом я жалею с самого момента их создания. Мне хватило всего пары недель, чтобы забыть, как именно настроены сервера, зачем на них включена та или иная фича, и теперь во время каждого апдэйда приходится молиться всем известным богам программирования, потому что если что-то пойдёт не так, я уже без понятия, как это разруливать. Даже просто перенести сайт на новый сервер было бы подвигом.

С Докер контейнерами таких проблем бы не было. Взял Dockerfile или docker-compose.yml, взял volumes с данными, перенёс на другую машину, и всё. Можно было бы даже запустить реплики блогов дома, чтобы на них экспериментировать, проверять апдэйты и надругивать новые фичи.

Но не всё потеряно. Прогрессирующее старпёрство мне уже не позволит просто так вот взять и выкатить Docker в свой «продакшен», но создать локальную докеризированную реплику одного из блогов определённо можно. А там, если всё пойдёт нормально, можно и в большой интернет.

Шаг 0: Задумка

Теоретически, задача не сложная, так как у Вордпресса уже есть свой собственный Докер образ. Даже больше, у них есть и пример docker-compose.yml файла, который и WordPress запустит, и MySQL к нему добавит, так что сразу есть с чего начать:

Если к полученной паре контейнеров прикрутить backup сайта, то, по идее, это должно сгодиться в качестве полноценной реплики. Конечно, могут начаться какие-нибудь проблемы, связанные с отсутствием доменного имени на локальной машине, но, думаю, что-нибудь можно придумать. Итак, начнём.

Шаг 1: Делаем бэкап блога

Вот что мне нравится в Вордпрессе, так это как легко с ним сделать полный бэкап. Архивируем www папку, архивируем дамп базы данных, и всё, гештальт завершён. В качестве подопытной морской свинки я возьму свой более свежий блог — codeblog.dotsandbrackets.com, и без лишних церемоний сделаю ему бэкап веб-контента с tar и дамп базы данных с mysqldump и gzip:

При помощи scp копирую получившиеся два архива на локальную машину, и понеслась, родная.

Шаг 2: Подключаем веб-контент к контейнеру

Я полазил в Dockerfile для WordPress образа, и, судя по всему, его авторы будут обновлять настройки (имя базы, логин, и т. п.) в вордпрессовском wp-config.php, если те передать в контейнер с переменными окружения. Удобно. Значит я могу не заморачиваться переносом mysql аккаунтов с «продакшен» машины, а создать новые или даже использовать root (значение по умолчанию).

В том же Dockerfile я заметил, что вордпрессовский контент будет лежать в папке /var/www/html (это ещё и volume). По идее, можно просто подключить туда мой бэкап, и вебовская часть контента будет восстановлена.

Наконец, моя прогрессирующая интернет паранойя больше не позволяет мне ложить имена и пароли открытым текстом в Docker-файлы, так что я лучше их положу в локальные переменные окружения и буду импортировать уже оттуда:

Теперь распаковываем бэкап с вэб-контентом, подкручиваем его к docker-compose.yml, задаём там же пустую базу данных, и пробуем запустить (кстати, всё это происходит на маке, но на никсе будет то же самое):

WordPress в Docker: установка

Ну, Вордпресс определённо запустился. Но как определить, это он «мой» контент использует сейчас, или «свой»? Можно, конечно, влезть в контейнер и посмотреть внутри, но лучше я подключу настоящую базу, и всё сразу станет яснее. Так что останавливаем запущенные контейнеры и вперёд к импорту данных:

Шаг 3: Импортируем данные

Краткий сеанс гугла меня очень порадовал. Оказывается, если примонтировать к mysql контейнеру дамп базы вот к этой папке — /docker-entrypoint-initdb.d/, то при первом запуске mysql его автоматически импортирует. Он даже архивы понимает, так что можно сдать ему мой дамп как он есть:

Снова запускаем контейнеры:

WordPress в Docker с импортированной базой данных

Ха! Всё запустилось. Но как-то не до конца. Когда я попытаюсь залогиниться, то меня редиректит на живой codeblog.dotsandbrackets.com. То есть где-то в базе жёстко прописано доменное имя, и его нужно оттуда выковырять.

Шаг 4. Исправляем доменное имя

Ещё один сеанс гугла, и решение найдено. Заменить имя может вот такой скрипт:

mysql’овская папка docker-entrypoint-initdb.d может принимать больше чем один файл (запускает в алфавитном порядке), так что создам-ка я какой-нибудь migrate.sql, пропишу в нём новые имена, да подключу к контейнеру:

Запускаем:

Логин и админка теперь работают. Правда, Jetpack плагин выглядит печальным, так как он сразу почувствовал, что где-то его провели, но бедолагу можно успокоить целительной эвтаназией, применённой через кнопку «ВЫКЛ».

JetPack в печали

Но теперь нарисовалась более крупная проблема. Непонятно, как я не заметил её раньше. Все ссылки на посты возвращают 404:

Нерабочие ссылки

Я смутно помню, что в конфигах nginx на сервере что-то действительно было про пермалинки и ссылки на посты, так что нужно снова идти туда и выяснять, что за оно.

Шаг 5. Исправляем ссылки

ОК, проблема на самом деле большая. Вот как я заставлял ссылки работать на nginx в «продакшене»:

Но в контейнером WordPress используется Apache! У него наверняка есть что-нибудь похожее, но я не настолько фанат или спец в Апаче, чтобы с ним ковыряться. Я хочу свой nginx назад!

Очередной сеанс гугла, и снова есть решение. Образ WordPress существует в нескольких вариантах, в том числе и fpm, к которому можно прикручивать собственные сервера. А один хороший человек даже подготовил образ с nginx для этого — rault/nginx-wordpress. Буду пробовать.

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

Теперь, меняем wordpress образ на wordpress:fpm и добавляем новый сервис — nginx:

Наконец, запускаем контейнера и скрещиваем все доступные пальцы на удачу, потому что разродиться альтернативным решением среди ночи я не смогу. Это просто должно сработать.

JetPack снова поругался и снова отправился в страну вечной охоты. Но в остальном всё вроде работает.

Полностью рабочий WordPress сайт в Docker

Я прокликал все очевидные ссылки, и всё ОК. Всё в докере, и всё ОК!

Мораль

Перевести существующий WordPress в Docker можно и не особо болезненно. Процесс относительно простой, и только конфигурация сервера меня немного поставила в тупик, но, возможно, это только моя проблема.

Я потрачу ещё какое-то время, тестируя эти контейнера. Измерю потерю в производительности, если такая есть, поищу косяки. Но если всё выйдет нормально, эта штука определённо едет в продакшен.

Как перенести WordPress сайт в Docker: 1 комментарий

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *