https://github.com/allysonsilva/laravel-docker
This repository is no longer maintained/updated, see new repositoryUse this repository to get started with developing your Laravel application in a Docker container.
This is a personal collection of Docker tools and images(Nginx, PHP-FPM, MySQL, Redis, MongoDB, Queue, Scheduler, and RabbitMQ) for applications in Laravel.
Overview
Project Structure/Tree
tree -a -I '.git|.DS_Store' --dirsfirst
.
├── mongodb
│ ├── ssl
│ │ ├── .gitignore
│ │ ├── ca.pem
│ │ ├── client.pem
│ │ └── server.pem
│ └── mongod.conf
├── mysql
│ ├── ssl
│ │ ├── .gitignore
│ │ ├── ca.pem
│ │ ├── client-cert.pem
│ │ ├── client-key.pem
│ │ ├── server-cert.pem
│ │ └── server-key.pem
│ ├── my.cnf
│ └── mysql.env
├── nginx
│ ├── certs
│ │ ├── .gitignore
│ │ ├── fullchain.pem
│ │ └── privkey.pem
│ ├── configs
│ │ ├── addon.d
│ │ │ └── 10-realip.conf
│ │ ├── nginx.d
│ │ │ ├── 10-headers.conf
│ │ │ ├── 20-gzip-compression.conf
│ │ │ ├── 20-open-file-descriptors.conf
│ │ │ ├── 30-buffers.conf
│ │ │ ├── 40-logs.conf
│ │ │ ├── 50-timeouts.conf
│ │ │ ├── 60-misc.conf
│ │ │ └── 70-proxy.conf
│ │ ├── servers
│ │ │ └── app.conf
│ │ ├── snippets
│ │ │ ├── cache-static.conf
│ │ │ ├── deny.conf
│ │ │ ├── php-fpm.conf
│ │ │ ├── ssl-certificates.conf
│ │ │ └── ssl.conf
│ │ ├── fastcgi.conf
│ │ ├── mime.types
│ │ └── nginx.conf
│ ├── Dockerfile
│ └── docker-entrypoint.sh
├── php
│ ├── configs
│ │ ├── conf.d
│ │ │ ├── opcache.ini
│ │ │ └── xdebug.ini
│ │ ├── fpm
│ │ │ ├── php-fpm.conf
│ │ │ └── www.conf
│ │ ├── php-local.ini
│ │ └── php-production.ini
│ ├── queue
│ │ ├── templates
│ │ │ ├── laravel-horizon.conf.tpl
│ │ │ └── laravel-worker.conf.tpl
│ │ └── supervisord.conf
│ ├── scheduler
│ │ └── artisan-schedule-run
│ ├── vscode
│ │ └── launch.json
│ ├── Dockerfile
│ ├── app.env.example
│ ├── docker-entrypoint.sh
│ ├── queue.env.example
│ └── scheduler.env.example
├── redis
│ └── redis.conf
├── .dockerignore
├── .editorconfig
├── .env.example
├── .gitignore
├── Makefile
├── README.md
├── docker-compose.override.yml
└── docker-compose.yml
What's Inside/Softwares Included:
PHP
7.3.x- PHP-FPM
Nginx
1.16.xMySQL
5.7MongoDB
4.2-
Redis
5.x -
RabbitMQ
3.8
Getting Started
Organization
docker
folder must match current repository folder.- The folder name is configurable via the
LOCAL_DOCKER_PATH
variable of the.env
environment file.
- The folder name is configurable via the
src
folder should contain Laravel application.- The folder name is configurable via the
LOCAL_APP_PATH
variable of the.env
environment file.
- The folder name is configurable via the
.
├── docker
└── src
Clone the project
$ git clone https://github.com/AllysonSilva/laravel-docker-lite docker && cd docker
- Copy the
.env.example
file in the root of the project to.env
and customize. - Uncomment the
pwd
variable and fill it with resultecho $PWD
. - The
LOCAL_DOCKER_PATH
variable in the.env
file must be the folder name of the docker project. - The
LOCAL_APP_PATH
variable that is in the.env
file must be the folder name of the Laravel application project.
Customize Running in Development
docker-compose -f docker-compose.yml -f docker-compose.override.yml up app webserver database redis queue scheduler
Build Images
To build the images it is necessary to configure the
.env
file with the information that will be used when thedocker-compose up
command is executed.
make config-docker-env \
local_docker_path=./docker \
local_app_path=./src \
app_domain=domain.xyz \
remote_src=/var/www/domain.xyz \
app_image_name=app:1.0 \
webserver_image_name=webserver:1.0
-
app_domain
must match the domain that will be used in the application. Used exclusively in the webserver container inserver_name
Nginx settings. -
remote_src
must match the same path in PHP (app
) and Nginx (webserver
) containers. Because thewebserver
container sends theindex.php
file path to PHP-FPM, so if the paths are different in both containers, a project execution error will occur.
Laravel/APP PHP-FPM
- The construction/configuration of this image is used for applications in Laravel.
- Used multi-stage builds in your
Dockerfile
.
- In the first stage use the image of Composer to manage the system dependencies (To speed up the download process hirak/prestissimo is used).
- In the second stage use the Node.js image to build the dependencies of the Front-end using the yarn manager.
- In the third and final stage, the results of the previous stages are used to copy the necessary files to the project image.
How to use
$APP_ENV
: Set the environment where the Laravel application will be configured. This variable can be defined at the moment of image build through arguments(--build-arg APP_ENV=production||local
), or if the image is already created, then it can be replaced by the parameter--env "APP_ENV=production||local"
when running the container.WORKDIR
corresponds to the variable$REMOTE_SRC
.php.ini
: Configured at the time of image build and is set according to the value passed to$APP_ENV
. If the value of$APP_ENV
islocal
thenphp.ini
will match the filesphp-local.ini
, if the value of$APP_ENV
isproduction
then the contents ofphp.ini
will correspond to the filephp-production.ini
.- Can be overridden by volume pointing to the
php.ini
file path:/usr/local/etc/php/php.ini
.
- Can be overridden by volume pointing to the
php-fpm.conf
: GLOBAL PHP-FPM configuration found/usr/local/etc/php-fpm.conf
.www.conf
: Specific configuration for pool[www]
found/usr/local/etc/php-fpm.d/www.conf
.
Configure/Build
Use the following command to build the image:
make build-app \
app_env=production||local \
remote_src=/var/www/domain.xyz \
local_app_path=./src \
local_docker_path=./docker \
app_image_name=app:1.0
If you want to customize the image construction according to your arguments, use the docker build
command directly:
docker build -t app:1.0 -f ./php/Dockerfile \
--build-arg USER_NAME=app \
--build-arg USER_UID=$UID \
--build-arg USER_GID=$(id -g) \
--build-arg APP_ENV=production||local \
--build-arg REMOTE_SRC=/var/www/domain.xyz \
--build-arg LOCAL_APP_PATH=./app \
--build-arg LOCAL_DOCKER_PATH=./docker \
./../
Nginx Webserver
Image will be used as REVERSE PROXY.
Use the following command to build the image:
make build-webserver \
app_domain=domain.xyz \
remote_src=/var/www/domain.xyz \
webserver_image_name=webserver:1.0
-
app_domain
is used for settingserver_name
inapp.conf
file. -
remote_src
must have the same value used in themake build-app
command. So there is no conflict in the communication of the services of the reverse proxy (NGINX) with the service CGI (PHP-FPM). -
Use the Let's Encrypt to generate SSL certificates and perform the NGINX SSL configuration to use the HTTPS protocol.
- Folder
nginx/certs/
should contain the files created by Let's Encrypt. It should contain the files:cert.pem
,chain.pem
,dhparam4096.pem
,fullchain.pem
,privkey.pem
.
- Folder
Run the application
Copy the files from the
php
folder to the docker root folder(./docker/php/app.env.example
move to./docker/app.env
):app.env.example
,queue.env.example
,scheduler.env.example
, and set to the values that will be used in the environment. Remove the suffix.env.example
, leaving only.env
.
APP_KEY
: If the application key is not set, your user sessions and other encrypted data will not be secure!
There are three ways to execute the application container:
PHP-FPM(default)
Runs the container with the PHP-FPM processes running.
Set the CONTAINER_ROLE
environment variable when running the PHP container so that its value is app
.
exec /usr/local/sbin/php-fpm -y /usr/local/etc/php-fpm.conf --nodaemonize --force-stderr
Queue
Container/service responsible for managing Queue in the application.
Set the CONTAINER_ROLE
environment variable when running the PHP container so that its value is queue
.
Container with PID 1 executed by supervisor to manage processes. Can have two configurations:
- Many processes running in the Laravel
artisan queue:work
for queue management. - Used for debugging and development, the Horizon is a robust and simplistic queue management panel. A single process in a supervisor configuration by running the
artisan horizon
command.
exec /usr/bin/supervisord --nodaemon --configuration /etc/supervisor/supervisord.conf
Mandatory environment variables
LARAVEL_QUEUE_MANAGER
: This environment variable defines the container context, and can have the following values:- worker: Configure the supervisor to run many processes in the Laravel command
artisan queue:work
. - horizon: Configure the supervisor to run a single Horizon process
artisan horizon
.
- worker: Configure the supervisor to run many processes in the Laravel command
Scheduler
Container/service responsible for managing Scheduler in the application.
Set the CONTAINER_ROLE
environment variable when running the PHP container so that its value is scheduler
.
- Container with PID 1 executed by cron.
- Environment variables
APP_KEY
andAPP_ENV
are required when executing the container. - Environment variables available for PHP processes thanks to the
printenv > /etc/environment
script in container entrypoint. - Container run as
root
as a cron service request.
Running a single scheduling command
* * * * * {{USER}} /usr/local/bin/php {{REMOTE_SRC}}artisan schedule:run --no-ansi >> /usr/local/var/log/php/cron-laravel-scheduler.log 2>&1
exec /usr/sbin/crond -l 2 -f -L /var/log/cron.log
docker-compose up
Some points to consider:
- MongoDB Container Uses SSL/TLS configuration for database connections. Before running the container you need to create these SSL files, or simply remove this setting.
- MySQL is also configured to accept only SSL connections. You can generate SSL keys through this link https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html.
- The Redis container uses a password(
requirepass
) to perform a database connection. - The Nginx container uses SSL certificates to make HTTPS connections only.
Only port 80 and 443 are tight to the internet for security reasons.
Change the passwords present in the files: mysql.env
, redis.conf
and the docker-compose.yml
variables which are: RABBITMQ_USERNAME
, RABBITMQ_PASSWORD
, MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
.
This project use the following ports:
Server | Port |
---|---|
Nginx | 80 |
Nginx | 443 |
Set the WEBSERVER_PORT_HTTP
environment variable for HTTP connections and WEBSERVER_PORT_HTTPS
for HTTPS connections.
Helpers commands
To access the MySQL via Terminal/Console:
mysql -h 127.0.0.1 -P 30062 -uapp -p'ExBkhs^NGuA6r_Fu' \
--ssl-ca=mysql/ssl/ca.pem \
--ssl-cert=mysql/ssl/client-cert.pem \
--ssl-key=mysql/ssl/client-key.pem
To access the Redis container database:
docker exec -it redis redis-cli -n 0 -p 6379 -a '.7HVhf(Yh+9CF-58' --no-auth-warning
To access the MongoDB via Terminal/Console:
mongo --ssl \
--sslCAFile ./mongodb/ssl/ca.pem --sslPEMKeyFile ./mongodb/ssl/client.pem \
--host 127.0.0.1 --port 29019 -u 'root' -p 'jyA7LF_7dX7.pmH' --authenticationDatabase admin
Install PHP modules
docker exec -it app /bin/bash
# After
$ /usr/local/bin/docker-php-ext-configure xdebug
$ /usr/local/bin/docker-php-ext-install xdebug
Installing package with composer
docker run --rm -v $(pwd):/app composer require laravel/horizon
Updating PHP dependencies with composer
docker run --rm -v $(pwd):/app composer update
Testing PHP application with PHPUnit
docker-compose exec -T app ./vendor/bin/phpunit --colors=always --configuration ./app
PSR2
Fixing standard code withdocker-compose exec -T app ./vendor/bin/phpcbf -v --standard=PSR2 ./app
PHP Mess Detector
Analyzing source code withdocker-compose exec -T app ./vendor/bin/phpmd ./app text cleancode,codesize,controversial,design,naming,unusedcode
Contributing
If you find an issue, or have a special wish not yet fulfilled, please open an issue on GitHub providing as many details as you can (the more you are specific about your problem, the easier it is for us to fix it).
Pull requests are welcome, too 😁! Also, it would be nice if you could stick to the best practices for writing Dockerfiles.