Tuesday, September 10, 2019

Docker - Apache, PHP and MySQL setup

Here we will be doing an installation of the development/production environment of PHP and MySQL using Docker under Ubuntu. Here is a full video on the subject:


For more information, you can check the Docker for web developers course.

First, we will install docker and docker-compose:  

sudo apt install docker docker-compose

Then we will create docker group and place our user inside(to be able to use the docker command without sudo): 

sudo groupadd docker && sudo usermod -aG docker $USER

 
Now we either exit and re-run the terminal or type: 

newgrp docker

to switch our group.


Let's check the current images we are having: from docker image ls. We can test if docker's installation is successful with: 

docker run hello-world

 
Keep in mind that we can check what images we have in our system via:  

docker image ls

and our containers via 

docker container ls
 

With docker 

rmi hello-world: latest

we will remove the just installed image, but only if it is empty.
 

Let's check once again  

docker container ls -a

which will list all the images: running or not. We see our image is placed inside a container.


As a rule: if we want to remove an image, first we have to remove its container.
So we look up the container name. It is usually assigned by docker and in our case is: relaxed_cray and then we type 

docker container rm relaxed_cray

Now we can remove the image with 

docker rmi hello-world:latest


Setting up the PHP development environment
We will make a directory web_dev : 

mkdir web_dev

and will go inside:  

cd web_dev

Then we will create docker-compose file with: 

nano docker-compose.yml

Inside we will place the following config:
Keep in mind that for the indentations we are using 2 spaces! 

services:
  web:
       image: php:8.1-apache
        container_name: php81
        volumes:
           - ./php:/var/www/html/
        ports:
          - 8008:80

Short explanation: under volumes: we are specifying which local directory will be connected with the container directory. So whenever we are changing something local, the container will reflect and display the changes. For the ports: when we open/browse local port 8008 (127.0.0.1:8008) docker will redirect us to the 80 port of the docker container (achieved via port forwarding).
For the PHP image, you can choose whatever image you prefer from hub.docker.com
Next run: docker-compose up. This will read the docker-compose file and create a container by loading up different parts/layers of the packages, later will create a default network for our container and will load up the already provided PHP image.
The installation is ready, but if you want to display practical information, you have to create index.php file inside the newly created local PHP directory (storing our PHP files)
First, it is good to change the ownership of the directory with:
sudo chown your_user:your_user php/ -R

Then with
sudo nano index.php
we can type inside:
<?php 
echo "Hello from docker";
?>
Then again run docker-compose up. Also, try changing the .php file again and refresh the browser pointing to 127.0.0.0:8008

MYSQL support
let's create a new file Dockerfile, inside the PHP directory. Place inside:

FROM php:8.1-apache
RUN apt-get update && apt-get upgrade -y RUN docker-php-ext-install mysqli
EXPOSE 80

This will base our MySQL on the PHP image, that we already have, update the container system, run  specific docker extensions supporting MySQL from within PHP and expose 80-port

Next, we will customize the docker-compose.yml :
We will replace the line: image: PHP
with

buid:
  context: ./php
  dockerfile: Dockerfile 

This will read the docker file which we have set previously and create web service out of it.

Now we will be building the MySQL service:

db:
  container_name: mysql8
  image: mysql:latest
  command: --default-authentication-plugin=mysql_native_password
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: test_db
    MYSQL_USER: devuser
    MYSQL_PASSWORD: devpass
   ports:
       - 6033:3306

Notes: We are using default authentication for MySQL in order to be able to login to the MySQL database, then docker is hardcoding mysql_user, mysql_password and mysql_database with: deuser, devpass, and test_db, and is exposing externally port 6033 for the MySQL service.

One last change: we would like first start the MySQL then the DB service, so we will add to the web service config:

depends_on:
  - db

To test the PHP-MySQL connection inside of our index.php file we can specify:

$host = 'db';  //the name of the mysql service inside the docker file.
$user = 'devuser';
$password = 'devpass';
$db = 'test_db';
$conn = new mysqli($host,$user,$password,$db){
 if($conn->connect_error){
  echo 'connection failed'. $conn->connect_error;
}
echo 'successfully connected to MYSQL';
}

If you experiencing problems you can remove the several images already created:

docker image ls -a 
docker rmi image ...fill here image names...
then run again docker-compose up and browse: 127.0.0.1:8008

Cheers and enjoy learning further.

Subscribe To My Channel for updates