<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayman Elmalah</title>
    <description>The latest articles on DEV Community by Ayman Elmalah (@ayman_elmalah).</description>
    <link>https://dev.to/ayman_elmalah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F580981%2F768393ed-3eef-4fd2-a013-e38dc683d489.png</url>
      <title>DEV Community: Ayman Elmalah</title>
      <link>https://dev.to/ayman_elmalah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayman_elmalah"/>
    <language>en</language>
    <item>
      <title>Dockerize php application</title>
      <dc:creator>Ayman Elmalah</dc:creator>
      <pubDate>Thu, 20 May 2021 12:23:02 +0000</pubDate>
      <link>https://dev.to/ayman_elmalah/dockerize-php-application-ikm</link>
      <guid>https://dev.to/ayman_elmalah/dockerize-php-application-ikm</guid>
      <description>&lt;p&gt;In this article you will learn how to dockerize php application or any php framework like laravel, symfony and others&lt;br&gt;
The first question is : What is docker ?&lt;br&gt;
Docker is a set of platform as service (PaaS) products that uses OS level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating system kernel and therefore use fewer resources than virtual machines&lt;/p&gt;

&lt;p&gt;you can learn more about docker from &lt;a href="https://www.docker.com/"&gt;https://www.docker.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prerequests&lt;/p&gt;

&lt;p&gt;Docker installed&lt;br&gt;
Knowledge about docker&lt;br&gt;
Knowledge about php&lt;br&gt;
What services we will use in this article ?&lt;/p&gt;

&lt;p&gt;php&lt;br&gt;
mysql&lt;br&gt;
nginx&lt;br&gt;
phpmyadmin&lt;br&gt;
composer&lt;br&gt;
artisan&lt;br&gt;
npm&lt;br&gt;
We need to build directory structure for the application first&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- phpdock
|   |-- nginx
|   |   |-- default.conf
|   |-- php
|   |   |-- Dockerfile
|   |-- .env
|   |-- .env.example
|   |-- .gitignore
|   |-- docker-compose.yml
|
|-- src
    |-- public
        |-- index.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;First thing we will open our phpdock/docker-compose.yml then start structuring our file&lt;/p&gt;

&lt;p&gt;version: '3'&lt;/p&gt;

&lt;p&gt;networks:&lt;br&gt;
  backend:&lt;/p&gt;

&lt;p&gt;services:&lt;br&gt;
  php:&lt;/p&gt;

&lt;p&gt;mysql:&lt;/p&gt;

&lt;p&gt;nginx:&lt;/p&gt;

&lt;p&gt;phpmyadmin:&lt;/p&gt;

&lt;p&gt;composer:&lt;/p&gt;

&lt;p&gt;artisan:&lt;/p&gt;

&lt;p&gt;npm:&lt;/p&gt;

&lt;p&gt;This will be the file structure for docker-compose.yml file, we will use version 3 of docker compose, the network to communicate between services will be backend, you can name it the name you want&lt;/p&gt;

&lt;p&gt;and we will list the services as showed in code&lt;/p&gt;

&lt;p&gt;HINT : we will use .env to save environment data and call it in docker&lt;/p&gt;

&lt;p&gt;As known .env can contain key=value and in docker we can call value by the given key as this way ${KEY}&lt;/p&gt;

&lt;p&gt;Now we can start building the first service in our app, it's PHP&lt;/p&gt;

&lt;p&gt;we still openeing docker-compose.yml so web can update php service&lt;/p&gt;

&lt;p&gt;php:&lt;br&gt;
    build:&lt;br&gt;
      context: ./php&lt;br&gt;
      dockerfile: Dockerfile&lt;br&gt;
    container_name: php&lt;br&gt;
    volumes:&lt;br&gt;
      - ../src:/var/www/html&lt;br&gt;
    ports:&lt;br&gt;
      - "${PHP_PORT}:${PHP_HOST_PORT}"&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt;We can now explain this part&lt;/p&gt;

&lt;p&gt;In this part we will use Dockerfile to pull php from docker, the docker file will be placed in phpdock/php/Dockerfile so the service will use context ./php as it's the path of Dockerfile, then the docker file name is Dockerfile, we can now name the pulled container php or the name you want, we will use the volumes to share user data to the container directory so developer will work on src/ and we can access this path using ../src and it will share this data to var/www/html as working directory, now we need to use a port for php, we will write it in .env and use it in this file as a variable like ${KEY}, networks that will be used in php is backend&lt;/p&gt;

&lt;p&gt;Now we can update phpdock/php/Dockerfile&lt;/p&gt;

&lt;p&gt;FROM php:7.4-fpm-alpine&lt;/p&gt;

&lt;p&gt;WORKDIR /var/www/html&lt;/p&gt;

&lt;p&gt;RUN docker-php-ext-install pdo pdo_mysql&lt;/p&gt;

