Dockerize a Laravel 5 App with PHP-FPM, NGINX and MySQL

Laravel 5 is a nice PHP framework for web artisans that enables to easily write robust MVC applications. Also it encourages the use of Homestead for local development .

Homestead is a Vagrant box that comes out of the box with all you need to cleanly write PHP web apps without messing up your operating system.

However, what if you need Docker in your project rather than Vagrant? If that sounds like you, don’t miss today’s boilerplate to dockerize a simple Laravel app for local developmentthis dockerized blog available on GitHub.

First things first, create a fresh Laravel installation:

composer create-project --prefer-dist laravel/laravel dockerized-blog
cd dockerized-blog

By the way, it is always a good idea to keep track of changes from minute one, so let’s initialize a git repository right away.

git init
git add -A
git commit -m "first commit"

Don’t forget to add the following entry to your /etc/hosts file:

127.0.0.1       blog.local

Now, here is a basic Docker set up for our Laravel app.

Dockerfile

FROM php:7.2-fpm

RUN apt-get update && apt-get install -y \
    git \
    libzip-dev \
    zip \
    unzip

RUN docker-php-ext-configure zip --with-libzip

RUN docker-php-ext-install pdo_mysql zip

RUN curl --silent --show-error https://getcomposer.org/installer | php && \
    mv composer.phar /usr/local/bin/composer

docker-compose.yml

version: "3.5"

services:
  php_fpm:
      build: .
      container_name: blog_php_fpm
      working_dir: /usr/share/nginx/blog
      networks:
        - blog
      volumes:
          - ./:/usr/share/nginx/blog

  nginx:
      image: nginx:1.15
      container_name: blog_nginx
      working_dir: /usr/share/nginx/blog
      networks:
        - blog
      ports:
          - "8080:80"
      volumes:
          - ./:/usr/share/nginx/blog
          - ./docker/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf

  mysql:
      image: mysql:5.7
      container_name: blog_mysql
      networks:
        - blog
      environment:
        - MYSQL_DATABASE=blog
        - MYSQL_ROOT_PASSWORD=password
        - MYSQL_USER=blog
        - MYSQL_PASSWORD=password

networks:
  blog:
    driver: bridge

docker/nginx/conf.d/default.conf

server {
    listen  80;

    root /usr/share/nginx/blog/public;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass php_fpm:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

As you see, we’re using PHP-FPM 7.2, NGINX 1.15 and MySQL 5.7.

Let’s commit our brand new Docker set up:

git add -A
git commit -m "Docker setup"

The Docker containers are started with all the requirements above:

docker-compose up --build

At this point, don’t forget to update the relevant database environment variables in your .env file:

DB_CONNECTION=mysql
DB_HOST=172.26.0.2
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=blog
DB_PASSWORD=password

Please note, the value of DB_HOST is replaced from 127.0.0.1 to 172.26.0.2, which is the IP of the MySQL container.

The IPAddress is obtained this way:

docker inspect blog_mysql

The www-data group needs write permissions to the storage folder:

sudo chmod 775 -R storage
sudo chown -R $USER:www-data storage

The same thing goes for the bootstrap/cache folder:

sudo chmod 775 -R bootstrap/cache
sudo chown -R $USER:www-data bootstrap/cache

Don’t forget to create your Laravel application key:

docker exec -it --user 1000:1000 blog_php_fpm php artisan key:generate

Finally, the default Laravel welcome page is displayed when running http://blog.local:8080/

Figure 1. Laravel welcome page

Enjoy!

You may also be interested in…