{"id":36100,"date":"2016-06-23T16:30:58","date_gmt":"2016-06-23T11:00:58","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=36100"},"modified":"2016-06-24T11:14:06","modified_gmt":"2016-06-24T05:44:06","slug":"using-docker-compose-to-migrate-wordpress-website-on-docker","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/using-docker-compose-to-migrate-wordpress-website-on-docker\/","title":{"rendered":"Using Docker Compose to Migrate WordPress Website on Docker"},"content":{"rendered":"<p><span style=\"color: #000000;\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-36293 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/06\/03.docker-wordpress.jpg\" alt=\"03.docker-wordpress\" width=\"591\" height=\"333\" \/><\/span><\/p>\n<p><span style=\"color: #000000;\">Docker is a like your mini virtual machine that is very light on your host resources. Unlike virtual machines, which need their own kernel, <a title=\"docker devOps\" href=\"http:\/\/www.tothenew.com\/devops-chef-puppet-docker\">Docker creates virtualized experience<\/a> on top of your running kernel. The mini virtual machines provided by Docker are called &#8220;containers&#8221;. These containers are platform independent and can be reused for deploying applications on different environments.<\/span><\/p>\n<p><span style=\"color: #000000;\">In this blog post, we will migrate an existing WordPress website on Docker. We will use Nginx as the web server (with php5-fpm for PHP support) and MySQL as the database solution. We will create 2 images (for Nginx and MySQL) and use Docker Compose to link them.<\/span><\/p>\n<p><span style=\"color: #000000;\">The steps followed assume that the Docker server<\/span><span style=\"color: #000000;\"> is a separate machine from the current WordPress server. However, both of these can be the same machine in which case you do not need to transfer the files to the other machine. This setup can be <a title=\"Docker Developers\" href=\"http:\/\/www.tothenew.com\/devops-automation-consulting\" target=\"_blank\">used by developers<\/a> as well for running the WordPress website on their own machine.<\/span><\/p>\n<h2><span style=\"color: #000000;\">Prerequisites<strong>:<\/strong><\/span><\/h2>\n<p><span style=\"color: #000000;\">This blog post assumes that the target machine is running Linux based OS with Docker and Docker Compose installed. Below are the requirements for this setup:<\/span><\/p>\n<ul>\n<li><span style=\"color: #000000;\">Operating System: Any Linux machine (Ubuntu 14.04 server is used for this demo)<\/span><\/li>\n<li><span style=\"color: #000000;\">Docker version 1.11.2<\/span><\/li>\n<li><span style=\"color: #000000;\">Docker Compose version 1.7.1<\/span><\/li>\n<\/ul>\n<p><span style=\"color: #000000;\">So let&#8217;s start. Below are the steps you need to follow.<\/span><\/p>\n<h2><span style=\"color: #000000;\">STEPS:<\/span><\/h2>\n<h3><span style=\"color: #000000;\"><strong>1. Backup website files and database.<\/strong><\/span><\/h3>\n<p><span style=\"color: #000000;\">Before starting with the migration, we need to take backup of website files used by WordPress and the database used by WordPress. Let&#8217;s start by backing up the DocumentRoot for WordPress website:<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-wp-server:~# tar -czf wordpressback.tgz wordpress\/<\/span><\/pre>\n<p><span style=\"color: #000000;\">Now let&#8217;s dump the WordPress database.<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-wp-server:~# mysqldump -u root -p wordpress | gzip &gt; wordpress.sql.gz\r\nEnter password:<\/span><\/pre>\n<p><span style=\"color: #000000;\">Enter your MySQL password when prompted. We have compressed the database dump so that the transfer is faster.<\/span><\/p>\n<p><span style=\"color: #000000;\">Note: We assume that there are no write queries on the database in this migration process. This migration can be achieved with zero downtime with proper strategy.<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-wp-server:~# gzip wordpress.sql<\/span><\/pre>\n<h3><span style=\"color: #000000;\"><strong>2. Setup new DocumentRoot and DB for Docker containers<\/strong><\/span><\/h3>\n<p><span style=\"color: #000000;\">Now let&#8217;s transfer these files onto the Docker server. You can also use your own machine for Docker. In that case, you do not need to transfer the files.<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-wp-server:~# scp wordpressback.tgz wordpress.sql.gz \\\r\n&gt; wp-docker.com:\/docker-data\/wordpress\/\r\nroot@wp-docker.com's password:\r\nwordpressback.tgz 100% 7589KB 7.4MB\/s 00:00\r\nwordpress.sql.gz 100% 90KB 89.6KB\/s 00:00<\/span><\/pre>\n<p><span style=\"color: #000000;\">We are using these 2 Docker images:<\/span><\/p>\n<ol>\n<li><span style=\"color: #000000;\"><em>wpmysql<\/em><\/span><\/li>\n<li><span style=\"color: #000000;\"><em>wpnginx<\/em><\/span><\/li>\n<\/ol>\n<p><span style=\"color: #000000;\"><strong>Note:<\/strong> These images can be pulled from Docker Hub<\/span><span style=\"color: #000000;\"> with following commands:<\/span><\/p>\n<pre><span style=\"color: #000000;\">docker pull raghuttnd\/ttnblog_wpmysql\r\ndocker pull raghuttnd\/ttnblog_wpnginx<\/span><\/pre>\n<p><span style=\"color: #000000;\">We will shortly have a look at the Dockerfiles used to create these 2 images and the Docker Compose files that we have used to bring up these containers.<\/span><\/p>\n<p><span style=\"color: #000000;\">Now that the dump file and the website tar is transferred on the Docker server, we need to extract the files and prepare the DocumentRoot directory which <em>wpnginx<\/em><\/span><span style=\"color: #000000;\"> container will use.<\/span><\/p>\n<p><span style=\"color: #000000;\">The directory <em>&#8220;\/docker-data\/wordpress&#8221;<\/em> will be used as the DocumentRoot for our website to be hosted on Docker. We will mount this directory inside the Docker container.<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-docker:~# cd \/docker-data\/wordpress\/\r\nroot@ubuntu-docker:\/docker-data\/wordpress# tar -xzf wordpressback.tgz --strip 1\r\nroot@ubuntu-docker:\/docker-data\/wordpress# rm wordpressback.tgz<\/span><\/pre>\n<p><span style=\"color: #000000;\">The DB dump file needs to be in a separate directory. We will use the directory <em>&#8220;\/docker-data\/dbdump\/&#8221;<\/em> for keeping this file and mount this directory inside the <em>wpmysql<\/em><\/span><span style=\"color: #000000;\"> container.<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-docker:~\/docker\/compose\/wordpress# mv wordpress.sql.gz \/docker-data\/dbdump\/\r\nroot@ubuntu-docker:~\/docker\/compose\/wordpress# gunzip \/docker-data\/dbdump\/wordpress.sql.gz<\/span><\/pre>\n<p><span style=\"color: #000000;\">Here, we need to make changes in the wp-config.php file according to our new setup. We need DB name, DB User, DB Password and DB Host. These will be created in our <em>wpmysql<\/em><\/span><span style=\"color: #000000;\"> container. So once our Docker Compose file is ready, we will come back and make these changes.<\/span><\/p>\n<h3><span style=\"color: #000000;\"><strong>3.\u00a0Docker Setup<\/strong><\/span><\/h3>\n<p><span style=\"color: #000000;\">The Docker setup involves setting up the images using the Dockerfiles and Entrypoint scripts (launch scripts).<\/span><br \/>\n<span style=\"color: #000000;\">Now we need to bring up the Docker containers. The containers used for this demo are based on ubuntu:14.04 image.<\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>wpnginx:<\/strong><\/span><br \/>\n<span style=\"color: #000000;\">The image used for Nginx is created using this Dockerfile:<\/span><\/p>\n<p>[sourcecode language=&#8221;bash&#8221;]FROM ubuntu:14.04<br \/>\nRUN apt-get update<\/p>\n<p>#Install nginx<br \/>\nRUN apt-get -y install \\<br \/>\nnginx \\<br \/>\nphp5-fpm \\<br \/>\nphp5-mysql \\<br \/>\nwget<br \/>\n#Clear the DocumentRoot<br \/>\nRUN rm -rf \/usr\/share\/nginx\/html\/*<br \/>\n#Copy the default configuration<br \/>\nCOPY conf\/default \/etc\/nginx\/sites-available\/<br \/>\nRUN mkdir \/root\/scripts<br \/>\nCOPY launch.sh \/root\/scripts\/<br \/>\nENTRYPOINT \/bin\/bash \/root\/scripts\/launch.sh[\/sourcecode]<\/p>\n<p><span style=\"color: #000000;\">The launch script starts Nginx and php5-fpm in background and continues running:<\/span><\/p>\n<p>[sourcecode language=&#8221;bash&#8221;]#!\/bin\/bash<br \/>\nservice nginx start<br \/>\nservice php5-fpm start<br \/>\ntail -f \/var\/log\/nginx\/{access.log,error.log}[\/sourcecode]<\/p>\n<p><span style=\"color: #000000;\">You can see the Nginx logs with the command:<\/span><\/p>\n<pre><span style=\"color: #000000;\"># docker logs -f wpnginx-container<\/span><\/pre>\n<p><span style=\"color: #000000;\"><strong>wpmysql:<\/strong><\/span><br \/>\n<span style=\"color: #000000;\">The Dockerfile used for this image is:<\/span><\/p>\n<p>[sourcecode language=&#8221;bash&#8221;]FROM ubuntu:14.04<br \/>\nRUN apt-get update<\/p>\n<p>#Install mysql non-interactive<br \/>\nRUN echo mysql-server mysql-server\/root_password password mysqlpass | debconf-set-selections<br \/>\nRUN echo mysql-server mysql-server\/root_password_again password mysqlpass | debconf-set-selections<br \/>\nRUN apt-get -y install mysql-server<br \/>\nRUN sed -i &#8216;\/bind-address\/c\\bind-address\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = 0.0.0.0&#8217; \/etc\/mysql\/my.cnf<br \/>\nRUN mkdir \/root\/scripts<br \/>\nCOPY launch.sh \/root\/scripts\/<br \/>\nRUN touch \/var\/lib\/mysql\/firstrun<br \/>\nRUN ln -s \/var\/lib\/mysql\/local.cnf \/root\/.my.cnf<\/p>\n<p>ENTRYPOINT \/bin\/bash \/root\/scripts\/launch.sh[\/sourcecode]<\/p>\n<p><span style=\"color: #000000;\">The default root password used in this image is overridden when the image is brought up the first time (using the launch script).<\/span><\/p>\n<p><span style=\"color: #000000;\">Here, as you can see that the ENTRYPOINT for this image is a launch script. This launch script does the following (using environment variables):<\/span><\/p>\n<ol>\n<li><span style=\"color: #000000;\">Creates the root password for the first time.<\/span><\/li>\n<li><span style=\"color: #000000;\">Creates the WordPress database.<\/span><\/li>\n<li><span style=\"color: #000000;\">Creates the WordPress user and sets its password.<\/span><\/li>\n<li><span style=\"color: #000000;\">Optionally populate the above database using the dump file if the dump file is provided in the environment variable \u201cWORDPRESS_DUMP_FILE\u201d (and removes the dump file if the dump is successful).<\/span><\/li>\n<\/ol>\n<p><span style=\"color: #000000;\">Here comes the launch script for <em>wpmysql<\/em>:<\/span><\/p>\n<p>[sourcecode language=&#8221;bash&#8221;]<br \/>\n#!\/bin\/bash<\/p>\n<p>FIRSTRUN=&quot;\/var\/lib\/mysql\/firstrun&quot;<br \/>\nWORKDIR=&quot;\/dockerinit\/&quot;<br \/>\nMYSQLCRED=&quot;\/root\/.my.cnf&quot;<br \/>\nmkdir -p $WORKDIR<\/p>\n<p>if [ -e $FIRSTRUN ]<br \/>\nthen<br \/>\n\tif [ -z $MYSQL_ROOT_PASSWORD ]<br \/>\n\tthen<br \/>\n\t\techo &gt;&amp;2 &quot;You are running the script for first time.&quot;<br \/>\n\t\techo &gt;&amp;2 &quot;Please specify MYSQL_ROOT_PASSWORD environment variable.&quot;<br \/>\n\t\texit 1<br \/>\n\telse<br \/>\n\t\tservice mysql start<br \/>\n\t\techo &quot;Resetting root password for first time.&quot;<br \/>\n\t\tmysql -u root -pmysqlpass &lt;&lt;-EOSQL<br \/>\n\t\t\tDELETE FROM mysql.user WHERE User=&#8217;root&#8217; ;<br \/>\n\t\t\tCREATE USER &#8216;root&#8217;@&#8217;%&#8217; IDENTIFIED BY &#8216;${MYSQL_ROOT_PASSWORD}&#8217; ;<br \/>\n\t\t\tGRANT ALL ON *.* TO &#8216;root&#8217;@&#8217;%&#8217; WITH GRANT OPTION ;<br \/>\n\t\t\tDROP DATABASE IF EXISTS test ;<br \/>\n\t\t\tFLUSH PRIVILEGES ;<br \/>\n\t\tEOSQL<br \/>\n\t\t&gt;$MYSQLCRED<br \/>\n\t\techo &quot;[client]&quot; &gt;&gt; $MYSQLCRED<br \/>\n\t\techo &quot;user=root&quot; &gt;&gt; $MYSQLCRED<br \/>\n\t\techo &quot;password=${MYSQL_ROOT_PASSWORD}&quot; &gt;&gt; $MYSQLCRED<br \/>\n\t\trm $FIRSTRUN<br \/>\n\tfi<br \/>\nfi<\/p>\n<p>#Setting passed env variables<br \/>\nWORDPRESS_DB_USER=${ENV_WORDPRESS_DB_USER:=wpuser}<br \/>\nWORDPRESS_DB_PASSWORD=${ENV_WORDPRESS_DB_PASSWORD:=wppass}<br \/>\nWORDPRESS_DB_NAME=${ENV_WORDPRESS_DB_NAME:=wordpress}<\/p>\n<p>service mysql start<\/p>\n<p>echo &quot;Initializing database..&quot;<br \/>\nmysql &lt;&lt;-EOSQL<br \/>\n\tCREATE DATABASE IF NOT EXISTS $WORDPRESS_DB_NAME ;<br \/>\n\tGRANT ALL ON $WORDPRESS_DB_NAME.* TO &#8216;$WORDPRESS_DB_USER&#8217;@&#8217;%&#8217; IDENTIFIED BY &#8216;$WORDPRESS_DB_PASSWORD&#8217; ;<br \/>\n\tFLUSH PRIVILEGES ;<br \/>\n\tEOSQL<\/p>\n<p>#Checking if there is any file for restoring the DB dump<br \/>\nif [[ -n $WORDPRESS_DUMP_FILE ]]<br \/>\nthen<br \/>\n\tif [[ -f $WORDPRESS_DUMP_FILE ]]<br \/>\n\tthen<br \/>\n\t\techo &quot;Checking if there is any file for restoring the DB dump&quot;<br \/>\n\t\tmysql -u ${WORDPRESS_DB_USER} -p${WORDPRESS_DB_PASSWORD} $WORDPRESS_DB_NAME &lt; $WORDPRESS_DUMP_FILE<br \/>\n\t\tif [[ $? -eq 0 ]]<br \/>\n\t\tthen<br \/>\n\t\t  rm -f $WORDPRESS_DUMP_FILE #So that we dont accidentally dump again<br \/>\n\t\tfi<br \/>\n\telse<br \/>\n\t\techo &gt;&amp;2 &quot;The dump file specified in variable WORDPRESS_DUMP_FILE does not exist.&quot;<br \/>\n\t\texit 2<br \/>\n\tfi<br \/>\nfi<\/p>\n<p>service mysql stop<br \/>\n\/usr\/bin\/mysqld_safe<\/p>\n<p>[\/sourcecode]<\/p>\n<p><span style=\"color: #000000;\">Before bringing up the Nginx container, we need to make sure that MySQL container is running. So we will use Docker Compose for solving this dependency issue. The docker-compose.yml file to be used is:<\/span><\/p>\n<p>[sourcecode language=&#8221;bash&#8221;]version: &#8216;2&#8217;<br \/>\nservices:<br \/>\nnginx-wordpress:<br \/>\nimage: wpnginx<br \/>\nhostname: wphost<br \/>\ncontainer_name: wpnginx-container<br \/>\nvolumes:<br \/>\n&#8211; &quot;\/docker-data\/wordpress\/:\/usr\/share\/nginx\/html\/&quot;<br \/>\nports:<br \/>\n&#8211; 80:80<br \/>\ndepends_on:<br \/>\n&#8211; mysql-wordpress<\/p>\n<p>mysql-wordpress:<br \/>\nimage: wpmysql<br \/>\nhostname: wpmysqlhost<br \/>\ncontainer_name: wpmysql-container<br \/>\nvolumes:<br \/>\n&#8211; \/docker-data\/dbdump\/:\/dbdump<br \/>\n&#8211; wp-mysql-data:\/var\/lib\/mysql<br \/>\nenvironment:<br \/>\n&#8211; MYSQL_ROOT_PASSWORD=ttndpass<br \/>\n&#8211; ENV_WORDPRESS_DB_USER=wpuser<br \/>\n&#8211; ENV_WORDPRESS_DB_PASSWORD=wppass<br \/>\n&#8211; ENV_WORDPRESS_DB_DATABASE=wordpress<br \/>\n&#8211; WORDPRESS_DUMP_FILE=\/dbdump\/wordpress.sql<\/p>\n<p>volumes:<br \/>\nwp-mysql-data:[\/sourcecode]<\/p>\n<p><span style=\"color: #000000;\">In this file, we have passed few environment variables to MySQL image. Below are the variables used:<\/span><\/p>\n<ul>\n<li><span style=\"color: #000000;\">MYSQL_ROOT_PASSWORD &#8211; Password for MySQL <\/span><span style=\"color: #000000;\">root user.<\/span><\/li>\n<li><span style=\"color: #000000;\">ENV_WORDPRESS_DB_USER &#8211; The new WordPress username.<br \/>\n<\/span><\/li>\n<li><span style=\"color: #000000;\">ENV_WORDPRESS_DB_PASSWORD &#8211; Password <\/span><span style=\"color: #000000;\">for above WordPress<\/span><span style=\"color: #000000;\"> user.<\/span><\/li>\n<li><span style=\"color: #000000;\">ENV_WORDPRESS_DB_DATABASE &#8211; Database name to be used by WordPress.<\/span><\/li>\n<li><span style=\"color: #000000;\">WORDPRESS_DUMP_FILE &#8211; Path to the dump file which needs to be restored to above database.<\/span><\/li>\n<\/ul>\n<p><span style=\"color: #000000;\">One last step before bringing up the Docker containers: We need to make DB connection changes in the wp-config.php file. The DB host in this file will be the name of MySQL service defined in the Compose file above (mysql-wordpress)<\/span><span style=\"color: #000000;\">.<\/span><\/p>\n<h3><span style=\"color: #000000;\"><strong>4. Bring up the Containers:<\/strong><\/span><\/h3>\n<p><span style=\"color: #000000;\">Now let\u2019s bring up the containers using Docker Compose. The following command can be executed to run the containers in background:<\/span><\/p>\n<pre><span style=\"color: #000000;\">root@ubuntu-docker:~\/docker\/compose\/wordpress# docker-compose up -d\r\nCreating wpmysql-container\r\nCreating wpnginx-container<\/span><\/pre>\n<p><span style=\"color: #000000;\">That&#8217;s all folks.<\/span><\/p>\n<p><span style=\"color: #000000;\">It might seem like a lot but once the ground work is done (the Dockerfile and docker-compose.yml), there is not much left to take care of. If you just want to use these images, without going into the whole process of creating them, you can pull them from Docker Hub a<\/span><span style=\"color: #000000;\">s mentioned earlier.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Docker is a like your mini virtual machine that is very light on your host resources. Unlike virtual machines, which need their own kernel, Docker creates virtualized experience on top of your running kernel. The mini virtual machines provided by Docker are called &#8220;containers&#8221;. These containers are platform independent and can be reused for deploying [&hellip;]<\/p>\n","protected":false},"author":931,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":27},"categories":[2348],"tags":[2590,2558,3592,3593,3594,3596,3595],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/36100"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/931"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=36100"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/36100\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=36100"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=36100"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=36100"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}