06 Mar

WordPress Docker containers and display of PHP warnings

I use a Docker container to host a WordPress blog and I recently upgraded the Docker image to one based on an image which used PHP 7.2. I had previously been using one based on Apache with PHP 5.6.

I immediately noticed warnings being displayed at the top of the blog

The warnings where from PHP letting a developer know that their code had a non fatal error. The cause of the error is a subject for another blog post. I just wanted to turn off the display of these warning messages.

To do this you can set the display_errors configuration variable to Off in php.ini

Create a file called hide_errors.ini with the following content

display_errors = Off

I then proceeded to recreate my WordPress docker container with the same volume as the current container used, as well as mounting hide_errors.ini to /usr/local/etc/php/conf.d/hide_errors.ini inside the container.

After this the warnings were no longer displayed.

15 Mar

A lesson in character encodings and Docker containers

I recently had to execute some commands on a MySQL docker container.

In particular the docker container was based on the image https://github.com/docker-library/mysql/blob/eeb0c33dfcad3db46a0dfb24c352d2a1601c7667/5.7/Dockerfile.

I executed a bash shell inside the docker container using docker exec -it mysql /bin/bash and then proceeded to enter a cli interface to MySQL:

mysql -uroot -p

The root password was a complex password generated by a password manager. It contained a £ symbol.

I had trouble pasting it in when mysql requested the password.

I decided to set a variable like so, PASS=complex-password so that I could enter mysql using:

mysql -uroot -p$PASS

However when I got to the £ symbol in the password, the shell inserted a # at the beginning of the line and then continued on the next line.

For example, if the complex password was super£pass then this would appear in the shell, if I tried to paste the password:

[email protected]:/# # PASS='super
[email protected]:/# pass'

I couldn’t quite figure out what was going on and I ended up posting a question on stackoverflow. Very fortunately some one answered my question and pointed me in the right direction.

I’ve repeated the explanation here as well as the remedy.

The crux of the issue is that the terminal I was connecting to the docker container from was encoding characters as UTF-8 whereas the bash shell inside the docker container had ASCII character encoding.

This meant when I typed a £ symbol in my terminal, the two bytes C2 A3 (The UTF-8 representation of the £ symbol) were sent into the docker container and interpreted as 2 characters.

Inside the docker container Bash was interpreting characters with the high bit set as characters with the Meta-key modifier set.

For more information on the meta-key see https://www.gnu.org/software/bash/manual/bashref.html#Introduction-and-Notation.

C2 is the decimal 194, which is equal to 128 + 66, which means Bash would interpret it as a capital B (ASCII value 66) with the meta-key modifier.

A3 is the decimal 163, which is equal to 128 + 35, which means Bash would interpret it as a # (ASCII value 35) with the meta-key modifier.

This means that Bash saw my key press of £ as the commands M-B, M-#.

Looking at https://www.gnu.org/software/bash/manual/bashref.html#Miscellaneous-Commands you will see that the
M-B moves the cursor back to the previous word and that M-# inserts the comment character at the start of the line and moves to a newline.

This explains the behaviour I was seeing but how do you go about fixing this so that I could type a £ symbol?

This is as simple as making sure the locale is set correctly in the docker container.

There was no LANG variable set, or no other locale information. This meant the default locale was being used which is the POSIX local. There were no proper locales installed. The only choice of locale with UTF-8 was C.UTF-8.

Setting the LC_ALL variable and launching bash (within bash) like so:

LC_ALL=C.UTF-8 bash

Allowed me to test this would work. Inside this bash shell within a bash shell I could now type the £ symbol freely without strange side affects.

I just had to make this change permanent.

I did this by appending the following to the file /root/.bashrc:

export LC_ALL=C.UTF-8
export LANG=C.UTF-8

29 Jul

Containerising your Word Press blog with Docker

In this post, I will talk you through how you can create a copy of your live Word Press blog as a Docker container. The reason I wanted to do this, is so that I can test actual updates and themes to my live site before making them publicly available and seeing how any tested plug-ins interact with actual live content.

The first thing you need to do is make sure you have Docker installed or have access to a Docker host.

Pull down the Word Press, MySQL and PhpMyAdmin prebuilt Docker images from the Docker hub

docker pull wordpress
docker pull mysql
docker pull phpmyadmin/phpmyadmin

Just to note at the time of writing this post the tags for each where:

Image Tag Dockerfile
wordpress 4.5 https://github.com/docker-library/wordpress/blob/6afa0720da89f31d6c61fd38bb0d6de6e9a14a49/apache/Dockerfile
mysql 5.7.13 https://github.com/docker-library/mysql/blob/f7a67d7634a68d319988ad6f99729bfeaa84ceb2/5.7/Dockerfile
phpmyadmin/phpmyadmin 4.6.3-1 (from GitHub tag) https://github.com/phpmyadmin/docker/blob/4.6.3-1/Dockerfile

We now need to download a snapshot of your current live word press blog. This is very hosting company specific but in the lowest generic terms possible you need to download all files that come under the www root directory on your hosting companies servers and to export a copy of your Word Press MySQL database. In the rest of this post I will refer to the copy of the www root directory as the Word Press files and I will refer to the export of the MySQL database as the database.

At this point we need to run up a MySQL and PhpMyAdmin container. Execute the following on the Docker host.

docker run --name wp-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pwd -d mysql
docker run --name phpmyadmin -d --link wp-mysql:db -p 8081:80 phpmyadmin/phpmyadmin

A MySQL server instance will now be running on the Docker host and it can be administered from the PhpMyAdmin instance running on port 8081 of the Docker host.

Use the PhpMyAdmin instance with the MySQL root password set above to create a new user and make sure you select to create a database with the same name. After this, import your database files using the import option of PhpMyAdmin.

Once you have imported the database modify the kvht_options table so that the records with the following name are updated accordingly:

name value
siteurl <docker-host-hostname-or-IP-address>:8080
home <docker-host-hostname-or-IP-address>:8080
upload_path /var/www/html/wp-content/uploads

Note: The table name may have a different prefix to mine or no prefix at all.

At this point if you have any media which is embedded using an absolute URL to your actual live Word Press site then you need to update individual posts to make the URL’s server relative. This is not taken care of in this post as I always use server root relative paths for this type of media. A quick trick would be to do an appropriate regex find and replace in the exported SQL file before the import.

Now we need to run an instance of the Word Press image but using our Word Press files.

docker run --name wp-blog --link wp-mysql:mysql -p 8080:80 -e MYSQL_ENV_MYSQL_USER=database_user -e MYSQL_ENV_MYSQL_PASSWORD=database_user_password -e MYSQL_ENV_MYSQL_DATABASE=database_name -v /path/to/wordpress/files:/var/www/html -d wordpress

At this point you should be able to access your Word Press site on port 8080 of the Docker host.

For those that use boot2docker (even through docker-machine) your Word Press file directory may not be writeable by the Word Press docker container. To fix this I built the Word Press image directly from the associated Dockerfile with an extra command to modify the www-data user inside the image so that it’s UID matched a user’s UID on the source file systems directory that had write access to the Word Press files.