In this tutorial, I am demonstrating how easy it is to create a stack (a development/production environment) of your own using docker-compose
. I am going to create a LEMP stack (Linux - nginx - MariaDB - PHP 5.6). I’m not eager to write my own image yet because, well, there are already images available for nginx, MariaDB, and PHP 5.6. What I want is to link them together to create my own service.
- Go to docker hub and search for nginx, mariadb, and php, and choose the images that I want to use to compose my stack
- nginx:1.11.8-alpine
- mariadb:5.5
- php:5.6-fpm-alpine
The reason I choose alpine image over other images is that alpine images are usually much smaller.
-
Create a project folder for the LEMP stack
mkdir LEMP cd LEMP
-
Create a
www
folder to contain PHP source code, and make aphpinfo()
test scriptmkdir www echo "<?php phpinfo(); ?>" > ./www/index.php
-
Create a folder for containing log files
mkdir logs
-
Create a
./nginx/site.conf
file containing the server’s configurationserver { listen 80; root /www; index index.html index.htm index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass phpfpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
This is pretty much a standard configuration for an nginx-phpfpm site. Except this line:
fastcgi_pass phpfpm:9000;
We are going to link the nginx container with the phpfpm container, thus
phpfpm
will be available in the nginx container’shosts
-
Create a
docker-compose.yml
file with the following contentversion: '2' services: mariadb: image: mariadb:5.5 user: $UID environment: - MYSQL_ROOT_PASSWORD=password123 - MYSQL_DATABASE=yii - MYSQL_USER=yii - MYSQL_PASSWORD=abcd1234 phpfpm: image: php:5.6-fpm-alpine user: $UID volumes: - ./www:/www links: - mariadb nginx: image: nginx:1.11.8-alpine user: $UID volumes: - ./nginx:/etc/nginx/conf.d - ./logs:/var/nginx/logs - ./www:/www ports: - 80:80 links: - phpfpm command: /bin/sh -c "nginx -g 'daemon off;'"
Things here are pretty straightforward:
- We have 3 services in our stack:
mariadb
,nginx
, andphpfpm
- What
environment
does is obvious ./nginx
will be mounted to nginx’s sites folder./logs
will be mounted to nginx’s logs folder./www
will be mounted on bothnginx
andphpfpm
containers, so the php process will also have access to the same file paths as nginxmariadb
is linked tophpfpm
, andphpfpm
is linked to nginx. There’s no need for nginx to link with mariadb, since static files don’t make database connections
- We have 3 services in our stack:
-
Check your folder’s structure
$ tree ./ ./ ├── docker-compose.yml ├── logs ├── nginx │ └── site.conf └── www └── index.php
-
Run the stack
export UID docker-compose up -d
- Go to localhost and check if your
phpinfo()
script has been successfully executed -
Testing database connection by replacing the content of
./www/index.php
with the following<?php $servername = "mariadb"; $username = "yii"; $password = "abcd1234"; // Create connection $conn = new mysqli($servername, $username, $password); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } echo "Connected successfully"; ?>
There should be an error message that says something like this
Fatal error: Class 'mysqli' not found in /www/index.php on line 7
We’ll just have to install
mysqli
. Luckily, it isn’t too complicated. The instructions are already on the php docker hub repodocker exec lemp_phpfpm_1 docker-php-ext-install mysqli
Restart the service
docker-compose restart
- Now, again, connect to localhost. It should say
Connected successfully