Обычный SQL-запрос UPDATE ... REPLACE(...) опасен для WordPress. В настройках виджетов и плагинов встречаются сериализованные PHP-данные: внутри них записана длина каждой строки. Если заменить домен на адрес другой длины, значение может перестать распаковываться.
WP-CLI понимает сериализованные структуры и меняет строки без повреждения их формата. Но даже с ним перенос лучше делать по короткому плану: копия, пробный проход, замена, проверка.
Ниже команды рассчитаны на Compose-стек из соседней инструкции, где WP-CLI запускается сервисом cli, а MariaDB — сервисом db.
1. Зафиксируйте старый и новый адрес
Сначала посмотрите, что WordPress считает домашним адресом и адресом установки:
docker compose run --rm cli option get home
docker compose run --rm cli option get siteurl
Запишите адреса целиком, включая http или https, www и возможный подкаталог. Для WordPress это разные строки:
http://old.example.test
https://example.ru
Перед заменой проверьте, что новый домен уже направлен на нужный сервер, reverse proxy настроен, а HTTPS-сертификат выпускается. Иначе после смены адреса админка начнёт перенаправлять браузер на ещё не работающий хост.
2. Сделайте дамп базы
Создайте каталог с текущей датой и выгрузите согласованный дамп InnoDB:
backup_dir="backups/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
docker compose exec -T db sh -lc \
'mariadb-dump --user=root --password="$(cat /run/secrets/db_root_password)" \
--single-transaction --routines --events wordpress' \
> "$backup_dir/wordpress-before-domain-change.sql"
Проверьте, что файл не пуст и в нём есть таблицы:
test -s "$backup_dir/wordpress-before-domain-change.sql"
grep -m 3 '^CREATE TABLE' "$backup_dir/wordpress-before-domain-change.sql"
Если база не использует InnoDB или во время операции меняется схема, одного --single-transaction недостаточно. Для небольшого сайта надёжнее на время замены включить режим обслуживания и остановить запись.
3. Посмотрите объём замены без записи
Подставьте свои адреса и обязательно начните с --dry-run:
docker compose run --rm cli search-replace \
'http://old.example.test' \
'https://example.ru' \
--all-tables-with-prefix \
--skip-columns=guid \
--precise \
--dry-run
Команда покажет таблицы, столбцы и число предполагаемых изменений, но ничего не запишет. Обратите внимание на три вещи:
- старый адрес действительно найден;
- в список попали таблицы нужной установки, а не соседнего сайта;
- число замен выглядит правдоподобно, без неожиданного захвата журналов или архивных таблиц.
--all-tables-with-prefix полезен, потому что плагины часто создают свои таблицы с префиксом WordPress. Если в одной базе лежит несколько установок со схожими префиксами, сначала выведите таблицы командой wp db tables --all-tables-with-prefix и проверьте список.
--skip-columns=guid оставляет поле guid записей без изменений. В WordPress оно служит постоянным идентификатором, а не обычной ссылкой для показа посетителю.
4. Выполните замену
Если dry-run не показал неожиданностей, повторите ту же команду без последнего ключа:
docker compose run --rm cli search-replace \
'http://old.example.test' \
'https://example.ru' \
--all-tables-with-prefix \
--skip-columns=guid \
--precise
После завершения очистите объектный кэш, если он подключён, и обновите правила постоянных ссылок:
docker compose run --rm cli cache flush
docker compose run --rm cli rewrite flush
Проверьте итоговые значения:
docker compose run --rm cli option get home
docker compose run --rm cli option get siteurl
Для multisite сначала изучите результат с ключом --network. Не добавляйте его к рабочей базе наугад: одна команда затрагивает все сайты сети.
5. Проверьте сайт как пользователь
Одного ответа главной страницы мало. Пройдите минимум по этому списку:
- главная страница и одна внутренняя запись открываются по HTTPS;
- вход в
/wp-admin/ не уходит в цикл перенаправлений;
- изображения из медиатеки загружаются с нового домена;
- редактор сохраняет запись;
- формы и отправка почты работают;
- REST API по адресу
/wp-json/ отвечает без старого домена;
- в HTML нет mixed content со старым
http://.
Остатки старого адреса можно проверить ещё одним dry-run — теперь ожидается ноль или небольшой понятный список:
docker compose run --rm cli search-replace \
'http://old.example.test' \
'https://example.ru' \
--all-tables-with-prefix \
--skip-columns=guid \
--dry-run
Если что-то пошло не так
Не запускайте десяток новых замен поверх повреждённого состояния. Сохраните журналы, остановите запись и восстановите сделанный дамп в чистую базу или после осознанной очистки текущей:
docker compose exec -T db sh -lc \
'mariadb --user=root --password="$(cat /run/secrets/db_root_password)" wordpress' \
< backups/ДАТА/wordpress-before-domain-change.sql
Перед импортом убедитесь, что выбрали правильный файл и базу. В production безопаснее сначала проверить восстановление на отдельном стенде, а затем повторить понятную процедуру на рабочем сайте.
Официальные источники