Manually Cloning WordPress

WordPress LogoAs the market-leading content management system WordPress enables the creation of websites with a user-friendly interface and numerous extension options. If the website is to be redesigned or changed at a later date, it makes sense to do this work in a STAGE or TEST environment and update the LIVE website only after this work is complete. For this cloning of a WordPress website there are good and detailed blog posts, such as How to Clone a WordPress Site (Complete Guide).

This post briefly shows the necessary steps for two concrete examples. First, a STAGE instance with a subdomain is set up at the hoster and second a local TEST instance in a Docker container. The instructions are intended for experienced administrators.

Be sure to create a backup of your WordPress site before you start working. Or never confuse LIVE and STAGE 😅

STAGE instance at the web hoster

ALL-INKL.COM LogoIn my example ALL-INKL.COM is the web hoster. The administration is done with the service kasserver.com, here in the example for the site URL website.de, which is delivered there from the directory /live:

  • create a subdomain stage.website.de with the directory /stage
  • generate a Let’s Encrypt certificate under SSL Protection and set Force SSL
  • create a new database
  • export a database dump with phpMyAdmin and import it into the new database with phpMyAdmin as well
  • download all files of the directory /live with FTP
  • in the file wp-config.php adjust the existing entries for DB_NAME, DB_USER and DB_PASSWORD and add two new lines in front of … stop editing! …
    define('WP_HOME', 'https://stage.website.de');
    define('WP_SITEURL', 'https://stage.website.de');
    
    /* That's all, stop editing! Happy blogging. */
    
  • upload the customized wp-config.php file and all other files to the /stage directory
  • set up a directory protection (under Tools) with username and password for the directory /stage, so that the subdomain is not found by the search engines (only now, so that the changes are only made in the uploaded file .htaccess)
  • nice to have is now still the marking of the new STAGE instance, or never confuse LIVE and STAGE 😅
    • in wp-admin prefix the title of the website with “STAGE” in Settings | General | Title of the website
    • Put a sticker “STAGE” on all pages with Design | Customize | Additional CSS and:
      STAGE
      body::before {
            content: "STAGE";
            position: fixed;
            top: 30px;
            left: 30px;
            background-color: darkblue;
            color: red;
            font-size: 24px;
            font-weight: bold;
            padding: 5px 10px;
            z-index: 9999;
      } 
      

Note: In the database dump, even a small website will have thousands of entries with the URL www.website.de and hundreds with the directory /live. However, these do not need to be changed in the database dump. It is enough to add the entries WP_HOME and WP_SITEURL and let the web server deliver the files from the directory /stage.

Note II: Absolute links can still be contained in the posts and in the configuration. These absolute links then jump to the LIVE website. Replacing them with relative links will then work for both STAGE and LIVE and be the right preparation for the back cloning from STAGE to LIVE once the work is done. Examples:

  • Change link in a post from https://www.website.de/References to /References.
  • Change URL in menu from https://www.website.de/About to /About.

Thus, a cloned version of the website is available at stage.website.de and can be changed, extended and tested at leisure. If everything fits, a back cloning from STAGE to LIVE takes place.

docker Logo

Test instance with Docker container

If only a local test instance is needed, e.g. to analyze a bug or to test an upgrade, then Docker containers are a good choice. For setting up Docker containers, github.com/muhme/wordpress-maildev can be used. The following shell commands are for a Unix-like operating system, such as Mac OS X:

$ git clone https://github.com/muhme/wordpress-maildev wordpress-test
$ cd wordpress-test
$ docker compose up -d

Then the wp_test database is created and imported into the wp_mariadb Docker container:

$ echo "CREATE DATABASE wp_test;" | docker exec -i wp_mariadb mysql -uroot -proot
$ docker exec -i wp_mariadb mysql -uroot -proot $DATABASE < export.sql

Then in the file wp-config.php adjust the following existing four entries and add three new lines:

define('DB_NAME', 'wp_test');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
define('DB_HOST', 'mysql');                    # docker container wp_mariadb

define('WP_HOME', 'http://localhost:3080');    # docker container wp_wordpress
define('WP_SITEURL', 'http://localhost:3080');
define('FORCE_SSL_ADMIN', false);              # simple use http on TEST instance

Then delete the WordPress installation in the Docker container wp_wordpress and upload the customized file wp-config.php and all other files to the directory /var/www/html in the Docker container wp_wordpress:

$ docker exec -i wp_wordpress /bin/bash -c "rm -rf /var/www/html 2>/dev/null"
$ tar -c * | docker exec -i  wp_wordpress tar x -C /var/www/html

This makes the TEST instance available at http://localhost:3080. The big advantage is the simpler installation and the possibility to run any number of test instances in parallel.