Post

Migrating A WordPress Website To Docker

Last Updated: April 17, 2024

Introduction –

In this tutorial you will learn how to migrate and dockerize a WordPress website and database from one host (such as On-Prem or a cloud provider like DigitalOcean). We will create three docker containers (mariadb, nginx, bitnami-php) using docker compose.

Export the WordPress Database from the current host

First, we need to login to the MySQL database, and export the current database.

Login to your current WordPress host via SSH, list the available databases and set the correct permissions for your wordpress SQL admin user:

1
2
3
4
5
mysql -u root -p
show databases;
GRANT PROCESS ON *.* TO '<username>'@localhost;
FLUSH PRIVILEGES;
EXIT;

Next, run the mysqldump command to Export the MySQL database to local storage. The following command will backup, export, and compress the backup database:

1
mysqldump --add-drop-table -h localhost -u <username> -p <database-name> | bzip2 -c > <db-backup-name>.bak.sql.bz2

Download the database backup to your local machine. For example, you can use MobaXterm establish an SSH connection to the virtual machine, then downloaded the file through the built-in SCP tab.

Note: Make sure to install bzip2 to zip the mysql database in 1 command.

1
sudo dnf install bzip2 -y

Export WordPress site data and html

We also need to zip and export the WordPress configuration files and plugins. The follow command will create an archive, output the progress, zips the files and directories, and sets a filename.

1
sudo tar cvzf /var/www/html/<wp-backup>.tar.gz /var/www/html/<wordpress-website>

Download the zipped WordPress databse archive to your local machine.

New Docker host - Create volumes for NGINX, PHP, and MariaDB containers

Now, we need to setup the docker host.

  1. Create a single volume group to encompass the entire sdb disk.
    1
    
    sudo vgcreate vg_sdb /dev/sdb
    
  2. Now create the logical volumes within vg_sdb.
    1
    2
    3
    
    sudo lvcreate -n lv_sdb1 -L 5G vg_sdb
    sudo lvcreate -n lv_sdb2 -L 2G vg_sdb
    sudo lvcreate -n lv_sdb3 -L 5G vg_sdb
    
  3. Identify the logical volumes on vda using the lvdisplay command.
    1
    
    sudo lvdisplay
    
  4. Create ext4 filesystems on these logical volumes using the mkfs.ext4 command. Here are the commands to do this:
    1
    2
    3
    
    sudo mkfs.ext4 /dev/vg_sdb/lv_sdb1
    sudo mkfs.ext4 /dev/vg_sdb/lv_sdb2
    sudo mkfs.ext4 /dev/vg_sdb/lv_sdb3
    
  5. Next, make new directories for the volumes to mount to and mount them:
    1
    2
    3
    4
    
    sudo mkdir /nginx_html
    sudo mkdir /nginx_config
    sudo mkdir /mariadb_data
    sudo mount -a
    

Finally, we will make the newly created volumes automatically mount on boot. Open the fstab file with the sudo vi /etc/fstab command, then add these lines to the end of the file:

1
2
3
/dev/vg_sdb/lv_sdb1 /nginx_html     ext4 defaults 0 2
/dev/vg_sdb/lv_sdb2 /nginx_config   ext4 defaults 0 2
/dev/vg_sdb/lv_sdb3 /mariadb_data   ext4 defaults 0 2

Extract the zipped WordPress archive to /nginx_html

1
2
sudo mkdir /nginx_html/<wordpress-website>
sudo tar xvf <wp-backup>.tar.gz -C /nginx_html/<wordpress-website>

Now we need to set permissions on the nginx_html directory so that that PHP container can write to it:

1
2
cd /nginx_html
chown -R 1:1 .

Docker Setup

Create a new user-defined bridged network for Docker:

1
docker network create wordpress

Docker Compose configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version: "3"
services:
 mariadb:
    image: mariadb:latest
    container_name: mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=<password>
    volumes:
      - /mariadb_data:/var/lib/mysql
    networks:
      - wordpress
 nginx:
    image: nginx:latest
    container_name: nginx
    volumes:
      - /nginx_config/:/etc/nginx
      - /nginx_html/<wordpress-website>:/var/www/html
    ports:
      - 80:80
      - 443:443
    networks:
      - wordpress
 php-fpm:
    image: bitnami/php-fpm
    volumes:
      - /nginx_html/<wordpress-website>:/var/www/html
    networks:
      - wordpress
volumes:
  mariadb_data:
  nginx_config:
  nginx_html:
networks:
  wordpress:

NGINX Configuration Setup

First, initiate the Docker container in detached mode:

1
docker compose up -d

Then, to transfer the NGINX configuration files from within the container to your host’s /nginx_config volume, execute:

1
docker run --rm -ti -v nginx_config:/data --entrypoint bash nginx -c 'cp -a /etc/nginx/. /data'

This command launches a transient, interactive container using the NGINX image. It binds the nginx_config named volume to /data inside this container and employs a custom entrypoint to run a bash shell command, which replicates the entire contents of /etc/nginx/ from inside the container to /data on the mounted volume.

Should you need to direct the NGINX configuration files to a different host directory, adjust the volume mount (-v) in the command accordingly. For instance, to place the files into /nginx_config/conf.d on your host, utilize:

1
docker run --rm -ti -v /nginx_config/conf.d:/data --entrypoint bash nginx -c 'cp -a /etc/nginx/. /data'

Open and edit the default NGINX configuration file located at /nginx_config/conf.d/default.conf to the values below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sudo vi /nginx_config/conf.d/default.conf

server {
  listen 80;
  server_name <host-public-ip-address or DNS name, ie exmaple.com www.example.com>;

  location / {
    try_files $uri $uri/ /index.php?q=$uri&$args;
  }

  location ~ \.php$ {
    try_files $uri /index.php =404;
    fastcgi_pass php-fpm:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
  }

  root /var/www/html;
  index index.php;
}

Create a new MariaDB database

First, ensure that the MariaDB MySQL client and bzip2 is installed on the host system.

1
2
sudo dnf install mariadb -y
sudo dnf install bzip2 -y

Make sure to you upload and unzip the exported & zipped database to the current directory on your host.

1
bunzip2 <db-backup-name>.bak.sql.bz2

On the Docker host, enter the Docker container’s mariadb mysql CLI using the password you added to the Docker Compose file. Verify the IP address of your MariaDB container. You can find it using:

1
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name_or_id>

Connect to the MariaDB container using the IP address from the above command. Now, enter this command from the host to connect to the mariadb container:

1
mysql -h <mariadb-ip-address> -u root -p

We will then need to create a new database for wordpress, and run the source command to import the old WordPress database into our new database.

1
2
3
4
5
6
CREATE DATABASE wordpress;
CREATE USER '<wordpress_user>'@'localhost' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON <db_name>.* TO '<wordpress_user>'@'localhost';
USE wordpress;
source <db-backup-name>.bak.sql
EXIT;

Update DNS records

If you decided to move hosts, you will need to update the A or CNAME records to the public IP address of your new host, with your DNS provider like Namecheap.

All that’s left to do is run docker compose up and access the website in your web browser.

1
sudo docker compose up -d



Featured Tweet

This post is licensed under Apache License 2.0 by the author.