Deploy a Containerized PHP Web Application with Docker
Tags: docker, containerapps, tutorial, devops
Published: 2023-01-12 16:54:24

In this project, you will be deploying a simple PHP-based containerized solution backed by a MySQL database application using Docker.

[Docker](https://docs.docker.com/get-started/overview/) is an open source platform for shipping, developing and running application on any OS running a docker engine. It is fast, takes less space than VMs and can be distributed or shipped as a Docker image.

[A quick 2 minutes read about Docker Container, Docker Image & Dockerfile](https://dev.to/oayanda/getting-started-docker-container-docker-image-dockerfile-2oj9)

**Prerequiste**

- [Docker](https://docs.docker.com/engine/install/ubuntu/) is installed on your ubuntu instance.
- Basic understanding of docker and containers.
- Basic Linux understanding will be helpful.
- [AWS free tier here](https://aws.amazon.com/free/)

Let's Begin.

### MySQL in Container

Let us start assembling the application from the backend Database layer – you will use a pre-built MySQL database container, configure it, and make sure it is ready to receive requests from the frontend PHP application.

**Step 1**: Pull MySQL Docker Image from [Docker Hub Registry](https://hub.docker.com/)

In the termainal, 

```bash
# Search available MySQL image in the docker hub registry
 
 docker search mysql-server
 ```
![docker search](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7zpw3y7r0k8ahqpqa5pu.png)

Next, you will pull the first on the list, which is the official and latest version and stored in the docker build cache locally.


```bash
# Download docker image locally from docker hub
docker pull mysql/mysql-server:latest
```

![docker image pull](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ky60zur7w60ot2qwr5fq.png)

You made this *pull* to make the container creation process faster. Otherwise, skip _step one_ and move to _step two_, which does the something.

**Step 2**: Deploy the MySQL Container to your Docker Engine

Once you have the docker image, move on to deploy a new MySQL container

```bash
# Create a MySQL container
docker run --name=mysqldb -e MYSQL_ROOT_PASSWORD=dontusethisinprod -d mysql/mysql-server:latest


# List all running containers
docker ps -a
```
![Mysql container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tg0r4ezoxv8xb1h3206i.png)

### Connecting to the MySQL Docker Container

Now, let's connect to the MySQL container directly

_**First Method**_

```bash
# Connect to the MySQL database and enter the from the initial step.

docker exec -it mysqldb mysql -uroot -p

# Exit the MySQL mode
exit
```
_Flags_
- Database name = mysqldb
- Username = -u
- Password = -p
- Interactive mode -it

![mysql](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kzjs14rx2p6roy0asq30.png)

You are going to use the second method below, so go ahead remove this container.

```bash
docker rm -f mysqldb
```

**_Second Method_**

After connecting to the MySQL container, you could go on can configure the schema and prepare it for the Frontend PHP application but this means you will be using the default bridge network which is the default way for connection for all containers. However, it better to create our own private network which enable us to control the network cidr.

Let's go ahead and create a network

```bash
# Create a new bridge network

docker network create --subnet=172.18.0.0/24 tooling_app_network
```
![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lp1tiobnutoyvxueqe7k.png)

This time, let us create an environment variable to store the root password:

```bash
# Save the password using environment variable
export MYSQL_PW=password

# verify the environment variable is created
echo $MYSQL_PW
```

> If you are using Window OS, run above command in your git bash terminal which comes with visual studio code editor.


![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax2bfljxbfq72tdjn1mr.png)

To avoid name conflict, remember to remove the initial container as stated above. Now, pull the image and run the container, all in one command like this below

```bash
docker run --network tooling_app_network -h mysqlserverhost --name=mysql-server -e MYSQL_ROOT_PASSWORD=$MYSQL_PW  -d mysql/mysql-server:latest
```

_Flags used_

- -d runs the container in detached mode
- --network connects a container to a network
- -h specifies a hostname

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lww11ny94hv8arejx329.png)

It is best practice not to connect to the MySQL server remotely using the root user. Therefore, you will create a SQL script that will create a user you can use to connect remotely.

Create a file and name it ***create_user.sql*** and add the below code in the file

 ```bash
 CREATE USER '<username>'@'%' IDENTIFIED BY '<password>'; 
 GRANT ALL PRIVILEGES ON * . * TO '<username>'@'%';
 ```
 Replace the username and password to your values.

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsadxgpmwfzm1buewq0w.png)

Now, run the script to create the new user. Ensure you are in the directory ***create_user.sql*** file is located.  

```bash
docker exec -i mysql-server mysql -uroot -p$MYSQL_PW < create_user.sql
```
![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5l8i6oys30fb7abbnaf2.png)

### Prepare Database Schema

Now, you need to prepare a database schema so that the Tooling application can connect to it.

Clone the Tooling-app repository from [here](https://github.com/oayanda/Tooling)

```bash
git clone https://github.com/oayanda/tooling-1
```
![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jtehzygzm0urtlb7gsw.png)

You can find the schema in tooling PHP application repo.

```bash
ls ~/tooling-1/html/
```

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tt11hmya4apjntn4dmif.png)

Use the SQL script to create the database and prepare the schema. With the `docker exec` command, you can execute a command in a running container.

```bash
docker exec -i mysql-server mysql -uroot -p$MYSQL_PW < ~/tooling-1/html/tooling_db_schema.sql
```

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rovs1uuh913nn6ff8b4r.png)

Next, you need to update the `.env` file with connection details to the database. The `.env` file is located in the html `~/tooling/html/`

```bash
# View the location of the file
ls la ~/tooling/html/
```

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsb32ef4775vyqs4xi5f.png)

Let's update the connection to the database using the `vi` editor

```bash
vi ~/tooling-1/html/.env
```

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebacwwek5hc3hd26o2f3.png)

***Flags used:***

- _MYSQL_IP_ mysql ip address "leave as mysqlserverhost"
- _MYSQL_USER_ mysql username for user export as environment variable
- _MYSQL_PASS_ mysql password for the user exported as environment varaible
- _MYSQL_DBNAME_ mysql databse name "toolingdb"

Update the `servername`, `username`, `password`& `databasename` in `db_conn.php` file in `tooling/html` directory

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7i08nkkm90lizneurky3.png)

Run the Tooling App

You are almost there. Now you need to containerized the Frontend Application as well and then connect it to the MySQL database.

However, as you now know that you need a Dock image to create a `Container` but you need a `Dockerfile` to create a `Docker image`. In the cloned tooling application repo you now have on system is a Dockerfile which you going to used to build the docker image.

> Ensure you are inside the directory "tooling" that has the file Dockerfile and build your container.

```bash 
docker build -t tooling:0.0.1 .
```

In the above command, we specify a parameter `-t`, so that the image can be tagged "`tooling.0.1`" - Also, you have to notice the `.` at the end. This is important as that tells Docker to locate the `Dockerfile` in the current directory you are running the command. Otherwise, you would need to specify the absolute path to the `Dockerfile`


![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9i320pi0sl12g4r8y2w.png)

Run the container

```bash
docker run --network tooling_app_network -p 8085:80 -it tooling:0.0.1 
```

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdkxz9clsbxb4o2p2qzk.png)

Ensure to allow port 8085 for a TCP connection in your security group.

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nblw7xd06zkvo066f45d.png)

View the login page in browser

![private](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a87uzdunuzn60llipwm9.png)

The default email is test@gmail.com, the password is 12345

> _Web application Repo from Darey.io_

Congratulation!!! You have successfully deployed a containerized web application with MySQL backend on docker.

As always, I look forward to getting your thoughts on this article. Please feel free to leave a comment!