Laravel + Docker: Our Successful Experience
What is this article about
The article will talk about our experience of using Docker to quickly configure a scalable dev environment for web development. I will briefly talk about the tasks that we faced and the tools that were chosen to solve these problems. The article is marked with the tutorial icon, because you will find instructions on how to deploy the environment in it. Compared to similar articles (links at the end of the article), there will be less technical details and more living examples.
What challenges we faced
It so happens that a new developer connects to an existing team. So that he could start to perform tasks (in other words, write code and check his work), it’s not enough to get the source code. You need an environment that includes a web server, a php compiler and a database. This is the minimum set. Depending on the project, the environment may include:
- Queue server;
- Full-text search engine;
- Caching solution;
- Useful developer tools;
All this should be installed locally by the developer, and be the same version as the rest of the team members. And here there are difficulties:
- After installation, you need to configure;
- The software is already installed, but it is a different version;
- It is long;
And the fact that developers work on different platforms (windows, linux, os x) complicates things even more.
Docker was chosen to solve the problem. Perhaps the main reason is that it fit easily into the existing infrastructure. It works great on Linux, and most of our developers are on this OS.
Laravel provides its own solution for organizing a local environment called Homestead. This is a set of configs and scripts for Vagrant, with the help of which the necessary software is deployed in a VirtualBox virtual machine. But the description of Homestead is beyond the scope of this article.
At the beginning, this project was aimed exclusively at launching Laravel on Docker, which is reflected in its name. But as popularity grew in the php community, Laradock began to support other php projects: Symfony, CodeIgniter, WordPress, Drupal. The project is really popular, actively supported and developed:
Laradock is a set of pre-configured, independent Docker images that can be connected based on the requirements of your project. Well documented and extremely easy to use. To run the components, simply list them:
docker-compose up apache2 php-fpm mysql phpmyadmin
docker-compose up nginx php-fpm mariadb adminer
Note : there is no need to explicitly specify php-fpm, since when you start the web server of the php-fpm containers, the container 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
Requirements and initial conditions
You will need:
Git repository architecture: main project and Laradock
Laradock can be used in two versions:
- Separate laradock for each project
- One laradock on many projects
In the first case, the directory structure will look like this:
In the second way:
We always use the first option: one project - one laradock. This approach provides the flexibility and independence of one project from another.
The second important question: 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? The answer is necessary, 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. When deploying through git, the environment files will not get there.
Environment Directory Name
By default, the names of the containers use the name of the current directory as a suffix: laradock_nginx_1, laradock_mysql_1, etc. To avoid confusing data inside volumes, you need unique directory names for your environments. This is easy to achieve if you stick to the chosen scheme: add the name of the project to the name of the directory with the environment, for example:
that is, the prefix “laradock” and the name of the project directory through a hyphen.
Single site launch
How do we start the site launch?
As we mentioned in the third chapter, we use Laradoc to create the environment.
The startup process consists of stages of setting up the environment and laravel-application.
Laradoc has an environment configuration example file. We create a copy of it for our project.
cp env-example .env
The .env options are pretty obvious. In the parameters we set the access to databases, e-mail parameters, access to third-party services, if we use in our project.
Starting and stopping environment applications are done with docker-compose commands.
If necessary, in the start-up team, you can load the necessary 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 in order not to enter it manually each time.
The startup script can be called “start.sh”, or at your convenience:
docker-compose up -d nginx percona adminer;
The service stop script can be called “stop.sh”, or “down.sh”:
The transition to the container environment is performed by the command
docker-compose exec --user=laradock workspace bash
When installing Laradoc in a linux environment, there may be a problem with file permissions.
In this case, the files may be the 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, as in the example above, errors similar to
/ var / www / vendor created
The stream or file "/var/www/storage/logs/laravel.log" couldn’t be streaming: Permission deniedThe reason for the error is that in the sample configuration of the docker environment, the User ID and User Group are strictly indicated, the default is 1000 and 1000, respectively.
If in our unix-system these IDs are already occupied by other entities, then you need to manually edit the configuration.
The procedure for eliminating errors
We check the user and group directories:
ls -la /var/www
File and directory owners (User and User Group) 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 your User ID and User Group IDs (/ etc / passwd, / etc / group) do not match with the specified ones, then in order to work correctly, you need to make changes to the following files:
/ laradock / php-fpm / Dockerfile *, in the line
" RUN usermod -u 1000 www-data "
replace 1000 with user ID
/laradock/.env in rows
WORKSPACE_PUID = 1000
WORKSPACE_PGID = 1000
WORKSPACE_PUID - specify your user ID, WORKSPACE_PGID - user group ID
/ laradock / workspace / Dockerfile *, in the lines
ARG PUID = 10315
ARG PGID = 10004
PUID - user ID, PGID - user group ID
After making the changes, rebuild workspace and php-fpm and then launch the container:
docker-compose build workspace php-fpm
If you encounter such a 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
SSL certificates and https
Most likely your site in production will work under a secure protocol. It makes sense and local development to lead to https. This is not very difficult to do, you need an SSL certificate and small settings. Details are described in this article How to issue a self-signed SSL certificate .
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, two laradock at the same time do not start, because each of them has a web server running that listens on port 80 — we get a conflict. But we have access to the nginx configs, let's configure it.
But first, a note about architecture and git repositories. In the case of several sites, we use the directory structure from the second option:
Git-repository with laradock is no longer a submodule of another repository, but becomes completely independent.
The web server configuration will be shown on the example of nginx. In the laradock directory, go to nginx / sites. 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:
and should like this:
root /var/www/site-1/public; root /var/www/site-2/public;
Important!Configure the crontab so that the laravel scheduler can work correctly. To do this, in the workspace / crontab / laradock file, add the following paths:
Look at the contents of .gitignore in this directory. All * .conf files except default.conf are ignored. You need to add the created files to the exceptions, that is, do not ignore them.
* * * * * laradock /usr/bin/php /var/www/site-1/artisan schedule:run >> /dev/null 2>&1 * * * * * laradock /usr/bin/php /var/www/site-2/artisan schedule:run >> /dev/null 2>&1
For successful communication sites inside containers, add aliases. In the file docker-compose.yml we find the section
### NGINX Server ###
and add an alias for each domain:
This is all you need to do to run a project with multiple domains. Outside the article, there remains the question of organizing https for several domains. All by analogy with the organization of ssl for one domain, which is described in the section above. Add a comment if there are difficulties, I will answer it or describe the features in a separate article.
It is possible to configure the applications we need in the Docker environment space. The basic configuration of Laradoc already includes application packages:
|Web application server||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|
|Программирование, программные оболочки и фреймворки||Php, Python, Symfony, Laravel, Node|
|Утилиты||Php, Python, Symfony, Laravel, Node|
|Менеджер пакетов||Yarn, Composer|
|Средство конфигурирования инфраструктурой приложения||Terraform|
Briefly consider the most mentioned applications.
A messaging engine between applications. The developer of this package defines its designation as: “queue manager”, “message broker” (message broker), or “message queue” (message-queuing).
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.
Create an in-memory data cache. It can also be used as a data warehouse along with the database server, or by replacing it.
Redis supports strings, lists, sets, ordered sets, and hash tables.
The main disadvantage of radishes is data loss in case of clearing the RAM, when the OS is restarted, or when the hardware is turned off. Radish developers have provided a similar scenario: in the AOF (Append Only File) mode, data is added to the disk file every second.
The main advantage of radishes is the fastest access to data with the speed of accessing RAM.
Links to materials
"How to issue a self-signed SSL certificate and make your browser trust it"
Docker + Laravel =
Having chosen the Laravel + Docker solution for web development, we won the most valuable prize: time.
Following the development scenario in WAMP or LAMP, we had to waste time
uselessly and nowhere.
Both WAMP and LAMP require a certain level of qualification from a php developer in areas that are not directly related to web development: configuring a web server, setting php parameters, etc.
Using Laradoc allows us, once having created the entire project environment, minimum time to deploy it in a new workplace. And get started right away.
In conclusion, we note the advantages of using Laradoc:
- unified, at every workplace, infrastructure: a web server, sql server, a set of frameworks and libraries;
- rational 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.