&lt;p&gt;in dockerfile we can pull php version from official php, and we can make workdir /var/www/html , we need other extenstions to be installed in our app, you can add the extensions you want, it's a simple example &lt;/p&gt;

&lt;p&gt;Now we can update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## PHP
&lt;/h6&gt;

&lt;p&gt;PHP_PORT=8081&lt;br&gt;
PHP_HOST_PORT=80&lt;/p&gt;

&lt;p&gt;The other service that we need to update is MYSQL, we will open docker-compose.yml and update mysql service&lt;/p&gt;

&lt;p&gt;mysql:&lt;br&gt;
    image: mysql:${MYSQL_VERSION}&lt;br&gt;
    container_name: mysql&lt;br&gt;
    restart: always&lt;br&gt;
    tty: true&lt;br&gt;
    ports:&lt;br&gt;
      - "${MYSQL_PORT}:${MYSQL_HOST_PORT}"&lt;br&gt;
    environment:&lt;br&gt;
      MYSQL_DATABASE: ${MYSQL_DATABASE}&lt;br&gt;
      MYSQL_USER: ${MYSQL_USER}&lt;br&gt;
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}&lt;br&gt;
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}&lt;br&gt;
      SERVICE_TAGS: dev&lt;br&gt;
      SERVICE_NAME: mysql&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt;The same code as php but now we can pull mysql from docker-compose.yml, the new thing you need to know that in mysql we need to create database with user and password after installation, so we wrote environment variables&lt;/p&gt;

&lt;p&gt;Now we can update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## MYSQL
&lt;/h6&gt;

&lt;p&gt;MYSQL_VERSION=5.7.29&lt;br&gt;
MYSQL_DATABASE=default&lt;br&gt;
MYSQL_USER=default&lt;br&gt;
MYSQL_PASSWORD=secret&lt;br&gt;
MYSQL_ROOT_PASSWORD=secret&lt;br&gt;
MYSQL_PORT=3306&lt;br&gt;
MYSQL_HOST_PORT=3306&lt;/p&gt;

&lt;p&gt;The other service that we need to update is NGINX, we will open docker-compose.yml and update nginx service&lt;/p&gt;

&lt;p&gt;nginx:&lt;br&gt;
    image: nginx:${NGINX_VERSION}&lt;br&gt;
    container_name: nginx&lt;br&gt;
    ports:&lt;br&gt;
      - "${NGINX_PORT}:${NGINX_HOST_PORT}"&lt;br&gt;
    volumes:&lt;br&gt;
      - ../src:/var/www/html&lt;br&gt;
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf&lt;br&gt;
    depends_on:&lt;br&gt;
      - php&lt;br&gt;
      - mysql&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt; we will pull nginx and we can add a new volume to make developer write app configuration as the way app need, the nginx depends on php and mysql services&lt;/p&gt;

&lt;p&gt;Now we can update phpdock/nginx/default.conf&lt;/p&gt;

