Local Development Environment with Docker for PHP (Part-1)
Tags: laravel, php, docker, webdev
Published: 2019-10-16 10:48:49

__*Setting Docker, Portainer, Nginx, PHP and Composer*__

If you work with different language, tools or technology its really hard some time to manage all these different environments in local machine. Docker is a great tool which give us isolated environment to build our application with required tools and libraries without messing with the host machine. You can package up an application with all of the parts it needs, such as libraries and other dependencies, and run it on any machine which have docker installed without installing a single piece of software. You can use different version of any tools separately without any hassle. So let’s see how can we use docker to setup our development environment to build application with Laravel.

### Install docker

I’m using antergos which is arch-linux based os, so installation instructions step below are for arch-linux distro. If you are on Mac or Windows or any other linux distro visit [here](https://www.docker.com/community-edition#download) for installation instruction.

    $ sudo pacman -S docker

To start the docker service (for any linux OS that use systemctl)

    $ sudo systemctl start docker.service

To start on system boot

    $ sudo systemctl enable docker.service

### Install Portainer

Portainer is a container which gives a nice ui dashboard to use docker easily. We’ll create and run the portainer container like below

    $ sudo docker run -d --name portainer -p 8000:8000 -p 9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

Above will create a container from portainer image and then run it in background ( -d flag make the container run in background). The command will search for the portainer image in local machine and if it doesn’t find the image then it will pull the image from docker image registry. We’ll run the container in port 9443 so port 9443 should be available, but if you want to use any other port than specify it via the -p flag ( -p 8080:9443 ). Also notice that we have named our container portainer with — name flag. You can name your container whatever you want. When the download is complete we can check that the container is running by $ docker ps command. It’ll show a list of all the running container

    CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                    NAMES
    1f5bb115d327        portainer/portainer   "/portainer"        5 seconds ago         Up 1 second         0.0.0.0:9000->9000/tcp   portainer

Now you can visit the dashboard by visiting localhost in your browser. You’ll see below screen

![](https://cdn-images-1.medium.com/max/2644/1*IiMm3jKgkKHpoWUXMdQCSg.png)

Provide a password for admin user account and then login to the dashboard. You’ll see a screen like below.

![](https://cdn-images-1.medium.com/max/2648/1*WkN1z_PM0cHqNpD_tJzLKw.png)

Select the first one and connect, you’ll see a nice dashboard

![](https://cdn-images-1.medium.com/max/2642/1*iiMMDvavsXI1S_KdvrWQIA.png)

### Create a PHP network

First we will create a network for php application only. Click the network menu from sidebar and then give it some name like php and click create.

![Create a php network](https://cdn-images-1.medium.com/max/2482/1*cVDl1WRrjx5lpluCRpt1Ug.png)*Create a php network*

### Install Nginx

First we will create a container as our server and we’ll use official nginx image from docker hub. Go to Containers page from sidebar menu and click on Add Container button

![Add New Container](https://cdn-images-1.medium.com/max/2646/1*FjabcxJNQtHKD9dgtrP27w.png)*Add New Container*

Let’s give our container a name of server and the image name which is nginx. Click the publish all exposed ports which’ll expose port 80. Next click map additional port and map our host machine port 80 to container port 80 like below

![Map host port 80 to container port 80](https://cdn-images-1.medium.com/max/2072/1*LbOqkYrRA3RlEBiMyIMwLA.png)*Map host port 80 to container port 80*

Next create two folders where you will keep your projects. This can be anywhere in your file system. One folders is to keep our application source code and the other is for nginx configuration.

![](https://cdn-images-1.medium.com/max/2000/1*ZUYYe0X6Psy8NsqtuhDJFw.png)

Now under Advanced Container Settings click the volume tab and bind sites directory to /var/www in container and nginx-conf directory to /etc/nginx/conf.d .

![](https://cdn-images-1.medium.com/max/2432/1*TWBD6U3WvslSYpjjZegxFw.png)

Next select the php network we created earlier in network tab. Finally hit the start container button. First portainer will pull the nginx image from registry and then start the container

![](https://cdn-images-1.medium.com/max/2090/1*qyle5bNsvQaeVH1BOEV2sA.png)

### Install PHP-FPM

Next we will install php fpm to serve our php application. We’ll create a container using official php-fpm image.

![](https://cdn-images-1.medium.com/max/2478/1*tBMvHo1vmNVLAnSvoq3GPA.png)

We don’t need to bind any port from our host machine to the container, nginx will send traffic to php-fpm, we just need to select the php network in network tab.

![](https://cdn-images-1.medium.com/max/2418/1*iMBk3-YUMDOonZCqoG1HVA.png)

Also we need to map our sites directory to the /var/www directory in the container.

![](https://cdn-images-1.medium.com/max/2410/1*oUUX9GcaQLH48ZOIoGX1aw.png)

Finally in Command tabs put /var/www as value in Working Dir field

![](https://cdn-images-1.medium.com/max/2414/1*o67Xa35i5hib1OqrYv6i6Q.png)

Now start the container by hitting start container button.

![](https://cdn-images-1.medium.com/max/2646/1*pMM_WxHLiE8mnpVzrTbkNg.png)

### Add Application

Let’s try to add our first php website. First add a hello.conf file inside nginx-conf directory with below contents

    server {
        listen 80;

        server_name hello.local;

        client_max_body_size 108M;

        access_log /var/log/nginx/hello.access.log;
        error_log /var/log/nginx/hello.error.log;

        root /var/www/hello/public;
        index index.php;

        if (!-e $request_filename) {
            rewrite ^.*$ /index.php last;
        }

        location ~ \.php$ {
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PHP_VALUE "error_log=/var/log/nginx/hello-php.log";
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            include fastcgi_params;
        }
    }

This file is for routing traffic to php-fpm. Next add a index.php file inside sites/hello/public directory with following contents

    <?php
    phpinfo();

And finally add a domain for our site in /etc/hosts file

    127.0.0.1    hello.local

Now visit [http://hello.local](http://hello.local) and you’ll see

![](https://cdn-images-1.medium.com/max/2644/1*VGJciA8oO9v10HDGF6aAQQ.png)

Now let’s add another site, the procedure is same. First we add conf file for nginx configuration and then add our code in a directory under sites and finally add a domain for that site in /etc/hosts file.

### Install PHP Extensions

By default only few extensions are installed in the container. If we want we can install more extensions. First let’s connect to the bash terminal of our php container. If you visit the container page you’ll see a console link, click it

![](https://cdn-images-1.medium.com/max/2406/1*skgNxzuS_2Si_UlyrCbR9A.png)

You’ll see a connect button to connect to the bash, click it and you’ll be at /var/www directory.

![](https://cdn-images-1.medium.com/max/2642/1*3t0MU2VcAo_wHjgwZ6z9-g.png)

Now let’s install pdo_mysql extension to use mysql pdo driver by following command

    $ docker-php-ext-install pdo_mysql

We’ll also install `gd` and `ext-zip` extensions

    $ docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && docker-php-ext-install gd

    $ apt-get install libzip-dev && docker-php-ext-install zip

You can install other extensions in similar way. After installing any extension restart the container.

### Install Composer

Before we install composer first install zip & unzip package which’ll be used by composer for laravel installation.

    $ apt-get update && apt-get install zip unzip

And now install composer

    $ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer

Let’s check composer is installed and in our path

    $ composer --version
    Composer version 1.4.2 2017-03-10 09:29:45

### Install Laravel

Lets install our first laravel application by running following command

    $ composer create-project --prefer-dist laravel/laravel example

It’ll create a new laravel app inside example directory. To make it accessible we have to create a example.conf and add example.local domain in /etc/hosts file. Also we need to change the owner of storage and boostrap folder like below

    $ chown -R www-data:www-data storage bootstrap

Now if we visit example.local in the browser we’ll see

![](https://cdn-images-1.medium.com/max/2648/1*0LLdZWXfbqAz8xUi8PomHA.png)

Adding another application will be same as before: 1) create a new laravel app inside sites directory, 2) add a new .conf file for that application, 3) add a domain in /etc/hosts 4) change owner of storage and bootstrap folder to www-data .

### Conclusion

We have one piece of the puzzle still left, that is database. We’ll see in next post how to add any database to our application and persist the data and also some other tools like redis etc. We’ll also see how can we use another php version to test the same application. Stay tuned!

#### [Part-2](/local-development-environment-with-docker-for-php-2)