Getting started with docker with DOMPP
Tags: docker, mysql, php, phpmyadmin
Published: 2022-09-11 04:41:12

First thing first here's the link to repo if you waana directly jump to code:
https://github.com/yogeshgalav/dompp

Few weeks before my manager asked me to switch from MariaDB to Mysql. As we were doing work on xampp and windows it was a complex task for me and I lost my all databases in the process. But the lost did not affect me as I already have this experience due to Xampp mysql and apache error. Wampp was a good alternative but the day it also gave me error I finally decided to switch to docker. 

_If you are a php or laravel developer who has got frustated from amount of errors, issues and fixes local servers like Xampp or Wampp takes, Then it's your time to move on to docker._

_By the way for knowledge part you don't need apache to be running for laravel local development. The command 'php artisan serve' just need php path in environment variable._

## Introduction to docker
If you are not familiar with docker it's kind of light weight virtual machine which you can be configured with few files. And you can share the same files with your fellow developers to construct the same environment as yours in just one build. Yes, you don't have to guide them step by step installation of software or dependencies or commands one by one. And don't forget the errors you get while installation, I bet you would like to forget them too.

Now coming back to solution for php server along with Mysql and PhpMyAdmin, I created a Docker based solution which only consists of few files and is not actually a software which personally I think is a great thing.

**In this blog I will help you setup docker, php-fpm, Mysql and PhpMyAdmin with help of DOMPP on your local.** 

But first let's just go through some definitions if you are not familiar with docker.

**Containers** 
Containers are processes which our application requires like in our case nginx, php-fpm, mysql. These process can keep running like apache or nginx or can exite after doing their job like composer install or npm install. Each container will behave as separate virtual machine or os. So you can access folders like bin, etc, lib inside each container via terminal.
 
**Images** 
Images are just files to define or setup those processes. Images can be custom made or can be pulled from docker hub. Like php-fpm is available on docker hub but we also want pre defined php extensions or want to define permission for project folder or anything predefined you want related to php.

**Volumes (-v)**
Volumes are folder or directory on your os which will be synced with directory inside these virtual machine or os.
On left side we define our local directory and on right side the container's directory.
Volumes are used for noticing regular changes inside directory while containers are running but if you want not to sync and only copy before the containers starts you can use "COPY" command.

**Ports (-p)**
Every process on our OS run on a port. So to "EXPOSE" ports of our VMs to our local OS we need some methodology.
Same as volumes on left side we will define our local port and on right side port of container.
Only condition here is our local port should be free not utilized.

**Environment**
Here we define environment variables predefined and used by our images.

**Networks**
As I have said each container behave as separate OS then what if we require some communication between these containers, Hence we use networks to keep our containers communicating via ports.

**RUN**
RUN inside docker file is used to run commands during construction of image.

**CMD**
CMD inside docker file is used to run final commands or process which will run image as container.

**Let's start docker setup with creation of files .env and  _docker-compose.yaml_**

The env file will help us make docker-compose file little customisable and it will contains our local OS ports and other information so it will make things more clear to you.

_.env_
```
PROJECT_DIR=dompp
PHP_DOCKERFILE=php74
MYSQL_PORT=3306
PMA_PORT=8183
NGINX_PORT=8081
```

The docker-compose file will always start with version of docker, then we define our services. Services are the definition of containers and their images.

```
version : '3'

services:
```

## Nginx
```
image: nginx:latest
    container_name: dompp_nginx
    ports:
      - "${NGINX_PORT}:80"
    volumes:
      - ./htdocs/${PROJECT_DIR}:/var/www/
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    networks:
      - dompp
    depends_on:
      - php
      - mysql
```
Here we are pulling image "nginx:latest" from docker,
Naming the container,
Assigning port 8081 of our local OS to port 80 of container.
This container will read files from "/var/www" and hence we sync files from our local "./htdocs/PROJECT_DIR" with container's folder.
Now "depends_on" suggests that the docker need to start php and mysql container before nginx because it depends on them.

_default.conf_
```
server {
  listen 80;
  root /var/www/public;
  index index.php index.html;
  server_name localhost;
  location / {
    try_files $uri $uri/ =404;
  }
}
```
This is nginx configuration file which reads index.html or index.php file and serves at localhost.
The only thing you need to care of is 'root' i.e. your path of index file. Make sure your index file is located inside public folder of your project which is default for Laravel. In case you are using core php or some other framework change it accordingly.

## PHP
```
build:
      context: .
      dockerfile: ./php/${PHP_DOCKERFILE}.dockerfile
    container_name: dompp_${PHP_DOCKERFILE}
    volumes:
      - ./htdocs/${PROJECT_DIR}:/var/www/
    networks:
      - dompp
```
Here instead of directly pulling image from docker we are using our custom image defined in file "./php/php74.dockerfile"

_php74.dockerfile_
```
FROM php:7.4-fpm
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
EXPOSE 9000
CMD ["php-fpm"]
```
Inside php74.dockerfile we are taking a staring point or base image from docker hub,
Then we install all essential php extensions,
Then we copy composer from docker hub image to our php-fpm image,
Then we expose 9000 port to local OS,
And finally we execute command to run as container "php-fpm"

## MySql
```
 image: mysql:latest
    container_name: dompp_mysql
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: default_schema
    ports:
    - ${MYSQL_PORT}:3306
    networks:
      - dompp
```
Here we pull our mysql latest image from docker hub,
Sync our "./mysql" folder which will initially be empty but later on will contain all the databases and respective information.
And define our environment variables which will be used by container.
 
## PhpMyAdmin
```
image: phpmyadmin/phpmyadmin
    container_name: dompp_pma
    links:
      - mysql
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306
      PMA_ARBITRARY: 1
      UPLOAD_LIMIT: 300M
    volumes:
      - ./phpmyadmin:/var/lib/mysql
    ports:
      - ${PMA_PORT}:80
    networks:
      - dompp
```
Same as all the above containers here also we pull image from docker hub and define environment variables. 
New thing here is link which help phpmyadmin container read IP address and host name of mysql container. In short linking.

## Commands
Now to start all containers defined in this file run
`docker compose up`
To run containers in background
`docker compose up -d` 
To stop all containers
`docker compose down`
To list all conatiners
`docker ps -a`
To list all images
`docker image ls`
And if you make changes in image and rebuild without cache
`docker-compose up -d --force-recreate --build`

## Limiting Docker RAM and CPU usage
One of the main downside of using docker in windows is more ram and cpu usage but you can easily decrease that also.
**Limit RAM**
Create a .wslconfig file inside C:/users/<username>
and paste the following content inside it
```
[wsl2]
memory=4GB
processors=4
swap=0
```

I hope you enjoyed reading this.
Please give your love and support to my Github open source repositories.
And If you are stuck somewhere or need to outsource your project feel free to hire us.

Thank You and Have Nice Day!