1
Write a post

Creating Laravel PHP Application in Docker: Step-by-Step Guide

Published Jan 30, 2017Last updated Jan 31, 2017
Creating Laravel PHP Application in Docker: Step-by-Step Guide

A challenge that every developer and development team faces is environment consistency.
At some point in your career you would most likely run into situations where code deployed to your production environment doesn’t quite work with your development environment.

Configuration and versions differences are usually the cause of these problems. Imagine developing a PHP application with PHP 7 on your local machine with all the required modules enabled and deploying it to a production environment only to discover the modules your application requires to run are absent. To solve this
problem, we started using VM(virtual machines) to maintain environment consistency; however, we soon discovered that VMs are not very efficient or portable. They are typically time consuming and require a lot of system resources to function properly.

This is where Docker comes in.

Docker containers wrap a piece of software in a complete filesystem that
contains everything needed to run: code, runtime, system tools, system libraries
— anything that can be installed on a server. This guarantees that the software
will always run the same, regardless of its environment.

With Docker, you can build and run lightweight containers for any services needed. Need to upgrade to a newer version of PHP? No problem, Docker allows you to destroy your entire environment, reconfigure it, and run it againquickly.

Laravel (one of the best things that happened to PHP) integrates a lot of technologies (MySQL, Redis, MongoDB, Memcached, etc) in order to provide a wide array of functionalities. It can be quite a challenge to get a good configuration initially — the goal of this post is to provide some understanding of building Laravel apps with Docker.

tldr; You can check out the code for this at
https://github.com/mrfoh/docker-laravel

Contents

  • Laravel setup
  • Docker setup
  • Local environment setup
  • Adding a database

Laravel setup

We’ll be working with Laravel 5.3 in this post and we’ll be installing it with
composer.
1*33Z09EmCQ_xD9kXvrDjZgw.png

The next step is to verify your installation

$ cd docker-laravel
$ php artisan serve

1*9IJla90ZoN7047Bb2k6w3g.png

Docker setup

Docker runs on Mac, Windows, and Linux. Select your platform to install Docker on your machine. Be sure to install Docker as well as
Docker Compose, which we will use in this post.

After installing it, you should be able to verify the installation with these commands:
1*98bau1ZgkjfDK5OZyCfEsQ.png
(I already have some containers running)

If you get an error running the docker ps command, you would need to open Docker and start it manually.

Local environment setup

The next step is to get the local environment setup right. If you've set up a PHP environment before, you are probably already familiar with running PHP alongside a web server like Nginx or Apache. With Docker, we can create containers to house
specific parts of the infrastructure of our local environment. We’ll have a container that runs nginx to handle web request, another container to handle application requests with PHP-FPM, and a few others to handle the application’s database and caching needs. Each container will have a responsibility and all containers
will be linked together to communicate.
1*TQZSYF7srKYr4bF1j50yvA.png
Overview of environment

Next up, we’ll use Docker Compose
to put all the pieces together in our environment. In the root of the project, create a file named docker-compose.yml.

1*9mhVxxG17WlxJ4vWnrt0vA.png
docker-composer.yml

In the docker-compose.yml file;

  • We have defined two services AKA containers; web and app
  • The web and app containers are set to use the project root as the context, from
    which the docker-compose tool builds out environment. The files also specify
    the names of
    Dockerfiles (app.docker,
    web.docker), which will instruct Docker on how to build our containers.
  • The next thing you’ll set is the volumes directive. This allows us to mount
    our project directory as volume on the container at the specified path, in this
    case /var/www.
  • The web container exposes port 8080 on our machine and maps it to port
    80 on the container, allowing us access to the app.
  • The links directive allows us to link one container to another, allowing
    us to reference the **app **container as a host from within the web
    container.

The docker documentation has more information about configuration
directives and is available for Docker Compose; you can check it out
here.

Let's create the Dockerfiles for our containers. Dockerfiles are essential files
containing instructions on how to build a container image. These instructions
are similar to the typical steps taken to provide a server for a task — web
server, database server, PHP app server, etc. Dockerfiles allow us to leverage
already created base images, which minimize configuration.

1*9AV6EAlOYN3yU-HUXuEFYg.png
app.docker

