Running PHP 5.3/5.6 in a Docker container with Nginx on Ubuntu 16.04

The docker installation procedure depends on the system architecture that can be determined with the following commands:

cat /proc/cpuinfo
dpkg --print-architecture

After I installed Docker I successfully run its test application:

docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b04784fba78d: Pull complete
Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:

docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

Then I created Ubuntu 16.04 image and played with it a bit to train how to commit changes and delete images:

docker run -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
75c416ea735c: Pull complete
c6ff40b6d658: Pull complete
a7050fc1f338: Pull complete
f0ffb5cf6ba9: Pull complete
be232718519c: Pull complete
Digest: sha256:a0ee7647e24c8494f1cf6b94f1a3cd127f423268293c25d924fbe18fd82db5a4
Status: Downloaded newer image for ubuntu:latest

Also I investigated the basic Docker commands:

docker ps -as
docker rm <container> <container> ...
docker images
docker rmi <image>:<tag>
docker commit <container> <image>/<tag>

There was some issues with the locate, so first I tried something like this:

locale-gen “en_US.UTF-8”
dpkg-reconfigure locales

But it did not work, and I created Dockerfile that sets up the locale correctly:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -y install apt-utils
RUN apt-get -y install locales

# Set the locale
RUN locale-gen en_US.UTF-8

RUN apt-get -y install software-properties-common
RUN apt-get update

To build the docker file and run the container the following commands can be used, assuming our file named ‘Dockerfile’ located in the current directory:

docker build -t php5 .
docker run -it php5

The rest of the installation and configuration I did manually (not in Dockerfile).

I installed PHP 5.6 with the following commands:

apt-get install software-properties-common
add-apt-repository ppa:ondrej/php
apt-get update
apt-get install php5.6
apt-get install php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-xml php5.6-cli
php -v

Created user ‘beauty’ with the same ID as on the host machine:

useradd -d /home/beauty -m --uid 1009 beauty

Mapped the volume (directory) and port and installed some further software for network diagnostics:

docker run -it -p 9001:9000 -v /home/beauty/www:/home/beauty/www php5
service --status-all
php-fpm5.6 -t
apt-get install net-tools
apt-get install iputils-ping
netstat -t -u -c
tcptrack -i any

Configured PHP-FPM to listen 9000 on all the network interfaces (probably is the most important part here) and allow the clients from IP address


user = nobody
group = beauty

listen =
listen.allowed_clients =

access.log = /var/log/php-fpm/$pool.access.log

catch_workers_output = yes
php_flag[display_errors] = on
php_admin_value[error_log] = /var/log/php-fpm/$pool.error.log
php_admin_flag[log_errors] = on

pm = dynamic

pm.max_children = 10
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 500

listen.backlog = -1
pm.status_path = /status

slowlog = /var/log/php-fpm/$pool.slow.log
request_slowlog_timeout = 5s

request_terminate_timeout = 300s
rlimit_files = 131072
rlimit_core = unlimited

chdir = /

socket-owner.conf file:

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
;                 mode is set to 0660
listen.owner = www-data = www-data
listen.mode = 0660

Made my Nginx on the host machine a reverse proxy and added ‘/status/ location support for showing PHP-PFM status in a browser:

server {
        location ~ ^/(status|ping)$ {
            include fastcgi.conf;

        location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_index index.php;
                include fastcgi.conf;

At this point I was able to see its status in browser by navigating to /status:

pool:                 beauty
process manager:      dynamic
start time:           03/Aug/2017:11:25:06 +0000
start since:          4370't_work_on_PHP_5.4
accepted conn:        17
listen queue:         0
max listen queue:     0
listen queue len:     128
idle processes:       0
active processes:     1
total processes:      1
max active processes: 1
max children reached: 0
slow requests:        0

And PHP info worked as expected:

PHP 5.6 info
The last step is allowing the access to MySQL database from Docker container. MySQL does not support binding to more than one IP address. We cannot have multiple bind-address directives or multiple IP addresses in a single bind-address directive, I set bind-address= and used a firewall to prevent connections from external IP addresses. Then I created a new user (with the same name as on localhost but with the different IP address and different password) for accessing MySQL database from docker:

SELECT User, Host FROM mysql.user;
CREATE USER 'beauty'@'' IDENTIFIED BY '*********';
GRANT SELECT, INSERT, UPDATE ON beauty.* TO 'beauty'@'';

My Joomla 1.x website connected to MySQL database, but it did not work with PHP 5.6 showing me the following errors in browser:

Strict Standards: Declaration of KHttpUri::set() should be compatible with KObject::set($property, $value = NULL) in /home/beauty/www/libraries/koowa/http/uri.php on line 0
Strict Standards: Declaration of KHttpUri::get() should be compatible with KObject::get($property = NULL, $default = NULL) in /home/beauty/www/libraries/koowa/http/uri.php on line 0
Strict Standards: Non-static method JLoader::register() should not be called statically in /home/beauty/www/libraries/joomla/cache/cache.php on line 19
Strict Standards: Declaration of JCacheStorage::get() should be compatible with JObject::get($property, $default = NULL) in /home/beauty/www/libraries/joomla/cache/storage.php on line 0
Strict Standards: Non-static method JLoader::register() should not be called statically in /home/beauty/www/libraries/joomla/document/document.php on line 19
Strict Standards: Non-static method JLoader::import() should not be called statically in /home/beauty/www/libraries/loader.php on line 186
Strict Standards: Non-static method JLoader::import() should not be called statically in /home/beauty/www/libraries/loader.php on line 186
Fatal error: Call-time pass-by-reference has been removed in /home/beauty/www/plugins/content/listitems.php on line 95

So, probably it makes a sense to install PHP 5.3, at least there is a command for switching between different versions of PHP:

sudo update-alternatives --set php /usr/bin/php5.6

I created another docker image with Ubuntu 12.04 and installed PHP 5.3 for its stock repository and configured PHP-FPM in the same way, except that I changed listen = ‘’ to ‘listen =’, PHP-FMP did not start with saying ‘unable to bind listening socket for address ‘′: Address already in use (98)’. Finally my Joomla 1.x website started to work with PHP 5.3.

Leave a Reply

Your email address will not be published. Required fields are marked *