Laravel 5.7 — Docker development environment (Apache, PHP 7.1, Redis, ElasticSearch)

Vladimir Sukhov
5 min readJan 23, 2019

--

This article is dedicated to a simple, yet powerful solution for the integrated development environment for those who prefer docker to virtual machines.

Firstly, you need to install docker on your machine as well as a docker-compose package. There is a very descent manual on that matter on the docker web portal.

You simply need to choose your operating system and follow the guide on how to setup the environment. At this stage, all information will be delivered using macOS or Linux environment, but there should not be much difference in Windows after all, except for the scripts.

Please bear in mind, that Docker won’t work on Windows Home edition (as per the time when this article has been written).

Install composer on your system (Follow instructions for installation):

The Goal here is to create a space that you could simply deploy to your personal machine and then, deploy it to a real server environment.

  1. Create a folder somewhere on your drive

cd ~ && mkdir Projects && cd ~/Projects;

2. Create a folder where your Laravel source code would be set in place. This manual deliberately omits mkdir -p for the sake of simplicity.

mkdir myapp && cd myapp && mkdir src && cd src && composer create-project --prefer-dist laravel/laravel myapp

You may obviously choose different name, rather than myapp, but as it will be used further in this tutorial, please remember your choice.

3. Inside your src folder, create a Dockerfile with the following contents:

#Base image for the containerFROM php:7.2-apache#Install GIT, GnuPG, NodeJS and NPMRUN apt-get update && apt-get install -y git gnupg && \
curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
apt-get install -y nodejs

#Add Laravel necessary php extensions
RUN apt-get install -y \
unzip \
vim \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-install -j$(nproc) zip mysqli pdo_mysql \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/
--with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd
# Create working directoryRUN mkdir -p /var/www/myapp
ENV APACHE_DOCUMENT_ROOT /var/www/myapp/public
ENV APP_NAME "myapp"
# Install composer from image. You may change it to the latestCOPY --from=composer:1.5 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/myapp
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf# Make laravel feel comfortable with mod-rewriteRUN a2enmod rewrite && service apache2 restart
EXPOSE 80

This docker file is responsible for your main web app container, which then will be built together with other services in docker compose.

4. In the same src folder, create script file setup.sh with the following contents. This is a basic setup for the Laravel to work properly:

#!/bin/bash# Change access rights for the Laravel folders
# in order to make Laravel able to access
# cache and logs folder.
chgrp -R www-data storage bootstrap/cache && \
chown -R www-data storage bootstrap/cache && \
chmod -R ug+rwx storage bootstrap/cache && \
# Create log file for Laravel and give it write access
# www-data is a standard apache user that must have an
# access to the folder structure
touch storage/logs/laravel.log && chmod 775 storage/logs/laravel.log && chown www-data storage/logs/laravel.logcomposer install && php artisan key:generate && npm install
php artisan migrate:fresh --seed && echo "Done..."

5. Make setup.sh executable by calling chmod +x setup.sh

6. Navigate up to myapp directory by executing:cd ..

7. Create docker-compose.yml file for MySQL, ElasticSearch and Redis containers. Insert the following contents:

version: "3"
services:
redis:
image: redis:5.0.0-alpine
restart: always
container_name: myapp-redis
ports:
- 6379:6379
networks:
myapp_net:
ipv4_address: 172.16.238.13
es:
image: docker.elastic.co/elasticsearch/elasticsearch:6.4.2
restart: always
container_name: myapp-es
environment:
- discovery.type=single-node
ports:
- 9200:9200
networks:
myapp_net:
ipv4_address: 172.16.238.10
db:
image: mysql:5.7.24
restart: always
container_name: myapp-db
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: mydb
ports:
- "3306:3306"
networks:
myapp_net:
ipv4_address: 172.16.238.11
app:
build: src/
restart: always
container_name: myapp-web
depends_on:
- db
- redis
- es
ports:
- "8888:80"
volumes:
- ./src/myapp:/var/www/myapp
networks:
myapp_net:
ipv4_address: 172.16.238.12
volumes:
web-app:
driver: local
networks:
myapp_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.16.238.0/24

This docker-compose.yml file plays a role of an initial setup and network connection provider for the final ecosystem, as well as it exposes docker to a working folder of your web application. Because Apache web server has a dynamic load of content, every change you make in your myapp (Laravel) folder, will be reflected on the container.

We created a designated network 172.16.238.0/24 where all your containers will interoperate together.

You may change ports of containers if you like to, but do not forget about .env file in Laravel, which should include proper connection strings.

For example:

DB_CONNECTION=mysql
DB_HOST=172.16.238.11
DB_PORT=3306
DB_DATABASE=mydb
DB_USERNAME=root
DB_PASSWORD=secret
REDIS_HOST=172.16.238.13
REDIS_PASSWORD=null
REDIS_PORT=6379
ELASTICSEARCH_INDEX=scout
ELASTICSEARCH_HOST=http://172.16.238.10:9200

As you can see, the final project ip addresses must conform to what you have stated in the docker-compose.yml file.

Note: you need to install Laravel Scout and change standard Algolia Search engine to ElasticSearch (will be a separate tutorial)

8. In the myapp folder — create helper script install.sh with the following contents:

cp ./src/setup.sh ./src/myapp/docker-compose up -d && echo "Please wait while service is up..." && sleep 5 && docker exec myapp-web /var/www/myapp/setup.sh && echo "All done"

The above script:

a) Runs docker-compose to build the final ecosystem

b) Iinvokes previously created setup.sh script that will generate all necessary keys and will change access rights, so that Laravel works properly.

9. Make install.sh executable by chmod +x install.sh

10. Last step is to run install.sh script that will make all the build for you. Once in terminal you see All done , you may access http://localhost:8888 where your application spins.

Feel free to make any changes to the myapp folder. All these changes will be reflected in the container instantly.

In the next tutorial, I will explain, how to deploy Docker solution in the Production environment, how to use iptablesand ufw with docker, as without a proper setup, docker bypasses UFW. As well as ElasticSearch setup.

--

--

Vladimir Sukhov

Software Engineer. Specialised on a distributed systems architecture. Systems development. Backend development.