In line 1, we specify the base image for our app container to be PHP-FPM using
FROM, with this convention you can easily switch to a different versions of
the base image. Our base image is pulled from the Docker
Hub
, which houses a lot of other base images.

In line 2, we run some commands to make sure our container is up to date and fetch some dependencies for our application.

1*ArmQm7qY-1W8xyoXbaVmrA.png
web.docker

Like the app.docker file, we specify a base image and perform some
configuration. In line 3, we add an Nginx configuration file to the web container.
1*8_MYt7GTEf1vOtZlGuKA8w.png
vhost.conf

The vhost.conf file contains standard Nginx configuration that will handle http
requests and proxy traffic to our app container on port 9000. Remember from
earlier, we named our container app in the Docker Compose file and linked it to the web container; here, we can just reference that container by its name and Docker will route traffic to that app container.

Next up, run this command from the root of the project

$ docker-compose up -d

This command tells Docker to start the containers in the background. The first
time you run the command, it might take some time to download the two base
images, after that it will be much faster. You can now visit the app.

*Note: Docker may not be using localhost (like on Windows sometimes). Run and
get the IP address to use instead.
1*JPxxAwXPMX2KiNtI0cqWag.png
Now our laravel app, powered by docker containers, is up and running.

Adding a database

So we’ve got our Laravel app up and running, the next step is to add another container to handle the application’s database needs. First, let’s stop our containers.

$ docker-composer kill #stops all running containers

Next, we’ll update the docker-compose.yml file and add a MySQL base image for our
database container.
1*MG-3jHBuUZkveXDQDYDVvA.png

We made a few changes here:

  • Added link on the container to the container.
  • Added environment variables to the app container, which will allow us to configure our local machine to connect using the config values set in the laravel file. This allows us to run artisan locally without messing with the
    connection details that are used inside the container.
  • Created the container using the mysql base
    image
    and set environment values to configure some defaults for the image.
  • Expose port on our machine and forward it to the container. This allows us to run artisan locally.

Now, in our .env file for Laravel, we can configure the connection details.
1*U3IKcPUCNBVOLsNPETzeqA.png

Now you can start up your updated environment with

$ docker-compose up -d

You now have database container to store data. You can now create the laravel migrations table on your database and create laravel database migrations as usual.

You can check if the mysql container is running with

$ docker ps

In this post, we successfully dockerized our local laravel environment. Now we can easily
update the Docker Compose fill and add new containers for more services like Redis, MongoDb, etc.

This post was inspired by a blog
post written
by Kyle Ferguson; he gave me a head start on Docker.

Discover and read more posts from Patrick Foh Jr
get started
Enjoy this post?

Leave a like and comment for Patrick

5
7
7Replies
Janaka Pushpakumara
a month ago

Hi Patrick, thanks for this good tutorial.
I got an error after the create app & web containers.
I run “docker-compose up -d” command. app & web containers up successfully.
When I check in Browser using “localhost:8080” URL.
I got " 500(Internal Server Error) "
I have to know idea how to fix this.
Please, can you help to solve this?
Thanks.

Janaka Pushpakumara
a month ago

I solve it out after set the permission on my Laravel application
sudo chmod -R 777 storage && sudo chmod -R 777 bootstrap/cache

Patrick Foh Jr
a month ago

Glad you found a solution

Alugbin Abiodun
2 months ago

Hey patrick, thanks for this tutorial. please i will like to ask how do i convert these to images and upload to production servers, or do i need to upload my codebase as well?
Also, instead of nginx, can u show us how to use apache instead? or is nginx the standard?

Again, Thanks

Patrick Foh Jr
a month ago

Hi Alugbin, sorry the about the late response. You can provision a virtual machine for production, and install docker like you did on your local machine or use something like AWS container service or Docker swarm. Check this out https://docs.docker.com/compose/production/
You should have your codebase on a version control system like git.
Nginx is not the standard, but these days nginx is more preferred.
I’ll find sometime and write a tutorial using apache.

Shivam Gupta
2 months ago

i’ve no words except else of saying it’s awesome

Patrick Foh Jr
a month ago

Thank you, glad it helped you.

Show more replies

Get curated posts in your inbox

Learn programming by reading more posts like this