This is a personal collection of Docker tools and images(Nginx, PHP-FPM, MySQL, Redis, MongoDB, Queue, Scheduler, ELK and Traefik) for applications in Laravel
Project Structure/Tree β’ What's Inside/Softwares Included β’ Getting Started β’ Build Images β’ Use Makefile
- A single service, a single application per container. Containers responsible for running a single service
- Configurations and variables of environment separated by service/container
Makefile
has the main commands for image build and container execution- MySQL configured to only accept connections in SSL/TLS
- MongoDB configured to only accept SSL/TLS connections
- Container of Reverse Proxy Nginx with the best security standard:
- Force HTTPS
- TLS best practices
- Security HTTP headers
- Controlling buffer overflow attacks
- Control simultaneous connections
- Allow access to our domain only
- Limit available methods
- Block referral spam
- Stop image Hotlinking
- Block ips attack by brute force
- Easy use and configuration of Traefik, acting as Api Gateway, forwarding the requests to the specific destination according to the applied rule
- A single container responsible for handling Queue
- A single container responsible for handling Scheduler
.
βββ .dockerignore
βββ .env.example
βββ Makefile
βββ docker-compose.yml
βββ docker-compose.override.yml
βββ php
βΒ Β βββ Dockerfile
βββ app
βΒ Β βββ Dockerfile
βΒ Β βββ docker-entrypoint.sh
βΒ Β βββ app.env.example
βΒ Β βββ config
βΒ Β βββ php.ini-development.ini
βΒ Β βββ php.ini-production.ini
βΒ Β βββ extensions
βΒ Β βΒ Β βββ opcache.ini
βΒ Β βΒ Β βββ xdebug.ini
βΒ Β βββ fpm
βΒ Β βΒ Β βββ php-fpm.conf
βΒ Β βΒ Β βββ www.conf
βΒ Β βββ vscode
βΒ Β βββ launch.json
βββ queue
βΒ Β βββ Dockerfile
βΒ Β βββ docker-entrypoint.sh
βΒ Β βββ queue.env.example
βΒ Β βββ config
βΒ Β βββ supervisord.conf
βΒ Β βββ templates
βΒ Β βββ laravel-horizon.conf.tpl
βΒ Β βββ laravel-worker.conf.tpl
βββ scheduler
βΒ Β βββ Dockerfile
βΒ Β βββ docker-entrypoint.sh
βΒ Β βββ scheduler.env.example
βΒ Β βββ cron-jobs
βΒ Β βββ laravel-scheduler
βββ nginx
βΒ Β βββ .dockerignore
βΒ Β βββ Dockerfile
βΒ Β βββ docker-entrypoint.sh
βΒ Β βββ certs
βΒ Β βΒ Β βββ cert.pem
βΒ Β βΒ Β βββ chain.pem
βΒ Β βΒ Β βββ dhparam4096.pem
βΒ Β βΒ Β βββ fullchain.pem
βΒ Β βΒ Β βββ privkey.pem
βΒ Β βββ config
βΒ Β βΒ Β βββ mime.types
βΒ Β βΒ Β βββ nginx.conf
βΒ Β βΒ Β βββ servers
βΒ Β βΒ Β βΒ Β βββ admin.conf
βΒ Β βΒ Β βΒ Β βββ api.conf
βΒ Β βΒ Β βΒ Β βββ app.conf
βΒ Β βΒ Β βΒ Β βββ site.conf
βΒ Β βΒ Β βΒ Β βββ webmail.conf
βΒ Β βΒ Β βββ snippets
βΒ Β βΒ Β βββ php
βΒ Β βΒ Β βΒ Β βββ fastcgi.conf
βΒ Β βΒ Β βΒ Β βββ php_fpm.conf
βΒ Β βΒ Β βββ server
βΒ Β βΒ Β βββ cache_expiration.conf
βΒ Β βΒ Β βββ deny_ips.conf
βΒ Β βΒ Β βββ real_ip.conf
βΒ Β βΒ Β βββ security_http_headers.conf
βΒ Β βΒ Β βββ ssl_best_practices.conf
βΒ Β βΒ Β βββ ssl_common_certificates.conf
βΒ Β βββ helpers
βΒ Β βββ cert-status.sh
βββ redis
βΒ Β βββ redis.conf
βββ mysql
βΒ Β βββ my.cnf
βΒ Β βββ mysql.env
βΒ Β βββ ssl
βΒ Β βββ ca-key.pem
βΒ Β βββ ca.pem
βΒ Β βββ client-cert.pem
βΒ Β βββ client-key.pem
βΒ Β βββ server-cert.pem
βΒ Β βββ server-key.pem
βββ mongodb
βΒ Β βββ mongo-init.js
βΒ Β βββ mongod.conf
βΒ Β βββ ssl
βΒ Β βββ ca.key
βΒ Β βββ ca.pem
βΒ Β βββ client.crt
βΒ Β βββ client.csr
βΒ Β βββ client.key
βΒ Β βββ client.pem
βΒ Β βββ server.crt
βΒ Β βββ server.csr
βΒ Β βββ server.key
βΒ Β βββ server.pem
βββ elastic
βΒ Β βββ .env
βΒ Β βββ docker-compose-setup.yml
βΒ Β βββ docker-compose.yml
βΒ Β βββ config
βΒ Β βΒ Β βββ elasticsearch
βΒ Β βΒ Β βΒ Β βββ elasticsearch.yml
βΒ Β βΒ Β βββ filebeat
βΒ Β βΒ Β βΒ Β βββ filebeat.yml
βΒ Β βΒ Β βββ kibana
βΒ Β βΒ Β βΒ Β βββ kibana.yml
βΒ Β βΒ Β βββ logstash
βΒ Β βΒ Β βΒ Β βββ logstash.yml
βΒ Β βΒ Β βΒ Β βββ pipeline
βΒ Β βΒ Β βΒ Β βββ logstash.conf
βΒ Β βΒ Β βββ metricbeat
βΒ Β βΒ Β βΒ Β βββ metricbeat.yml
βΒ Β βΒ Β βββ packetbeat
βΒ Β βΒ Β βΒ Β βββ packetbeat.yml
βΒ Β βΒ Β βββ ssl
βΒ Β βΒ Β βββ ca
βΒ Β βΒ Β βββ instances.yml
βΒ Β βββ scripts
βΒ Β βΒ Β βββ setup-beat.sh
βΒ Β βΒ Β βββ setup-elasticsearch.sh
βΒ Β βΒ Β βββ setup-kibana.sh
βΒ Β βΒ Β βββ setup-logstash.sh
βΒ Β βΒ Β βββ setup-users.sh
βΒ Β βΒ Β βββ setup.sh
βΒ Β βββ setups
βΒ Β βββ docker-compose.setup.beats.yml
βΒ Β βββ docker-compose.setup.elasticsearch.yml
βΒ Β βββ docker-compose.setup.kibana.yml
βΒ Β βββ docker-compose.setup.logstash.yml
βββ traefik
βββ traefik.toml
Download and install Docker Engine (>= 18.09) for your platform and you also have to install Docker compose (>= 1.24.0)
PHP
7.4.x- PHP-FPM
Nginx
1.17.xMySQL
5.7MongoDB
4.2-
Redis
5.x Elasticsearch
|Logstash
|Kibana
6.6.xTraefik
1.7.x
[Installed PHP extensions](The following modules and extensions have been enabled, in addition to those you can already find in the official PHP image)
You are able to find all installed PHP extensions by running php -m
inside your workspace.
bcmath
Core
ctype
curl
date
dom
fileinfo
filter
ftp
gd
gmp
hash
iconv
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
soap
sockets
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zip
zlib
Optional modules that can be installed according to the compilation/build of the PHP base image(make build-php
)
amqp
swoole
mongodb
sqlsrv
pdo_sqlsrv
ds
igbinary
lzf
msgpack
redis
xdebug
Xdebug
Zend OPcache
- The folder name of the repository must be
docker
and notlaravel-docker
(original repository name) - Folder
docker
must be in the root folder of the Laravel project - Copy
.dockerignore
to the project's root folder
To install Git, download to the root folder of the laravel project it and install following the instructions:
$ git clone https://github.com/AllysonSilva/laravel-docker docker && cd docker
- Rename the
.env.example
file to.env
- Uncomment the
pwd
variable and fill it with resultecho $PWD
- Use the
DOCKER_FOLDER_PATH
variable in the.env
file for the folder namedocker
Customize Running in Development
docker-compose -f docker-compose.yml -f docker-compose.override.yml up database redis app webserver queue
- To generate SSL certificates using the minica package, use the following command:
make app-ssl-certs domain_app=yourdomain.tld
- To build all the images that will be used by
docker-compose
, use the following initialization:
make build \
domain_app=yourdomain.tld \
app_path_prefix=/var/www \
remote_src=/var/www/yourdomain.tld/ \
app_env=local \
project_environment=development \
docker_folder_path=./docker
- Add the domain in
/etc/hosts
sudo tee -a /etc/hosts >/dev/null <<EOF
127.0.0.1 yourdomain.tld
127.0.0.1 www.yourdomain.tld
EOF
Run the make pull
command to download the images that will be used in docker-compose.yml
or make
commands.
Image(
app:base
) used to be as BASE in the firstFROM
instruction ofDockerfile
. Used as a more generic image for any application in PHP. It has the responsibility to act only as a BASE image for more specific images according to the type of the framework/application PHP(Laravel, Symfony, CakePHP ...)
-
By default
php.ini
corresponds to thephp.ini-production
file of the source code in the default repository in GitHub PHPmv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
-
Composer: Installed globally in the path of the
$PATH
/usr/local/bin/composer
-
PHPUnit: Installed globally in the path of the
$PATH
/usr/local/bin/phpunit
-
WORKDIR
in Dockerfile corresponds to the value of the argument--build-arg REMOTE_SRC=/var/www/app/
Use the following command to build the image:
$ make build-php php_base_image_name=app:base
If you want to customize the image construction according to your arguments, use the docker build
command directly:
docker build -t app:base \
--build-arg DEFAULT_USER=app \
--build-arg DEFAULT_USER_UID=$UID \
--build-arg DEFAULT_USER_GID=$(id -g) \
- < ./php/Dockerfile
Use the --build-arg
option to customize/install specific PHP extensions according to the arguments in the Dockerfile
of the image.
See Docker's documentation the ARG
statement in Dockerfile
The values of the arguments below represent default arguments that are used when the docker build
command is executed without any custom arguments.
docker build -t app:base \
--build-arg DEFAULT_USER=app \
--build-arg DEFAULT_USER_UID=$UID \
--build-arg DEFAULT_USER_GID=$(id -g) \
--build-arg INSTALL_PHP_AMQP=false \
--build-arg INSTALL_PHP_SWOOLE=false \
--build-arg INSTALL_PHP_MONGO=false \
--build-arg INSTALL_PHP_SQLSRV=false \
--build-arg INSTALL_PHP_IGBINARY=true \
--build-arg INSTALL_PHP_LZF=true \
--build-arg INSTALL_PHP_MESSAGEPACK=true \
--build-arg INSTALL_PHP_REDIS=true \
--build-arg INSTALL_PHP_DS=true \
--build-arg INSTALL_PHP_XDEBUG=true \
- < ./php/Dockerfile
To create the image with all extensions enabled by default, use the following command:
$ make build-full-php php_base_image_name=app:base
- The construction/configuration of this image is used for applications in Laravel
- Extend the image BASE PHP by means of instruction
FROM $PHP_BASE_IMAGE
in yourDockerfile
- 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
-
$PROJECT_ENVIRONMENT
: Can be set to two values: (production
anddevelopment
). Its purpose is to define the flow in the ENTRYPOINT (/entrypoint.sh
)- Can be defined at the moment of image creation through argument:
--build-arg PROJECT_ENVIRONMENT=production||development
) - Can be updated at the time of executing the container through environment variables:
--env "PROJECT_ENVIRONMENT=production||development"
- Can be defined at the moment of image creation through argument:
-
$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 -
The environment variables
${APP_PATH_PREFIX}
and${DOMAIN_APP}
only serve at the time of creation/build of the image. After the image is created, then these variables have no significance in ENTRYPOINT. It aims to define at the time of image build the value of the$REMOTE_SRC
variable that this same value will be used in theWORKDIR $REMOTE_SRC
statement -
$REMOTE_SRC
- Matches the value
${APP_PATH_PREFIX:-/var/www}/${DOMAIN_APP:-appxyz.dev}/
- Used in instruction
WORKDIR $REMOTE_SRC
onDockerfile
- Matches the value
-
WORKDIR
corresponds to the variable$REMOTE_SRC
that at the time of image build has its value${APP_PATH_PREFIX}/${DOMAIN_APP}/
, where the value of${DOMAIN_APP}
is equal to the value of thedomain_app
argument in the commandmake build-app ...
-
php.ini
: Configured at the time of image build and is set according to the value passed to$PROJECT_ENVIRONMENT
. If the value of$PROJECT_ENVIRONMENT
isdevelopment
thenphp.ini
will match the filesphp.ini-development.ini
, if the value of$PROJECT_ENVIRONMENT
isproduction
then the contents ofphp.ini
will correspond to the filephp.ini-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
Use the following command to build the image:
make build-app \
domain_app=mydomain.com \
app_env=production||local \
project_environment=production||development \
app_image_name=app:3.0 \
php_base_image_name=app:base
If you want to customize the image construction according to your arguments, use the docker build
command directly:
docker build -t app:3.0 -f ./app/Dockerfile \
--build-arg DOMAIN_APP=mydomain.com \
--build-arg APP_ENV=production \
--build-arg PHP_BASE_IMAGE=app:base \
--build-arg APP_PATH_PREFIX=/var/www \
--build-arg DOCKER_FOLDER_PATH=./docker \
--build-arg PROJECT_ENVIRONMENT=production \
./../
Edit the ENV variables to match the project settings. You can edit/add the environment variables in the
docker-compose.yml
file itself, which has priority over the same variable defined else where (Shell environment variables, Environment file,Dockerfile
).
To run the service/container through the run
command of Docker use/customize the following script:
Note: You must specify a unique APP_KEY
including base64:
prefix generated by php artisan key:generate
within the container.
docker run \
--rm \
-p 9001:9001 \
-p 8081:8080 \
-v $(pwd)/../:/var/www/mydomain.com/ \
-v $(pwd)/app/docker-entrypoint.sh:/entrypoint.sh:ro \
--env "REMOTE_SRC=/var/www/mydomain.com/" \
--env "APP_KEY=SomeRandomString" \
--env "PROJECT_ENVIRONMENT=development" \
--env "APP_ENV=local" \
--env "APP_DEBUG=true" \
--env "DB_CONNECTION=mysql" \
--env "DB_HOST=database" \
--env "DB_PORT=3306" \
--env "DB_DATABASE=app" \
--env "DB_USERNAME=root" \
--env "DB_PASSWORD=5?qqSm3_@mqrJ_" \
--env "REDIS_HOST=redis" \
--env "REDIS_PASSWORD=HQD3{9S-u(qnxK@" \
--env "REDIS_PORT=6379" \
--env "REDIS_QUEUE=queue_default" \
--env "BROADCAST_DRIVER=redis" \
--env "CACHE_DRIVER=redis" \
--env "QUEUE_CONNECTION=redis" \
--env "SESSION_DRIVER=redis" \
--user 1000:1000 \
--workdir "/var/www/mydomain.com/" \
--name=php-fpm \
--hostname=php-fpm \
-t app:3.0
To run a server with artisan serve
access the container first:
docker exec -ti php-fpm bash
Inside the container, run the following command to run the PHP built-in server with artisan serve
:
php artisan serve --port=8080 --host=0.0.0.0
-
The
--workdir
option of thedocker run
command must have the same value as the variable$REMOTE_SRC
-
The volume configuration destination
-v $(pwd)/../:/var/www/mydomain.com/
must match the same value of the variable$REMOTE_SRC
, which must match the same value as--workdir
indocker run
orWORKDIR
statement in Dockerfile
Image will be used as REVERSE PROXY.
- Configuration
ssl_best_practices.conf
andssl_common_certificates.conf
to allow only connections over the protocol HTTPS - Snippet
security_http_headers.conf
for best security practices for settings HTTP HEADERS - Snippet
deny_ips.conf
to block brute force attacks or IPs in the blacklist globally on the internet - Snippet
real_ip.conf
for PROXY configuration. Configuring the real client IP - Control, concurrent connection limitation, to block HOST attacks through
limit_conn
andlimit_req
instructions of NGINX - 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
- To generate the certificates use or customize the script:
make gen-certs domain_app=mydomain.com
- There are 4 configurations of virtual server, which are:
mydomain.com
,api.mydomain.com
,admin.mydomain.com
,webmail.mydomain.com
. All within the foldernginx/servers/
Use the following command to build the image:
make build-nginx \
domain_app=mydomain.com \
nginx_image_name=webserver:3.0 \
app_image_name=app:3.0
-
nginx_image_name
: Parameter used for TAG of the image -
domain_app
: Domain to be used on the path${APP_PATH_PREFIX}/${DOMAIN_APP}/
${APP_PATH_PREFIX}
: Application path prefix that matches the same value in the image Laravel APP/PHP-FPM and its default value is/var/www
${DOMAIN_APP}
: Parameter valuedomain_app
used in the commandmake build-nginx
- The same value for the
domain_app
parameter of this same image should match the same value used in the samedomain_app
parameter in the image compilation Laravel APP/PHP-FPM, so there is no conflict in the communication of the services of the reverse proxy (NGINX) with the service CGI (PHP-FPM)
To run the service using the run
command of Docker use/customize the following script:
docker run \
--rm \
-p 80:80 \
-p 443:443 \
-v $(pwd)/../:/var/www/mydomain.com/ \
-v $(pwd)/nginx/docker-entrypoint.sh:/entrypoint.sh:ro \
-v $(pwd)/nginx/config/nginx.conf:/etc/nginx/nginx.conf:ro \
-v $(pwd)/nginx/config/servers/:/etc/nginx/servers \
--env "DOMAIN_APP=mydomain.com" \
--env "APP_PATH_PREFIX=/var/www" \
--workdir "/var/www/mydomain.com/" \
--name=webserver \
--hostname=webserver \
-t webserver:3.0
To use only the servers/app.conf
(single domain) configuration of the serves use the ONLY_APP
option as the environment variable passing its value to true
:
docker run \
--rm \
-p 80:80 \
-p 443:443 \
--env "DOMAIN_APP=mydomain.com" \
--env "APP_PATH_PREFIX=/var/www" \
--env "ONLY_APP=true" \
--workdir "/var/www/mydomain.com/" \
--name=webserver \
--hostname=webserver \
-t webserver:3.0
Container/service will be used to manage the MySQL database.
- The MySQL (my.cnf) settings are set to use SSL, then the following instructions are to create the SSL configuration files:
Creating SSL and RSA Certificates and Keys using MySQL
mysql_ssl_rsa_setup --datadir=$(pwd)/mysql/ssl
# Verify a certificate chain
openssl verify -CAfile $(pwd)/mysql/ssl/ca.pem $(pwd)/mysql/ssl/server-cert.pem $(pwd)/mysql/ssl/client-cert.pem
Creating SSL Certificates and Keys Using openssl
Important
Whatever method you use to generate the certificate and key files, the Common Name value used for the server and client certificates/keys must each differ from the Common Name value used for the CA certificate. Otherwise, the certificate and key files will not work for servers compiled using OpenSSL.
Use the following information when completing the certificates CN
:
ca.pem CN/=MySQL_CA_Certificate
server-cert.pem CN/=MySQL_Server_Certificate
client-cert.pem CN/=MySQL_Client_Certificate
# Create CA certificate
openssl genrsa -out ca-key.pem -aes256 8192
openssl req -new -x509 -nodes -days 1024 \
-key ca-key.pem -out ca.pem \
-subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=authority/CN=MySQL_CA_Certificate"
# Create server certificate, remove passphrase, and sign it
# server-cert.pem = public key, server-key.pem = private key
openssl req -newkey rsa:4096 -days 365 \
-nodes -keyout server-key.pem -out server-req.pem \
-subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=server/CN=MySQL_Server_Certificate"
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 365 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
# Create client certificate, remove passphrase, and sign it
# client-cert.pem = public key, client-key.pem = private key
openssl req -newkey rsa:4096 -days 365 \
-nodes -keyout client-key.pem -out client-req.pem \
-subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=client/CN=MySQL_Client_Certificate"
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 365 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
- To see the contents of an SSL certificate (for example, to check the range of dates over which it is valid), run openssl directly:
openssl x509 -text -in ca.pem
openssl x509 -text -in server-cert.pem
openssl x509 -text -in client-cert.pem
- It is also possible to check SSL certificate expiration information using this SQL statement:
mysql> SHOW STATUS LIKE 'Ssl_server_not%';
- To find out if SSL is enabled in MySQL, use one of the following commands after logging in to Client-MySQL.
mysql> SHOW SESSION STATUS LIKE 'Ssl_version';
mysql> show variables like '%ssl%';
mysql> SHOW GLOBAL VARIABLES LIKE '%ssl%';
- To run the service/container using the Docker
run
command, use/customize the following script:
docker run \
--rm \
-p 30061:3306 \
-v $(pwd)/./mysql/ssl/ca.pem:/etc/mysql-ssl/ca.pem:ro \
-v $(pwd)/./mysql/ssl/server-cert.pem:/etc/mysql-ssl/server-cert.pem:ro \
-v $(pwd)/./mysql/ssl/server-key.pem:/etc/mysql-ssl/server-key.pem:ro \
-v $(pwd)/./mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro \
--env "MYSQL_DATABASE=app" \
--env "MYSQL_USER=app" \
--env "MYSQL_ROOT_PASSWORD=5?qqSm3_@mqrJ_" \
--env "MYSQL_PASSWORD=TxdITs=CgN9e7+p" \
--name=database \
--hostname=database \
-t mysql:5.7
- To access the database via Terminal/Console, use:
mysql -h 127.0.0.1 -P 30061 -uapp -p'TxdITs=CgN9e7+p' \
--ssl-ca=mysql/ssl/ca.pem \
--ssl-cert=mysql/ssl/client-cert.pem \
--ssl-key=mysql/ssl/client-key.pem
Container/service will be used to manage the Redis database. Used for Management of Queue, Sessions, Cache, and many other things in the application that require speed in retrieving/writing information;
- Use the following command to run the Redis container/service via Docker
run
option.
docker run \
--rm \
-p 63781:6379 \
-v $(pwd)/./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro \
--name=redis \
--hostname=redis \
-t redis:5-alpine redis-server /usr/local/etc/redis/redis.conf --appendonly yes
- To access the database Redis:
redis-cli -h 127.0.0.1 -p 63781 -a 'HQD3{9S-u(qnxK@'
Container/service responsible for managing MongoDB database.
Creating SSL Files from the Command Line on Unix
# Creating own SSL CA to dump our self-signed certificate
openssl genrsa -out ca.key -aes256 8192
openssl req -new -x509 -nodes -extensions v3_ca -key ca.key -days 1024 -out ca.pem -subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=authority/CN=MongoDB_CA_Certificate"
##############################
# Generate SERVER certificates
##############################
# Generate the Certificate Requests and the Private Keys
openssl req -newkey rsa:4096 -sha256 -nodes -keyout server.key -out server.csr -subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=server/CN=127.0.0.1"
openssl req -newkey rsa:4096 -sha256 -nodes -keyout client.key -out client.csr -subj "/C=BR/ST=State/L=Locality/O=Organization Name/OU=client/CN=MongoDB_Client_Certificate"
# Sign your Certificate Requests
openssl x509 -req -CA ca.pem -CAkey ca.key -set_serial 00 -days 365 -in server.csr -out server.crt
openssl x509 -req -CA ca.pem -CAkey ca.key -set_serial 00 -days 365 -in client.csr -out client.crt
# Concat each Node Certificate with its key
cat server.key server.crt > server.pem
cat client.key client.crt > client.pem
- To run the container using the
run
option in Docker, use the following script:
docker run \
--rm \
-p 29019:27017 \
-v $(pwd)/./mongodb/mongod.conf:/etc/mongo/mongod.conf:ro \
-v $(pwd)/./mongodb/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro \
-v $(pwd)/./mongodb/ssl/ca.pem:/etc/ssl/ca.pem:ro \
-v $(pwd)/./mongodb/ssl/server.pem:/etc/ssl/server.pem:ro \
--env "MONGO_INITDB_ROOT_USERNAME=root" \
--env "MONGO_INITDB_ROOT_PASSWORD=Y601=lN!JbL6yj18" \
--name=mongodb \
--hostname=mongodb \
-t mongo:4.2 mongod --config /etc/mongo/mongod.conf
Secure your MongoDB connections - SSL/TLS
- To access the MongoDB container database:
mongo --ssl \
--sslCAFile ./mongodb/ssl/ca.pem --sslPEMKeyFile ./mongodb/ssl/client.pem \
--host 127.0.0.1 --port 29019 -u 'root' -p 'Y601=lN!JbL6yj18' --authenticationDatabase admin
Container/service responsible for managing Queue in the application.
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
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
APP_KEY
: If the application key is not set, your user sessions and other encrypted data will not be secure!APP_ENV
: Configures the environment in which the application will runPROJECT_ENVIRONMENT
: Can be set to two values:production
anddevelopment
. It aims to define the flow in the file of ENTRYPOINT (/start.sh
)
Build
Use the following script to build the image:
$ make build-queue app_queue_image_name=app:queue app_image_name=app:3.0
Run
To run the queue container use the run
command from docker:
docker run \
--rm \
-p 8081:8080 \
--workdir "/var/www/mydomain.com/" \
-v $(pwd)/../:/var/www/mydomain.com/ \
-v $(pwd)/queue/docker-entrypoint.sh:/start.sh \
-v $(pwd)/app/config/php.ini-production.ini:/usr/local/etc/php/php.ini:ro \
--env "APP_ENV=production" \
--env "PROJECT_ENVIRONMENT=production" \
--env "APP_KEY=SomeRandomString" \
--env "CACHE_DRIVER=redis" \
--env "QUEUE_CONNECTION=redis" \
--env "BROADCAST_DRIVER=redis" \
--env "REDIS_PASSWORD=HQD3{9S-u(qnxK@" \
--env "REDIS_HOST=redis" \
--env "REDIS_PORT=6379" \
--env "REDIS_QUEUE=queue_default" \
--env "DB_HOST=database" \
--env "DB_PORT=3306" \
--env "DB_DATABASE=app" \
--env "DB_USERNAME=app" \
--env "DB_PASSWORD=TxdITs=CgN9e7+p" \
--name=app-queue \
-t app:queue
Container/service responsible for managing Scheduler in the application.
- 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
Build
$ make build-scheduler app_scheduler_image_name=app:scheduler app_image_name=app:3.0
A set of services that are not in the main docker-compose.yml
at the root of the project, but is located in the elastic
folder with its own settings, its own docker-compose.yml
because it has a level of complexity higher than the other services (MySQL, PHP, Redis ...). It has the following services: elasticsearch
, kibana
, logstash
, metricbeat
, filebeat
and packetbeat
.
First we need to:
- Set default password
- Create keystores to store passwords
- Install dashboards, index patterns, etc.. for beats and apm
This is accomplished using the docker-compose-setup.yml
file:
cd elastic && docker-compose -f docker-compose-setup.yml up && docker-compose up
Please take note after the setup completes it will output the password that is used for the elastic
login.
Now we can launch the stack with docker-compose up -d
to create a demonstration Elastic Stack with Elasticsearch, Kibana, Logstash, Metricbeat, Filebeat and Packetbeat.
Point a browser at http://localhost:56011
to see the results.
NOTE: Elasticsearch is now setup with self-signed certs.
Log in with elastic
and what ever your auto generated elastic password is from the setup.
Login in container:
docker exec -ti elasticsearch bash
Change users password:
bin/elasticsearch-setup-passwords interactive
or
/usr/local/bin/setup-users.sh
Deleting the volume from the elasticsearch
service
If the main volume of the elasticsearch
service data is deleted, you should run the /usr/local/bin/setup-users.sh
script so that users of services that were once configured in the initial SETUP (Kibana, Logstash ...), can be configured again.
Note: Before running the above script, you must uncomment the environment variable ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
from the elasticsearch
service, so that the password can be configured on users of services that are experiencing connection problems.
The password in ELASTIC_PASSWORD
should be the same as the one configured in the initial SETUP, otherwise, there will still be problems in the connections between the service.
When developing, you can use Makefile for doing the following operations:
Name | Description |
---|---|
build | Initializes and configures docker in the application |
app-ssl-certs | Generate LOCAL SSL certificates for single domain |
pull | Download images |
build-nginx | Build the NGINX image to act as a reverse proxy |
run-nginx | Create a container for the webserver with docker run |
in-nginx | Access the NGINX container |
build-php | Build the base image of projects in PHP |
build-full-php | Build the base image of projects in PHP with all extensions and components enabled by default |
build-app | Build the image with settings for Laravel/PHP projects |
run-app | Create a container for the application with docker run |
build-queue | Build the image to act as queue management. Extends the default project image (build-app) |
build-scheduler | Build the image to act as scheduler management. Extends the default project image (build-app) |
app-code-phpcs | Check the APP with PHP Code Sniffer (PSR2 ) |
app-code-phpmd | Analyse the APP with PHP Mess Detector |
docker-clean | Remove docker images with filter <none> |
docker-stop | Stop and execute $> make docker-clean |
composer-up | Update PHP dependencies with composer |
gen-certs | Generate SSL certificates |
get-certs | Retrieves certificate expiration dates |
mysql-dump | Create backup of all databases |
mysql-restore | Restore backup of all databases |
In Makefile need GNU sed to work so replace BSD sed with GNU sed using:
brew install gnu-sed
Update the default shell (bashrc or zshrc):
if brew ls --versions gnu-sed > /dev/null; then
export PATH="$(brew --prefix gnu-sed)/libexec/gnubin:$PATH"
fi
# or
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Reload shell:
source ~/.bashrc
# or
source ~/.zshrc
Check you version of sed with:
man sed
sed GNU version path is:
$ which sed
/usr/local/opt/gnu-sed/libexec/gnubin/sed
Instead of default path of BSD sed (installed by default on MAC OS):
/usr/bin/sed
- You have Docker and Docker-Compose installed (Docker for Mac, Docker for Windows, get.docker.com and manual Compose installed for Linux).
- You want to use Docker for local development (i.e. never need to install php or npm on host) and have dev and prod Docker images be as close as possible.
- You don't want to lose fidelity in your dev workflow. You want a easy environment setup, using local editors, debug/inspect, local code repo, while web server runs in a container.
- You use
docker-compose
for local development only (docker-compose was never intended to be a production deployment tool anyway). - The
docker-compose.yml
is not meant fordocker stack deploy
in Docker Swarm, it's meant for happy local development.
docker exec -t -i app /bin/bash
# After
$ /usr/local/bin/docker-php-ext-configure xdebug
$ /usr/local/bin/docker-php-ext-install xdebug
docker run --rm -v $(pwd):/app composer require laravel/horizon
docker run --rm -v $(pwd):/app composer update
docker-compose exec -T app ./vendor/bin/phpunit --colors=always --configuration ./app
Fixing standard code with PSR2
docker-compose exec -T app ./vendor/bin/phpcbf -v --standard=PSR2 ./app
Analyzing source code with PHP Mess Detector
docker-compose exec -T app ./vendor/bin/phpmd ./app text cleancode,codesize,controversial,design,naming,unusedcode
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.