&lt;p&gt;server {&lt;br&gt;
    listen 80;&lt;br&gt;
    index index.php index.html;&lt;br&gt;
    server_name localhost;&lt;br&gt;
    error_log  /var/log/nginx/error.log;&lt;br&gt;
    access_log /var/log/nginx/access.log;&lt;br&gt;
    root /var/www/html/public;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;and we can also update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## NGINX
&lt;/h6&gt;

&lt;p&gt;NGINX_VERSION=stable-alpine&lt;br&gt;
NGINX_PORT=8080&lt;br&gt;
NGINX_HOST_PORT=80&lt;/p&gt;

&lt;p&gt;The other service that we need to update is PHPMYADMIN, we will open docker-compose.yml and update phpmyadmin service&lt;/p&gt;

&lt;p&gt;phpmyadmin:&lt;br&gt;
    image: phpmyadmin/phpmyadmin:${PHPMYADMIN_VERSION}&lt;br&gt;
    container_name: phpmyadmin&lt;br&gt;
    restart: always&lt;br&gt;
    ports:&lt;br&gt;
      - "${PHPMYADMIN_PORT}:${PHPMYADMIN_HOST_PORT}"&lt;br&gt;
    depends_on:&lt;br&gt;
      - php&lt;br&gt;
      - mysql&lt;br&gt;
    environment:&lt;br&gt;
      PMA_HOST: ${PMA_HOST}&lt;br&gt;
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt;phpmyadmin is very easy to understand how to build, it's the same as other services and no thing is complicated, &lt;/p&gt;

&lt;p&gt;and we can also update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## PHPMYADMIN
&lt;/h6&gt;

&lt;p&gt;PHPMYADMIN_VERSION=4.7&lt;br&gt;
PHPMYADMIN_PORT=8082&lt;br&gt;
PHPMYADMIN_HOST_PORT=80&lt;br&gt;
PMA_HOST=mysql&lt;/p&gt;

&lt;p&gt;Now the application is ready for running but other frameworks like laravel will need some features to work well like composer, artisan, and npm so we will add it to our app and of you dont need it you can skip this step&lt;/p&gt;

&lt;p&gt;Now we can add features we will need, so we will update now composer service at docker-compose.yml&lt;/p&gt;

&lt;p&gt;composer:&lt;br&gt;
    image: composer:${COMPOSER_VERSION}&lt;br&gt;
    container_name: composer&lt;br&gt;
    volumes:&lt;br&gt;
      - ../src:/var/www/html&lt;br&gt;
    working_dir: /var/www/html&lt;br&gt;
    depends_on:&lt;br&gt;
      - php&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt;it's very easy to understand this code, so we can now update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## COMPOSER
&lt;/h6&gt;

&lt;p&gt;COMPOSER_VERSION=latest&lt;/p&gt;

&lt;p&gt;Now we can add artisan service, we can update docker-compose.yml&lt;/p&gt;

&lt;p&gt;artisan:&lt;br&gt;
    build:&lt;br&gt;
      context: ./php&lt;br&gt;
      dockerfile: Dockerfile&lt;br&gt;
    container_name: artisan&lt;br&gt;
    volumes:&lt;br&gt;
      - ../src:/var/www/html&lt;br&gt;
    depends_on:&lt;br&gt;
      - mysql&lt;br&gt;
    working_dir: /var/www/html&lt;br&gt;
    entrypoint: ['php', '/var/www/html/artisan']&lt;br&gt;
    networks:&lt;br&gt;
      - backend&lt;/p&gt;

&lt;p&gt;The new thing you want to know is entrypoint, we do it to make developer write the command artisan and it will point to php /var/www/html/artisan, it's the php path&lt;/p&gt;

&lt;p&gt;The last section we will do is npm service, we can update docker-compose.yml&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
    image: node:${NODE_VERSION}&lt;br&gt;
    container_name: npm&lt;br&gt;
    volumes:&lt;br&gt;
      - ../src:/var/www/html&lt;br&gt;
    working_dir: /var/www/html&lt;br&gt;
    entrypoint: ['npm']&lt;/p&gt;

&lt;p&gt;And we need now update phpdock/.env&lt;/p&gt;

&lt;h6&gt;
  
  
  ################## NODE
&lt;/h6&gt;

&lt;p&gt;NODE_VERSION=13.7&lt;/p&gt;

&lt;p&gt;Now we can copy .env file content to .env.example content, and in .gitignore we can make .env ignored so we can push it to any git repository without push .env to save our data&lt;/p&gt;

&lt;p&gt;Now the services is ready for installed&lt;/p&gt;

&lt;p&gt;you can now open your terminal and go to phpdock directory then run this command&lt;/p&gt;

&lt;p&gt;docker-compose build &amp;amp;&amp;amp; docker-compose up -d&lt;/p&gt;

&lt;p&gt;Then open src/public/index.php&lt;/p&gt;

&lt;p&gt;&amp;lt;?php&lt;/p&gt;

&lt;p&gt;echo "Hello world";&lt;/p&gt;

&lt;p&gt;Open your browser and visit &lt;a href="http://127.0.0.1:8080/%C2%A0for"&gt;http://127.0.0.1:8080/ for&lt;/a&gt; your php code, &lt;a href="http://127.0.0.1:8082/%C2%A0for"&gt;http://127.0.0.1:8082/ for&lt;/a&gt; phpmyadmin access&lt;/p&gt;

&lt;p&gt;All thing is good until now&lt;/p&gt;

&lt;p&gt;If you want to install laravel as example, you can clone it into src app then access this link in brwoser you will show laravel app &lt;a href="http://127.0.0.1:8080/"&gt;http://127.0.0.1:8080/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run composer command like composer dump autoload =&amp;gt; go to terminal in phpdock and run this command&lt;br&gt;
docker-compose run composer dump-autoload&lt;/p&gt;

&lt;p&gt;To run artisan command like php artisan migrate =&amp;gt; go to terminal in phpdock and run this command&lt;br&gt;
docker-compose run artisan migrate&lt;/p&gt;

&lt;p&gt;To run npm command like npm install =&amp;gt; go to terminal in phpdock and run this command&lt;br&gt;
docker-compose run npm install&lt;/p&gt;

&lt;p&gt;If you are using laravel, these lines will be database environments variables in .env, or the variables you wrote in .env for docker&lt;/p&gt;

&lt;p&gt;DB_CONNECTION=mysql&lt;br&gt;
DB_HOST=mysql&lt;br&gt;
DB_PORT=3306&lt;br&gt;
DB_DATABASE=default&lt;br&gt;
DB_USERNAME=default&lt;br&gt;
DB_PASSWORD=secret&lt;/p&gt;

&lt;p&gt;You will find source code &lt;a href="https://github.com/ayman-elmalah/phpdock"&gt;https://github.com/ayman-elmalah/phpdock&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
