Dockerize PHP Application
Tags: php, docker, webdev, beginners
Published: 2022-08-25 20:57:00

Dockerize an application comes up with many benefits. Modern micro service architecture requires application to be containerised. It also minimise the gap between production environment and development environment. Developer can up and running with all the dependencies with a single command.


![Docker rulez](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5k2537edh1pzgn3vwi30.jpeg)


While dockerize, development of compiled language can suffer from various problems. One of the major bottleneck is inspect the change set after a minor change. There are many hot reload options available out there for different stacks, but mostly very slow and buggy. Sometimes change sets are not propagated properly causing unnecessary hassle.


![Development of compiled language using docker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gp0q8zc9tx0vjidt1ev.jpg)


Besides scripting language like PHP does not suffer from these problem. As long as files are inside the `apache`'s serving directory all the changes is visible to the apache server. To say briefly `apache` spawn a `php` process to a particular `.php` file specified in the request path.


![Advantage of PHP development using docker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtpaefqxuglb4tgygq19.gif)


So how we can get benefitted with it while developing using docker container ?

Let's start how can we leverage the power of containerisation with docker for PHP application. 

You can check [this repository](https://github.com/ratulSharker/painless-php) or start from scratch. Our directory structure will look like following.

```txt
.
├── src
│   └── index.php
├── Dockerfile
└── docker-compose.yml
```

Inside the `index.php` an awesome script is written, which looks like:

```php
<?php echo "Hello world\n"; ?>
```

![Awesome script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1wtedw126nle76oflcq.jpg)

Now for dockerize the application, a `Dockerfile` is necessary. We need `php` and `apache` pre installed docker image. [`php:apache-buster`](https://hub.docker.com/layers/php/library/php/apache-buster/images/sha256-3116abca1a9a1314af1818fd96d3ad2e777408a1c10798fa11aa66ac88759243?context=explore) image such an image we are looking for.

Using that image as base image, our `Dockerfile` will look like following

```dockerfile
FROM php:apache-buster

COPY ./src/* /var/www/html

CMD ["apache2-foreground"]
```

Right after the base image `FROM` command, we copied our content of `src` folder inside the `/var/www/html` from where apache serves files while requesting.

The last line actually running apache in foreground. Actually i copied it from the base image `php:apache-buster` 😉.

So the definition for our image is ready.


![Done imaging](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxrxr3ehfwhl7g773rcm.jpg)


Now time for local orchestration file `docker-compose.yml`. This file dictates the configuration to ran the image. 

```yml
version: '3.2'
services:
  awesome-app:
    build:
      context: .
      dockerfile: Dockerfile
    image: awesome-app:latest
    ports:
    - 80:80
    volumes:
    - type: bind
      source: ./src
      target: /var/www/html
```

Here what is done, a service is declared named `awesome-app`. This service will build image using the `Dockerfile` we just finished writing. We named the image `awesome-app` and tagged it with `latest`. Exposed the port `80` to the host so that apache can be accessed from the host. 

The last part is the trickiest one, we mount a volume which connects the hosts `./src` (our source directory) to container's `/var/www/html` (directory where apache serves from). This volume mounting will make sure, any change done inside the `./src` will be seen by the `apache`.

![Finished the docker composing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqbsxty1vwcbj1c0gukk.jpg)

Now time for testing. To test everything is working as expected we will do followings

1. Starting `awesome-app`.
2. Check existing output.
3. Change code.
4. Inspect changed output.

**1. Starting `awesome-app`**

To start my `awesome-app` we will use `docker-compose`

```sh
docker-compose up -d
```

This will create a `awesome-app` container in the background

**2. Check existing output**

To inspect the output of existing codebase i will use `curl`

```sh
curl -i http://localhost
```
```http
HTTP/1.1 200 OK
Date: Thu, 25 Aug 2022 19:27:35 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/8.1.9
Content-Length: 12
Content-Type: text/html; charset=UTF-8

Hello world
```

**3. Change code:**

Now i will modify code inside `index.php`

```php
<?php echo "My Awesome app says hello world\n"; ?>
```

**4. Inspect changed output.**

```sh
curl -i http://localhost
```
```http
HTTP/1.1 200 OK
Date: Thu, 25 Aug 2022 19:37:24 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/8.1.9
Content-Length: 32
Content-Type: text/html; charset=UTF-8

My Awesome app says hello world
```

![We did it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b12cj3300yd8exxrigz4.jpg)

See, it just like developing PHP application locally with all the benefits of docker.

All the above codes is available in [my github repository](https://github.com/ratulSharker/painless-php).