Laravel + Docker

In the article we will talk about Docker + Laravel for a quick setup of a scalable dev environment for web development. The article is a tutorial because you will find instructions how to deploy the environment. Here you find less technical details but more living examples.

Alternative

Laravel provides own solution for organizing a local environment called Homestead. This is a set of configurations and scripts for Vagrant, with the help of the necessary software deploy in virtual machine VirtualBox. But the description of Homestead is beyond the scope of this article.

Laradock Project

At the beginning Laradock focused exclusively on launching Laravel on Docker, which is reflected in its name. But the popularity of Laradock is still growing in the php community, and now it is able to support other php projects: Symfony, CodeIgniter, Drupal. The project is really popular and it is actively supported and developed:

Laradock is a set of pre-configured, independent Docker images, which you can involve basing on the requirements of your project. It is well documented and extremely easy to use. To run the components, you simply need to write them:

docker-compose up apache2 php-fpm mysql phpmyadmin

or

docker-compose up nginx php-fpm mariadb adminer

Note: there is no need to explicitly specify php-fpm, because when you start the web server of the php-fpm containers, it starts automatically.

There are more than 48 containers in the repository, including:

  • Databases: MySQL, MariaDB, Percona, MongoDB, MSSQL, PostgreSQL
  • Database Management: PhpMyAdmin, Adminer, PgAdmin
  • Web servers: nginx, Apache2, Caddy
  • PHP compilers: PHP FPM, HHVM
  • Miscellaneous: Selenium, Jenkins, ElasticSearch, Kibana, Gitlab, Mailhog, MailDev, Laravel Echo, Phalcon
  • Tools: PHP CLI, Composer, Git, Linuxbrew, Node, V8JS, Gulp, SQLite, xDebug, Envoy, Deployer, Vim, Yarn, Drush

Git repository architecture: main project and Laradock

Laradock can be used in two versions:

  • Separate Laradock for each project
  • One Laradock in many projects

In the first case the directory structure will look like this: 

+ project-a
  + laradock-a
+ project-b
  + laradock-b

In the second like this:

+ laradock
+ project-a
+ project-b

I always use the first option: one project – one Laradock. This approach provides the flexibility and independence of one project from another.

And here we have two questions: to create one common repository or two separate ones? In other words, do I need to add Laradock files to the main repository with the project?

Yes, you need to add them but in the form of a sub-module to the main repository. Docker-environment is a supporting part of the project and it is not always required. For example, on staging and production servers it is not necessary. If you deploying through git, the environment files will not get there.

Single site launch

As I wrote earlier, we use Laradoc to create the environment. The startup process consists of setting up the environment and laravel-application. Project Settings:

Laradoc has an environment configuration example file. We create a copy of it for our project.

cp env-example .env

Starting and stopping environment applications are made with Docker-compose commands.

docker-compose up

and

docker-compose stop

If necessary you can load services. For example, I will load three additional services:

docker-compose up -d nginx percona adminer

You can remove this command in a separate shell-script so you don’t do it manually each time.

Starting the script can be called “start.sh”, or at your convenience:

#!/usr/bin/env bash

docker-compose up -d nginx percona adminer;

Stopping the script can be called “stop.sh”, or “down.sh”:

#!/usr/bin/env bash

docker-compose stop;

Project Initialization

The transition to the container environment is performed by the command

docker-compose exec --user=laradock workspace bash

Deployment errors

During installation of Laradoc in Linux there may be problems with files permissions. In this case the files have wrong owner or insufficient access rights.

Symptoms: when you try to start the environment with the “Docker-compose up” command or switch to the container with the “Docker-compose exec …” command, you may get these errors:

/var/www/vendor does not exist and could not be created

The stream or file "/var/www/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied

The reason for the error is the sample configuration of the Docker environment, the User ID and Groups ID are strictly indicated, the default value is 1000 and 1000 respectively.

If in your Unix-system these IDs are already occupied by other entities, then you need to manually edit the configuration.

The procedure of eliminating errors

Check the user and group directories:

ls -la /var/www

File and directory owners (User and Groups) must be laradock : laradock.

If instead of laradock: laradock, the owner and group are designated by numbers (1001: 1001, 1001: 13002 and similar combinations), then you need to make changes to the configuration files.

If the ID of your User and Groups (/etc/passwd, /etc/group) do not coincide with the specified ones for correct work you need to make changes to the following files:

/laradock/php-fpm/Dockerfile*, in line

«RUN usermod -u 1000 www-data»

