Laravel-Docker during development
Ayman Elbery
Software Engineer @ SAMI Advanced Electronics | Bachelor of Computer Sciences
Introduction
In this article i'm going to show you how to use docker-compose to build multiple services to setup a Laravel PHP project on your local machine.
And since we use docker so you don't need to install any tools on your machine except for docker to create liable application.
The Target setup
We need a server that handle incoming requests which then triggers the PHP interpreter to run our PHP code for these incoming requests, and setting all of that up on your local machine combined with MYSQL on MongoDB databases, that be quite annoying.
Now here's your target setup, which you wanna achieve in this article therefore. And this will be a setup which allows you to build a Laravel applications without installing anything on your host machine, except for Docker.
1- We have a some folder on your host machine that contain the source code of this Laravel application.
2- This source code folder will then exposed to one container The PHP interpreter which has PHP insalled inside of it.
3- Beside this PHP interpreter which you need to run your code, you also need that extra server and that's when you'll have a second container which has Nginx in it.
4- Now for storing data, you're going to add a MySQL database which of course your PHP interpreter in the end needs to be able to communicate with.
5- Besides these three application containers my setup also needs a couple of utility containers because it turns out that in Laravel application, there are three kind of tools, utilities, which you need composer, artisan, and npm.
1. Adding a Nginx Container
So let's get started writting some code here.
I'm going to start by adding docker-compose.yaml file then adding my first service configurations to be like that:
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?mysql
As you can see above, I have built my first service Nginx web server from a dockerfile which is like that:
FROM?nginx:stable-alpine
WORKDIR?/etc/nginx/conf.d
COPY?nginx/nginx.conf?.
RUN?mv?nginx.conf?default.conf
WORKDIR?/var/www/html
COPY?src?.
And also as you see above, I have copied Nginx conf file that you could get it from officail Nginx docker-hub image from here, then you are ready for the next service.
2. Adding a PHP Container
So let's now work on the PHP container
The PHP service will be relatively straight forward, i actually also use a custom dockerfile though, because there is no finished image which have everything i need.
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?
- mysql
php:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:
-?./src:/var/www/html:delegated
As you can see above, I have built my second service PHP interpreter from a dockerfile which is like that:
FROM?php:7.4-fpm
WORKDIR?/var/www/html
COPY?src?.
RUN?docker-php-ext-install?pdo?pdo_mysql
RUN?chown?-R?www-data:www-data?/var/www/html
Note: don't forget the fifth instruction layer that is a command to run in your php container in order to change user and group whos owner the source code directory to www-data and this is an important step in Laravel to prevent permession denied issue.
You could get the official PHP docker-hub image from here, then you are ready for the next service.
3. Adding a MySQL Container
It shouldn't come as a surprise that we also have an official docker-hup image for MySQL which you can use like PHP and Nginx.
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?
- mysql
php:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html:delegated
mysql:
image:?mysql:5.7
env_file:
- ./env/mysql.env
As you can see above, I have built my third service MySQL from the official docker-hub image and pass env_file to it.
The mysql service env_file will be like this below:
MYSQL_DATABASE=homestead
MYSQL_USER=homestead
MYSQL_PASSWORD=secret
MYSQL_ROOT_PASSWORD=secret
Note: you have to remember?these values in mysql env_file, because you'll use it in the Laravel .env file
Now you have a three application containers which you'll up and down, but you still have no any source code, so let's move on to the next step or next first utility service.
4. Adding a Composer Utility Container
Let's now ensure that i'm going to setup this container, which will now be a utility container, which will then not only be used inernally by Laravel, but which most importantly can be used by me to also setup a Laravel application in the fisrt place.
领英推荐
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?
- mysql
php:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html:delegated
mysql:
image:?mysql:5.7
env_file:
- ./env/mysql.env
composer:
build:
context:?./dockerfiles
dockerfile:?composer.dockerfile
volumes:
-?./src:/var/www/html
As you can see above, I have built my fourth service Composer from a dockerfile which is like that:
FROM?composer:latest
WORKDIR?/var/www/html
ENTRYPOINT?[?"composer",?"--ignore-platform-reqs"?]
Note: i add "--ignore-platform-reqs" as an option for composer entrypoint command in order to ignore platform requirements warrnings.
Now you can use these four services to compose-up your Laravel application and your source code, but let me finish creating all services and then list all commands to up all services in the best way, so let's move on to the next utility service.
5. Adding a Artisan Utility Container
Let's continue with the artisan container, which we need to run certian level commands in Laravel project for example, to populate the database with some initial data.
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?
- mysql
php:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html:delegated
mysql:
image:?mysql:5.7
env_file:
- ./env/mysql.env
composer:
build:
context:?./dockerfiles
dockerfile:?composer.dockerfile
volumes:
-
-?./src:/var/www/html
artisan:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html
entrypoint:?["php",?"/var/www/html/artisan"]
As you can see above, I have built my fifth utility service Artisan from the same php dockerfile which used in building PHP service, and overwrite it by adding entrypoint instruction in my docker-compose.yaml file to run artisan file that will be exist in your source code.
Last service regarding to my target setup will be NPM, which used in laravel for frontend and UI staff. Let's se the updated yaml file.
6. Adding a NPM Utility Container
Npm is quite simple, here i'll use use the node image.
version: "3.8"
services:
server:
build:
context:?.
dockerfile:?dockerfiles/nginx.dockerfile
ports:
-?"8000:80"
volumes:?
-?./src:/var/www/html
-?./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
-?php
-?
- mysql
php:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html:delegated
mysql:
image:?mysql
env_file:
- ./env/mysql.env
composer:
build:
context:?./dockerfiles
dockerfile:?composer.dockerfile
volumes:
-
-?./src:/var/www/html
artisan:
build:
context:?.
dockerfile:?dockerfiles/php.dockerfile
volumes:?
-?./src:/var/www/html
entrypoint:?["php",?"/var/www/html/artisan"]
npm:
image:?node
working_dir:?/var/www/html
entrypoint:?["npm"]
volumes:
-?./src:/var/www/html?
Now i have finished the instructions setup, then let list all commands tou have to run in the same order to up your Laravel project.
1. Generate the source code using composer utility service:
# docker-compose run --rm -d composer create-project laravel/laravel .
2. Edit your .env file in laravel source code (section of connecting to DB):
DB_CONNECTION=mysql
DB_HOST=mysql // name of mysql serviece ...
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
3. Run database migration using artisan utility service:
docker-compose run --rm -d artisan migrate
4. Generate node_modules and UI staff using npm utility service:
docker-compose run --rm -d npm install
5. Start your compose by up server which in turn will up other services because it depends on them:
docker-compose up --build -d server
Note: you should see result like that in your terminal (and docker desktop windows users):
Then if you go to in your browser and in your localhost on port 8000 you will see Laravel project successfully run
In the end, this is my first article. I hope it helps you. If there are any comments, do not hesitate to send them to me.
Thank you ..