There are two parts to the migration: the database and the static files.
The most important part is the database. You'll need a database backup (aka sqldump
) of the production database, and you'll need to import that into your local database. There are several ways to accomplish this, depending on your site hosting and whether or not you can use drush
.
The local site should be somewhat functional after a database import, but it may look odd if it is missing static assets such as image files. Depending on how the production site is configured, you can probably find most of these in the public files directory. The most common location for these files is ./web/sites/default/files
but the path may differ. You'll need to copy these files from the production web host to your local environment using a tool like rsync
, scp
, or sftp
.
If you have installed Drush (via composer require drush/drush
) then you may be able to use drush sql:sync
to synchronize databases.
Before you do that, you might want to set up Drush aliases for local and remote environments.
Keep in mind, also, that drush migrate
is used for a different purpose -- migrating site contents from another non-Drupal platform into your Drupal site.
As a thought experiment, let's say you had three copies of your Drupal site -- Dev, Stage, and Prod -- on one server (using three different Apache2 VirtualHosts
with DocumentRoot
set to /var/www/dev
, /var/www/stg
, and /var/www/prd
).
In that case, you could use the local_sync
function defined below to sync the database and files from a higher environment to a lower environment:
#!/bin/bash
function local_drush () {
if [[ $# -eq 0 ]]; then
echo "local_drush (set environment and execute project-local drush)"
echo "Usage: local_drush [dev stg prd] [drush-args]"
echo "Sets environment to dev stg or prod, then passes argv to local drush."
fi
if [[ $1 == 'dev' ]] || [[ $1 == 'stg' ]] || [[ $1 == 'prd' ]]; then
RETURN_DIR=${PWD}
cd /var/www/$1
./vendor/bin/drush ${@:2}
cd ${RETURN_DIR}
else
echo "Invalid usage: first arg must be dev, stg, or prd."
fi
}
function local_sync () {
if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then
echo "local_sync (migrate db and files to a lower environment)"
echo "Usage: local_sync <SOURCE> <TARGET>"
echo "Set source and target environments, then sync db and files."
fi
if [[ $1 == 'prd' ]] || [[ $1 == 'stg' ]]; then
SOURCE=$1
if [[ $2 == 'stg' ]] || [[ $2 == 'dev' ]]; then
TARGET=$2
if [[ ( $1 = 'prd' && $2 == 'stg' ) || ( $1 = 'prd' && $2 == 'dev' ) || ( $1 = 'stg' && $2 == 'dev' ) ]]; then
RETURN_DIR=${PWD}
BACKUP_DIR=$HOME/sqldumps/${SOURCE}
BACKUP_FILE=${BACKUP_DIR}/${SOURCE}_$(date -I).sql
mkdir -p ${BACKUP_DIR}
SOURCE_FILES=/var/www/${SOURCE}/web/sites/default/files/
TARGET_FILES=/var/www/${TARGET}/web/sites/default/files/
EXCLUDE_CSS=${SOURCE_FILES}css/
EXCLUDE_JS=${SOURCE_FILES}js/
EXCLUDE_PHP=${SOURCE_FILES}php/
echo "Creating temporary database backup of ${SOURCE} environment ..."
local_drush ${SOURCE} sql:dump > ${BACKUP_FILE}
if [[ -s "${BACKUP_FILE}" ]]; then
echo "Importing database backup into ${TARGET} environment ..."
local_drush ${TARGET} sqlc < ${BACKUP_FILE}
echo "Deploying staged configuration for ${TARGET} environment ..."
local_drush ${TARGET} deploy
echo "Copying public files from ${SOURCE} to ${TARGET} ..."
rsync --exclude ${EXCLUDE_CSS} \
--exclude ${EXCLUDE_JS} \
--exclude ${EXCLUDE_PHP} \
--delete --progress -av ${SOURCE_FILES} ${TARGET_FILES}
echo "Rebuilding Drupal caches for ${TARGET} environment ..."
local_drush ${TARGET} cache:rebuild
echo "Import from ${SOURCE} to ${TARGET} completed successfully."
echo "Removing database backup of ${SOURCE} environment ..."
rm ${BACKUP_FILE}
cd ${RETURN_DIR}
else
echo "Error: ${BACKUP_FILE} not found, cannot continue."
fi
else
echo "Invalid usage: cannot copy from ${SOURCE} to ${TARGET}."
fi
else
echo "Invalid usage: second arg must be stg or dev."
fi
else
if [[ $1 == 'dev' ]]; then
echo "Invalid usage: cannot migrate from dev to higher environment."
else
echo "Invalid usage: first arg must be prd or stg."
fi
fi
}
Note that the local_sync
command depends on the local_drush
command, which in turn depends on the local and remote projects containing a site-local Drush in ./vendor/bin/drush
, which is the recommended method of installing Drush. The shell script is non-standard, but it has the advantage of working whether or not you have configured Drush aliases properly.
I'll leave it to you as an exercise to figure out how to get the files from your remote server into your local environment. There's nothing wrong with doing all these steps manually, or with using Filezilla to transfer files via SFTP over SSH, but consider that the rsync
command (on lines 49-52) can be used with a different ${SOURCE}
which can be on a remote server. The only other change you'd need to make would be to also rsync
the ${BACKUP_FILE}
to your local (around line 42).
Ha! I see that you edited your question while I was writing my answer.
Your new question is a duplicate, answered here by Clive.
From the comments on that answer:
The official way is for modules relying on the old way to explicitly write the code to make the updates happen in hook_update_N
. All the gritty details are here: https://drupal.org/node/3034742
The workaround is to install the Devel Entity Updates module, which makes the old drush entup
command available.
You're not supposed to use this in production, but it's OK to use in your local development environment as long as you don't promote your local DB to the production environment.
It sounds like you are only having this problem in your local, not in production, so this option may work for you.
Good luck!