replace 1000 with user ID

/laradock/.env in lines

WORKSPACE_PUID=1000
WORKSPACE_PGID=1000

WORKSPACE_PUID — specify your user ID,

WORKSPACE_PGID — Users groups id

/laradock/workspace/Dockerfile*, in lines

ARG PUID=10315
ARG PGID=10004

PUID — user ID, PGID — groups ID

After making changes, you should rebuild the workspace, php-fpm and then run the container:

docker-compose build workspace php-fpm

If you get such problem, you need to check the access rights to the Laravel framework directories. Set permissions for directories that require write permissions:

sudo chgrp -R www-data storage bootstrap/cache; sudo chmod -R ug+rwx storage bootstrap/cache

Running multiple sites

So, all projects work according to the “One Laradock – One Project” scheme. But one project is not necessarily one site. Sometimes you need to run several sites at the same time, because they will interact with each other.

In this case, don’t start two Laradock at the same time, because each of them has a web server which is listened to on port 80 — you will get a conflict. But we have access to the nginx configs – let’s go through them.

But at first, a note about architecture and git repositories. In case of several sites, we use the directory structure from the second option:

+ project
  + laradock
  + website-a
  + website-b

The git repository with Laradock is no longer a submodule of another repository, it becomes completely independent.

The web server configuration will be shown on the example of nginx. In the Laradock directory, you need to go to nginx/sites. Here we see the default.conf and several * .conf.example files. Based on default.conf or sample files we create configurations for sites.

Pay attention to the document root. By default, the root directive looks like this:

root /var/www/public;

and it should look like this:

root /var/www/website-a/public;

root /var/www/website-b/public;

Important! Look at the contents of .gitignore in this directory. All * .conf files except default.conf are ignored. You need to add created files to the exceptions, do not ignore them.

Configure the crontab so that the laravel scheduler can work correctly. To do this, in the workspace /crontab/laradock file, add the following paths:

* * * * * laradock /usr/bin/php /var/www/website-a/artisan schedule:run >> /dev/null 2>&1 

* * * * * laradock /usr/bin/php /var/www/website-b/artisan schedule:run >> /dev/null 2>&1

For successful communication sites inside containers add aliases. In the file docker-compose.yml find the section

### NGINX Server ###

and add an alias for each domain:

This is all you need to do to start a project with multiple domains. But the question of organizing https for several domains still remains. It can be implemented on the analogy with the organization of ssl for one domain.

Additional features

In the Docker environment, it is possible to configure the applications what we need. The basic configuration of Laradoc already includes application packages:

  • Web servers : Apache2, Caddy
  • Web Application Caching : Nginx, Varnish
  • Databases and Caching Services : Mongo, Redis, Mssql, Mysql, Percona, Mariadb, Elasticsearch, Memcached, Redis, RethinkDb, Aerospike
  • Web interfaces to databases : Adminer, PhpMyAdmin
  • Load balancing : Haproxy
  • Programming, programming shells and frameworks : Php, Python, Symfony, Laravel, Node
  • Package manager : Yarn, Composer
  • Testing tool : Jenkins
  • Application Infrastructure Configuration Tool : Terraform

Let’s briefly consider mentioned applications.

RabbitMQ

It is a mechanism of messaging between applications. The developer of this package defines its designation as: “queue manager”, “message broker” or “message queue”.

A message can contain any data set.

In the scenario of working with the queue manager, the message from one application – the sender – is saved until another application (receiver) connects and takes the message from the queue.

Redis

It creates data cache in RAM. It can also be used as a data storage along with the database server, or replacing it.

Redis supports strings, lists, sets, ordered sets, and hash tables.

The main disadvantage of Redis is data loss in case of clearing the RAM, when the OS is restarted, or when the hardware is turned off. Developers have provided a similar scenario: in AOF (Append Only File) mode, data is added to the files on hard disk every second.

The main advantage of Redisis the fastest access to data with the speed of accessing RAM.

Conclusion

Having chosen the Laravel + Docker solution for web development, we won the most valuable thing – time.

Following the development scenario in WAMP or LAMP we will waste time useless.

Using Laradoc allows us, once having created the entire project environment, to deploy it in a new workplace in the shortest time possible. And get started right away.

In conclusion, we note the advantages of using Laradoc:

  • unified infrastructure at every workplace: a web server, sql server, a set of frameworks and libraries;
  • efficient use of working time;
  • quick entry of a new developer into the project.

Write in the comments how your team works with the environment, what tools and approaches you use.