laravel-docker
laravel-docker copied to clipboard
π³ π Dockerized PHP/LARAVEL stack: Nginx, PHP, MySQL, MongoDB, Traefik, Redis, Authelia, Netdata, Portainer
Β Β
>
Β
Laravel Dockerized
Use this repository to get started with developing your Laravel application in a Docker container.
This is a personal collection of Docker images and services(Nginx, PHP-FPM, Traefik, Authelia, Netdata, New Relic, Portainer, MySQL, Redis, MongoDB, Queue, Scheduler, and GoAccess) for applications in Laravel.
Overview
- Getting Started
- Organization
- Initial setup / clone the project
- Build the image of the Laravel/APP PHP-FPM application
- Build the NGINX/Webserver image
- Create Letβs Encrypt certificates
- Generating with DNS challenge
- Before up the application
- Create the default container networks
- UP APP Application + NGINX/Webserver
- APP/Laravel with New Relic
- NGINX/Webserver with GeoIP2
- Run Containers
- Run Redis Container
- Run Authelia Container
- Run Netdata Container
- Run MongoDB Container
- Run MySQL Container
- Run Portainer Container
- Run Queue Container
- Run Scheduler Container
- Run GoAccess Container
- Makefile Commands
- Scripts
./scripts/cron-renew-certs.sh./scripts/deploy-version.sh./scripts/loadbalancer-nginx.sh./scripts/update-app.sh
- Setup Auto-Renew Let's Encrypt SSL Certificates
- Generate SSL certificates manually
- Configure
renew.envto generate certificates via HTTP challenge - Configure
renew.envto generate certificates via DNS challenge - Configure
renew.envto generate the certificates via the DNS plugin certbot-dns-cloudflare
- Configure
- Configure CRON to automatically generate SSL certificates
- Generate SSL certificates manually
Project Structure/Tree
tree --sort=name --dirsfirst -a -I ".git|.DS_Store"
.
βββ nginx
βΒ Β βββ configs
βΒ Β βΒ Β βββ addon.d
βΒ Β βΒ Β βΒ Β βββ 10-realip.conf
βΒ Β βΒ Β βββ nginx.d
βΒ Β βΒ Β βΒ Β βββ 10-deny-ips.conf
βΒ Β βΒ Β βΒ Β βββ 10-security-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
βΒ Β βΒ Β βββ snippets
βΒ Β βΒ Β βΒ Β βββ cache-static.conf
βΒ Β βΒ Β βΒ Β βββ deny.conf
βΒ Β βΒ Β βΒ Β βββ http-to-https-non-www.conf
βΒ Β βΒ Β βΒ Β βββ no-caching.conf
βΒ Β βΒ Β βΒ Β βββ php-fpm-common.conf
βΒ Β βΒ Β βΒ Β βββ php-fpm.conf
βΒ Β βΒ Β βΒ Β βββ resolver-docker.conf
βΒ Β βΒ Β βΒ Β βββ resolver-global.conf
βΒ Β βΒ Β βΒ Β βββ ssl-certificates.conf
βΒ Β βΒ Β βΒ Β βββ ssl.conf
βΒ Β βΒ Β βΒ Β βββ www-to-non-www.conf
βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ fastcgi.conf
βΒ Β βΒ Β βββ mime.types
βΒ Β βΒ Β βββ nginx.conf
βΒ Β βββ geoip2
βΒ Β βΒ Β βββ cronjob
βΒ Β βββ logrotate
βΒ Β βΒ Β βββ conf.d
βΒ Β βΒ Β βΒ Β βββ nginx
βΒ Β βΒ Β βββ cronjob
βΒ Β βΒ Β βββ logrotate.conf
βΒ Β βββ .dockerignore
βΒ Β βββ Dockerfile
βΒ Β βββ DockerfileCertbot
βΒ Β βββ docker-entrypoint.sh
βββ php
βΒ Β βββ configs
βΒ Β βΒ Β βββ conf.d
βΒ Β βΒ Β βΒ Β βββ opcache.ini
βΒ Β βΒ Β βΒ Β βββ xdebug.ini
βΒ Β βΒ Β βββ fpm
βΒ Β βΒ Β βΒ Β βββ pools
βΒ Β βΒ Β βΒ Β βΒ Β βββ www.conf
βΒ Β βΒ Β βΒ Β βββ global.conf
βΒ Β βΒ Β βββ php-local.ini
βΒ Β βΒ Β βββ php-production.ini
βΒ Β βββ logrotate
βΒ Β βΒ Β βββ conf.d
βΒ Β βΒ Β βΒ Β βββ php
βΒ Β βΒ Β βΒ Β βββ php-fpm
βΒ Β βΒ Β βΒ Β βββ storage-app
βΒ Β βΒ Β βββ cronjob
βΒ Β βΒ Β βββ logrotate.conf
βΒ Β βββ queue
βΒ Β βΒ Β βββ templates
βΒ Β βΒ Β βΒ Β βββ laravel-horizon.conf.tpl
βΒ Β βΒ Β βΒ Β βββ laravel-worker.conf.tpl
βΒ Β βΒ Β βββ supervisord.conf
βΒ Β βββ vscode
βΒ Β βΒ Β βββ launch.json
βΒ Β βββ Dockerfile
βΒ Β βββ docker-entrypoint.sh
βββ scripts
βΒ Β βββ envs
βΒ Β βΒ Β βββ deploy.env
βΒ Β βΒ Β βββ docker.env
βΒ Β βΒ Β βββ renew.env
βΒ Β βββ cloudflare-ips-ufw.sh
βΒ Β βββ cron-renew-certs.sh
βΒ Β βββ deploy-version.sh
βΒ Β βββ loadbalancer-nginx.sh
βΒ Β βββ renew-certs.sh
βΒ Β βββ self-signed-SSL.sh
βΒ Β βββ update-app.sh
βββ services
βΒ Β βββ app
βΒ Β βΒ Β βββ .env.compose
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ Makefile
βΒ Β βΒ Β βββ docker-compose.webserver.yml
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ authelia
βΒ Β βΒ Β βββ configs
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βΒ Β βββ configuration.yml
βΒ Β βΒ Β βΒ Β βββ users.yml
βΒ Β βΒ Β βββ data
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ secrets
βΒ Β βΒ Β βΒ Β βββ jwt
βΒ Β βΒ Β βΒ Β βββ redis
βΒ Β βΒ Β βΒ Β βββ session
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ goaccess
βΒ Β βΒ Β βββ html
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ .env.compose
βΒ Β βΒ Β βββ docker-compose.webserver.yml
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βΒ Β βββ entrypoint.sh
βΒ Β βΒ Β βββ goaccess.conf
βΒ Β βββ mongodb
βΒ Β βΒ Β βββ ssl
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βΒ Β βββ mongod.conf
βΒ Β βββ mysql
βΒ Β βΒ Β βββ ssl
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βΒ Β βββ my.cnf
βΒ Β βββ netdata
βΒ Β βΒ Β βββ configs
βΒ Β βΒ Β βΒ Β βββ alarms
βΒ Β βΒ Β βΒ Β βΒ Β βββ cgroups.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ cpu.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ mysql.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ nginx.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ phpfpm.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ ram.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ web_log.conf
βΒ Β βΒ Β βΒ Β βββ modules
βΒ Β βΒ Β βΒ Β βΒ Β βββ go.d
βΒ Β βΒ Β βΒ Β βΒ Β βββ mysql.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ nginx.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ phpfpm.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ prometheus.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ redis.conf
βΒ Β βΒ Β βΒ Β βΒ Β βββ web_log.conf
βΒ Β βΒ Β βΒ Β βββ orchestrators
βΒ Β βΒ Β βΒ Β βΒ Β βββ go.d.conf
βΒ Β βΒ Β βΒ Β βββ health.conf
βΒ Β βΒ Β βΒ Β βββ netdata.conf
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ newrelic
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βΒ Β βββ infrastructure.sh
βΒ Β βββ nginx
βΒ Β βΒ Β βββ certs
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ servers
βΒ Β βΒ Β βΒ Β βββ additional
βΒ Β βΒ Β βΒ Β βΒ Β βββ goaccess.conf
βΒ Β βΒ Β βΒ Β βββ shared
βΒ Β βΒ Β βΒ Β βΒ Β βββ letsencrypt.conf
βΒ Β βΒ Β βΒ Β βββ templates
βΒ Β βΒ Β βΒ Β βΒ Β βββ app.conf.tpl
βΒ Β βΒ Β βΒ Β βΒ Β βββ spa.conf.tpl
βΒ Β βΒ Β βΒ Β βββ app.conf
βΒ Β βΒ Β βΒ Β βββ healthcheck.conf
βΒ Β βΒ Β βΒ Β βββ nginx-status.conf
βΒ Β βΒ Β βΒ Β βββ phpfpm-status.conf
βΒ Β βΒ Β βββ .env.compose
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ Makefile
βΒ Β βΒ Β βββ docker-compose.certs.yml
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ portainer
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ queue
βΒ Β βΒ Β βββ .env.compose
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ redis
βΒ Β βΒ Β βββ ssl
βΒ Β βΒ Β βΒ Β βββ .gitignore
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βΒ Β βββ redis.conf
βΒ Β βββ scheduler
βΒ Β βΒ Β βββ .env.compose
βΒ Β βΒ Β βββ .env.container
βΒ Β βΒ Β βββ docker-compose.yml
βΒ Β βββ traefik
βΒ Β βββ .env.compose
βΒ Β βββ docker-compose.yml
βββ traefik
βΒ Β βββ dynamic
βΒ Β βΒ Β βββ 10-tls.yml
βΒ Β βΒ Β βββ WRR-service.yml
βΒ Β βΒ Β βββ dashboard.yml
βΒ Β βΒ Β βββ middlewares.yml
βΒ Β βΒ Β βββ routers.yml
βΒ Β βΒ Β βββ services.yml
βΒ Β βββ .gitignore
βΒ Β βββ traefik.yml
βββ .dockerignore
βββ .editorconfig
βββ .env.example
βββ .gitignore
βββ Makefile
βββ README.md
βββ docker-compose.yml
βββ systemd.services
Docker Images Included:
- PHP
8.0-fpm-alpine - Traefik
v2.4 - Nginx
1.20-alpine - MySQL
8.0 - MongoDB
4.4 - Redis
6.2 - Authelia
4.29 - Netdata
v1.31 - Portainer
2.5.1-alpine
[PHP Modules/Extensions]
[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 calendar Core ctype curl date dom exif 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 xsl zip zlib
Additional non-core php extensions:
amqp mongodb ds igbinary newrelic msgpack redis
[Zend Modules]
Xdebug OPcache
Getting Started
Organization
dockerfolder must match current repository folder- The folder name is configurable via the
LOCAL_DOCKER_FOLDERvariable of the.envenvironment file
- The folder name is configurable via the
appfolder should contain Laravel application- The folder name is configurable via the
APP_LOCAL_FOLDERvariable of the.envenvironment file
- The folder name is configurable via the
The organization of the folders should serve as a reference for organizing this repository Docker + Laravel Application:
.
βββ /var/www/
βββ docker
βββ your-app
βββ your-app-2
Initial setup / clone the project
$ git clone https://github.com/AllysonSilva/laravel-docker docker && cd docker
- Execute command
make config-env docker_folder=./docker - The
LOCAL_DOCKER_FOLDERvariable in the.envfile must be the folder name of the docker project
Obs: The .env file is a copy of the .env.example file, which is created from the initial make config-env command.
Important:
- Open
.envfile and editPROJECT_NAMEandDOMAINvariables- The value of the
DOMAINvariable from the scripts/envs/deploy.env file must match the same value as the same variable from the.envfile
- The value of the
- Search for
yourdomain.tldwithin that same Docker folder and replace with your company's domain - Copy scripts/envs/docker.env file to root
dockerfolder- Use the command to make the copy:
cp scripts/envs/docker.env . - Edit the variable
COMPOSE_PROJECT_NAME, where it should have the same value as the variablePROJECT_NAMEin the.envfile
- Use the command to make the copy:
Build the image of the Laravel/APP PHP-FPM application
- Copy the contents of the services/app/.env.compose file and place at the end of the
.envfile - Copy the
.dockerignorefile to a higher folder level with the commandcp .dockerignore .. - Open the
.envfile and edit the variablesAPP_IMAGE,APP_LOCAL_FOLDER,APP_LIMITS_CPU,APP_LIMITS_MEMORYandAPP_RESERVATIONS_MEMORYAPP_IMAGE: Docker image tag that will be used in its creation through thedocker-build-appcommand and also used in the execution of PHP/Laravel containersAPP_LOCAL_FOLDER: Name of the folder where the Laravel application is located. It should be./folder-name-project-laravel
- Download the Laravel application repository. The
APP_LOCAL_FOLDERvariable in the.envfile must have the same name as the Laravel application folder - If it's in the Docker root folder, go back up one folder to clone the Laravel application repository(
cd ..)- Download the Laravel application:
git clone --branch 8.x --single-branch https://github.com/laravel/laravel.git app - Return to Docker folder:
cd docker
- Download the Laravel application:
- To install composer dependencies, use the command:
make -f Makefile -f services/app/Makefile composer-install- It is not necessary in the image building process, only if using volumes/bind in Docker
- After installing the composer dependencies, the
vendorfolder will be withrootpermission. To change the permission of the Laravel application folder to the machine user, use the command:sudo chown -R $USER:$USER ../app/
- To install npm dependencies run:
make -f Makefile -f services/app/Makefile npm-handlemake -f Makefile -f services/app/Makefile npm-handle npm_command="npm run prod"
- Use the command to build the image:
make -f Makefile -f services/app/Makefile docker-build-app
Build the NGINX/Webserver image
Obs: If the server is not using Cloudflare as protection/Load balancing, then change the value of the real_ip_header directive in the nginx/configs/addon.d/10-realip.conf file from CF-Connecting-IP to X-Forwarded-For.
- Copy the contents of the services/nginx/.env.compose file and place at the end of the
.envfile - Open the
.envfile and edit the variablesWEBSERVER_IMAGE,WEBSERVER_PORT_HTTP,WEBSERVER_PORT_HTTPS,WEBSERVER_LIMITS_CPU,WEBSERVER_LIMITS_MEMORYandWEBSERVER_RESERVATIONS_MEMORYWEBSERVER_IMAGE: Docker image tag that will be used in its creation through thedocker-build-webservercommand and also used in the execution of the NGINX/Webserver containers
- Use the command to build the image:
make -f Makefile -f services/nginx/Makefile docker-build-webserver
Create Letβs Encrypt certificates
Generating with DNS challenge
- Copy the scripts/envs/renew.env file to the docker root folder(same value as the
DOCKER_PATHvariable in the.envfile)- Use the command to make the copy:
cp scripts/envs/renew.env .
- Use the command to make the copy:
- Open
renew.envfile and edit the following variables:RENEW_CERT_DOMAINS: Domains/subdomains that will be in the certificate (separated by comma)- Some CAs (such as Let's Encrypt) require that domain validation for wildcard domains be done through DNS record modifications, which means that the DNS-01 challenge type must be used. According to Let's Encrypt policy, wildcard identifiers must be validated by DNS-01 challenge, therefore, authorizations corresponding to wildcard identifiers will only offer DNS-01 challenge
RENEW_CERT_COMMAND_TARGET: Command that will be executed on the file in theservices/nginx/Makefilefile, which can be:gen-certs-cloudflare: It uses the cloudflare DNS API to automatically insert the DNS TXTs records and thus generate the certificates- To use this challenge, you must create a file in the
services/nginx/certsfolder namedcloudflare.inicontainingdns_cloudflare_api_token = YOUR_TOKEN_AQUI
- To use this challenge, you must create a file in the
gen-certs: Used for both HTTP and DNS validationWebroot/HTTP:- Used for HTTP challenge
- It should be used after first generating the certificates through DNS challenge, as the domain is not active on the internet so that the challenge can be successfully performed
- Need to set variable
RENEW_CERT_IS_CHALLENGE_WEBROOTtotrueand variableRENEW_CERT_COMMAND_OPTIONStowebroot=yes preferred_challenge=http-01
DNS: Use this validation to generate DNS TXT records and enter manually. The value of the variableRENEW_CERT_COMMAND_OPTIONSshould bemanual=yes preferred_challenge=dns-01
To create the certificates for the first time, as the domain is not active/available on the internet, then it is necessary to use the DNS challenge/plugin manually.
After correctly setting the variables, the renew.env file should look like this:
RENEW_CERT_DOMAINS="*.domainA.tld,domainA.tld,sub.domainB.tld,domainC.tld"
[email protected]
RENEW_CERT_COMMAND_TARGET=gen-certs
RENEW_CERT_COMMAND_OPTIONS="manual=yes \
preferred_challenge=dns-01"
- Replace the domains in the
RENEW_CERT_DOMAINSenvironment variable with the correct domains - Change the value of
RENEW_CERT_EMAILto the email that Let's Encrypt will use to warn of certificate expiration
You must build a custom certbot image, adding the host/server user so that the certificates don't have root but server user permissions:
cd nginx/
docker build \
--tag company/certbot:v1 \
--build-arg TAG_IMAGE="certbot/certbot:v1.16.0" \
--file DockerfileCertbot \
.
# Back to docker root folder
cd ..
The above image was generated with the tag company/certbot:v1. This value must be updated in the WEBSERVER_CERTBOT_IMAGE variable in the .env file.
After, update the variable WEBSERVER_CERTBOT_IMAGE with the name of the newly created image, then run the script ./scripts/renew-certs.sh and follow the steps to create the first certificates for the application.
To see the domains and certificate validity, run the command make -f Makefile -f services/nginx/Makefile get-certs.
Before up the application
Before running the application, you must configure the docker networks for connection between containers
Create the default container networks
-
Two networks are created by default. One for all containers(
compose_network) and one for connectingtraefikto containers for proxy(traefik_network), in the file docker-compose.yml -
To run the
docker-compose --compatibility upcommand to create the networks and then the application containers,traefik,nginxand others to connect, it is necessary first to copy the contents of the file services/traefik/.env.compose and place at the end of the.envfile -
After performing the above step, run the command
docker-compose --compatibility upto create the networks so that the containers can connect and traefik act as a proxy- Run the command
docker network lsand see if there are two networks with the name:${VARIABLE_VALUE_PROJECT_NAME}_networke${VARIABLE_VALUE_PROJECT_NAME}_traefik_network
- Run the command
-
The
traefiknetwork name, must be updated in the traefik/traefik.yml file in theproviders.docker.networkdirective. Replacingcompany_traefik_networkwith the value${VARIABLE_VALUE_PROJECT_NAME}_traefik_network- The
providers.docker.networkdirective of the traefik/traefik.yml file, must have the same value as theTRAEFIK_DOCKER_NETWORKvariable in the.envfile
- The
UP APP Application + NGINX/Webserver
-
If the server is not behind some proxy like cloudflare, then remove the
websecure.forwardedHeaders.trustedIPsdirective -
After the HTTPs certificates are created, run the command
make docker-up context=traefik version=v0 -
Create the
dhparam.pemfile for NGINX to use in thessl_dhparamdirective, with the following command:$ cd services/nginx/certs/ $ openssl dhparam -out dhparam.pem 4096 # Back to docker root folder $ cd ../../../ -
Create
rotatefolder in./../app/storage/logs/for log rotation, usinglogrotate- Use the command to create the folder:
mkdir ./../app/storage/logs/logrotate- Change the
appfolder to the name of the correct folder where the Laravel application is located
- Change the
- Use the command to create the folder:
-
Copy scripts/envs/deploy.env file to docker root folder
- Use the command to make the copy:
cp scripts/envs/deploy.env . - Edit the variable
DOMAINwith the same value of the same variable in the.envfile
- Use the command to make the copy:
-
Edit the services/app/.env.container file, setting the variables for the laravel project, mainly
APP_KEYandAPP_ENV, which are mandatory in theentrypointdocker of the application containerAPP_KEY: If the application key is not set, user sessions and other encrypted data will not be secure!- Use
APP_ENV=productionandAPP_DEBUG=falsefor production, andAPP_ENV=localAPP_DEBUG=truefor development - Configure the variables
PHPFPM_MAX_CHILDREN,PHPFPM_START_SERVERS,PHPFPM_MIN_SPARE_SERVERSandPHPFPM_MAX_SPARE_SERVERSaccording to the capacity of the machine/server
-
See if the domain is correct in the
server_namedirective in the services/nginx/servers/app.conf file -
Run the scripts/deploy-version.sh script to create the Laravel/PHP-FPM and Webserver/NGINX containers
- The script uses
git checkout ./services/nginx/servers, so any changes to the NGINX virtualhost must be committed so that they cannot be lost
- The script uses
-
Access the application's domain and view the website in the browser with
https://yourdomain.tld
Obs: When there are new changes in the code and with that, a new image is built, then, it is necessary to run or rerun the deploy script to update the PHP/APP containers with the new code of the new images.
APP/Laravel with New Relic
- Access the address https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#license-key-create so i can generate a new license
- Open the file services/app/.env.container and edit the section
# # NEW RELIC ENVs- Edit the variable
NEW_RELIC_ENABLEDtotrue - Edit the variable
NEW_RELIC_APPNAMEwhich represents the name of the application that will be rendered in the New Relic panel - Update
NEW_RELIC_LICENSE_KEYvariable with the license value generated previously. 40-character New Relic User Account Key
- Edit the variable
- Run container with command:
make docker-up context=newrelic
NGINX/Webserver with GeoIP2
- Access your user account on the website www.maxmind.com
- If you don't have a registered account, you need to create a new account
- Go to menu "Manage License Keys"
- Click in "Generate new license key"
- In the "License key description" field enter a license name so you can remember
- In the message "Old versions of our GeoIP Update program use a different license key format. Will this key be used for GeoIP Update?", mark the option "No" and click "Confirm"
- On the next page, the Account/User ID and License key credentials will appear
- Open file services/nginx/.env.container
- Set the value of the
WITH_GEOIP2variable totrue - Set the value of the
GEOIPUPDATE_ACCOUNT_IDvariable to the value that appears in Account/User ID - Set the value of the
GEOIPUPDATE_LICENSE_KEYvariable to the value that appears in License key
- Set the value of the
- Open file services/nginx/.env.container
Run Containers
Run Redis Container
-
Change the redis password in the
requirepassdirective in the services/redis/redis.conf file -
Configuration file, uses default port
6379for non TLS/SSL connections, and port6380for encrypted TLS/SSL connections. To generate the certificates to use in the TLS/SSL connection, the following command must be run:./scripts/self-signed-SSL.sh \ --service=redis \ --cert-ca-pass=keypassword \ --cert-server-pass=keypassword \ --cert-server-host=redis.yourdomain.tld \ --with-dhparam- Add
127.0.0.1 redis.yourdomain.tldto/etc/hosts - Change the value of the
tls-key-file-passdirective in the services/redis/redis.conf file to the value of the--cert-server- pass
- Add
-
Run the container using the command:
make docker-up context=redis version=v1 service=redis scale=2 -
To access the Redis container database:
docker exec -it v1_company_redis_1 redis-cli -n 0 -p 6379 -a 'YOUR_REDIS_PASSWORD' --no-auth-warning
Run Authelia Container
-
Uncomment the line containing
authelia-forwardAuth@dockerin the traefik/dynamic/middlewares.yml filetraefikdynamic settings are updated in real time. No need to restart thetraefikcontainer
-
Open the file services/authelia/configs/configuration.yml and configure the following points:
- Search and replace the example domain
yourdomain.tldto the real domain of the company - Change the name of the redis container
v1_company_redis_1
- Search and replace the example domain
-
Edit the passwords in the services/authelia/secrets folder
-
Edit the user and password in the services/authelia/configs/users.yml file. See documentation
-
Run the container using the command:
make docker-up context=authelia version=v0 -
Access Authelia with
https://authelia.yourdomain.tld
Run Netdata Container
-
The settings applied to the Netdata container are found in services/netdata/configs/netdata.conf
- See the settings at https://learn.netdata.cloud/docs/agent/daemon/config
-
Edit the
ExecStartsetting in the Docker service file/lib/systemd/system/docker.serviceto the valueExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375 --containerd=/run/containerd/containerd.sock- Update the new changes with
sudo systemctl daemon-reloadandsudo services restart docker
- Update the new changes with
-
Set to
truethe value of the variableWITH_NETDATAin the./deploy.envfile -
Run the container using the command:
make docker-up context=netdata services=dockerproxy make docker-up context=netdata services=netdata -
Access Netdata with
https://netdata.yourdomain.tld
Run MongoDB Container
-
Run the script to generate the certificates for use in the TLS/SSL connection:
./scripts/self-signed-SSL.sh \ --service=mongodb \ --cert-ca-pass=keypassword \ --cert-server-pass=keypassword \ --cert-server-host=mongodb.yourdomain.tld- Obs: The mongo shell verifies that the hostname (specified in --host option or the connection string) matches the SAN (or, if SAN is not present, the CN) in the certificate presented by the mongod or mongos. If SAN is present, mongo does not match against the CN. If the hostname does not match the SAN (or CN), the mongo shell will fail to connect.
- Add
127.0.0.1 mongodb.yourdomain.tldto/etc/hosts
-
Open the services/mongodb/mongod.conf file and edit the
certificateKeyFilePasswordsetting which should match the--cert-server-passargument of the above script -
Open the file services/mongodb/.env.container and edit the password, replacing
YOUR_MONGODB_ROOT_PASSWORDwith the new password -
Run the container using the command:
make docker-up context=mongodb -
Run the script below to retrieve the full name of the
mongodbcontainer:MONGODB_CONTAINER_NAME=$(docker ps -q --filter name="mongodb" --filter status=running --no-trunc --format="{{.Names}}") -
Recover the external port to connect outside the server:
docker port ${MONGODB_CONTAINER_NAME} 27017/tcp # `0.0.0.0:OUTSIDE_PORT`- To verify that the connection supports TLS in version 1.3, run the command:
openssl s_client -connect 127.0.0.1:OUTSIDE_PORT -tls1_3
- To verify that the connection supports TLS in version 1.3, run the command:
-
To access the database using the container's own mongodb client, run the command:
docker exec -ti ${MONGODB_CONTAINER_NAME} mongo \ --username 'root' \ --authenticationDatabase 'admin' \ --password 'YOUR_MONGODB_ROOT_PASSWORD'-
To create a user, use the following command:
$ use admin $ db.createUser({user: 'app', pwd: 'passw0rd1', roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase"]}) # mongo --username "app" --password "passw0rd1" --authenticationDatabase "admin"
-
-
To access the database using the machine's mongodb client inside or outside the server, run the command:
mongo --tls \ --tlsCAFile ca.pem \ --tlsCertificateKeyFile client.pem \ --host localhost||SERVER_IP||SERVER_DATABASE_DNS \ --port MONGODB_PUBLIC_PORT \ --username 'app||root' \ --authenticationDatabase 'admin' \ --password 'passw0rd1||${MONGO_INITDB_ROOT_PASSWORD}'
Run MySQL Container
-
Run the script to generate the certificates for use in the TLS/SSL connection:
./scripts/self-signed-SSL.sh \ --service=mysql \ --cert-server-host=mysql.yourdomain.tld- Add
127.0.0.1 mysql.yourdomain.tldto/etc/hosts
- Add
-
Open the file services/mysql/my.cnf and edit the MySQL settings
-
Open the services/mysql/.env.container file and edit the environment variable credentials
-
Run the container using the command:
make docker-up context=mysql -
To access the MySQL container database:
mysql -h 127.0.0.1||mysql.yourdomain.tld -P {OUTSIDE_PORT/3306} -uapp -p'YOUR_MYSQL_PASSWORD' \ --ssl-ca=services/mysql/ssl/ca.pem \ --ssl-key=services/mysql/ssl/client-key.pem \ --ssl-cert=services/mysql/ssl/client-cert.pem
Run Portainer Container
- Run the container using the command:
make docker-up context=portainer - Access Portainer with
https://portainer.yourdomain.tld
Run Queue Container
- Open
.env.containerfile and edit as desired:- Set the
CONTAINER_ROLEenvironment variable when running the PHP container so that its value isqueue 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- Many processes running in the Laravel artisan
queue:workfor queue management
- Many processes running in the Laravel artisan
- horizon: Configure the supervisor to run a single Horizon process
artisan horizon- 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
- worker: Configure the supervisor to run many processes in the Laravel command
- Set the
- Environment variables
APP_KEYandAPP_ENVare required when executing the container
Container with PID 1 executed by supervisor to manage processes.
Run the container using the command: make docker-up context=queue
Run Scheduler Container
- Open
.env.containerfile and edit as desired:- Set the
CONTAINER_ROLEenvironment variable when running the PHP container so that its value isscheduler
- Set the
- Container with PID 1 executed by cron
- Environment variables
APP_KEYandAPP_ENVare required when executing the container - Container run as
rootas a cron service request
Running a single scheduling command:
* * * * * /usr/local/bin/php ${REMOTE_SRC}/artisan schedule:run --no-ansi >> ${REMOTE_SRC}/storage/logs/scheduler.log 2>&1
exec /usr/sbin/crond -l 2 -f -L /var/log/cron.log
Run the container using the command: make docker-up context=scheduler
Run GoAccess Container
-
Open file
.envand edit the variableDOCKER_COMPOSE_WEBSERVER_OPTIONS, adding the value of:-f services/goaccess/docker-compose.webserver.yml -
Open file deploy.env(if it exists), and edit the variable
DOCKER_COMPOSE_WEBSERVER_OPTIONS, adding the value of:-f services/goaccess/docker-compose.webserver.yml -
Copy the file services/nginx/servers/additional/goaccess.conf to a folder level, it should be in
services/nginx/servers/goaccess.conf- Edit the
server_name goaccess.yourdomain.tldline, replacingyourdomain.tldwith the correct company domain
- Edit the
-
Copy the contents of the services/goaccess/.env.compose file and place at the end of the
.envfile -
Restart/Recreate the NGINX/Webserver container with the command:
make -f Makefile -f services/nginx/Makefile docker-up-webserver -
Check and edit the GoAccess configuration file as preferred services/goaccess/goaccess.conf
-
Run the container GoAccess using the command:
make docker-up context=goaccess -
Access GoAccess with
https://goaccess.yourdomain.tld
Makefile Commands
Install PHP Composer Dependencies in Project
make -f Makefile -f services/app/Makefile composer-install
Run NPM Commands
make -f Makefile -f services/app/Makefile npm-handle npm_command="npm run prod"
Replace "npm run prod" with "npm anything"
Build the APP/Laravel Image
make -f Makefile -f services/app/Makefile docker-build-app
Run/Recreate APP/Laravel containers
make -f Makefile -f services/app/Makefile docker-up-app
With the following options:
version: Option used to specify a new version other than the currently running containersscale: Total number of containers NGINX will use as HTTP load balancer in theupstreamdirective- After passing these options, it is necessary to run the command
./scripts/loadbalancer-nginx.shso that you can update theapp.conffile of NGINX with the names/version of the new containers
- After passing these options, it is necessary to run the command
up_options: Options that will be passed to theupcommand. By default the options are:--force-recreate --no-build --no-deps --detachoptions: Options that are passed to thedocker-composecommand like--verboseor--log-levelfor example
Run/Recreate NGINX/Webserver containers
make -f Makefile -f services/nginx/Makefile docker-up-webserver
With the following options:
version: Option used to specify a new version other than the currently running containersscale: Total number of containers that will be executed, will be running ready to receive and handle requests throughtraefikup_options: Options that will be passed to theupcommand. By default the options are:--force-recreate --no-build --no-deps --detachoptions: Options that are passed to thedocker-composecommand like--verboseor--log-levelfor example
Build the NGINX/Webserver Image
make -f Makefile -f services/nginx/Makefile docker-build-webserver
Scripts
Important: Before running the scripts/commands below it is necessary:
- Copy the files in the
scripts/envsfolder to the docker root folder - Edit the
COMPOSE_PROJECT_NAMEenvironment variable in thedocker.envfile with the same value as the same variable in the.envfile
./scripts/cron-renew-certs.sh
Use this command to set up a CRON schedule for automatic renewal of Let's Encrypt certificates
To add a schedule in CRON to renew HTTPs certificates every Sunday at 02:00, run the following command:
./scripts/cron-renew-certs.sh --timer=\"0 2 * * MON\" --path=/var/www/docker/ --add
Where:
--timer=: Scheduling expression in CRON--path=: Docker folder path-add: Add a command that will execute ./scripts/renew-certs.sh to CRON which will be executed every time set in the--timeroption
To remove the schedule from CRON, run the command:
./scripts/cron-renew-certs.sh --remove
./scripts/deploy-version.sh
Use this command to update the number of running PHP/Laravel and NGINX/Webserver containers or to update the version of the containers with a new updated PHP/Laravel or NGINX/Webserver image
Before running the script/command it is necessary to update the environment variable DOMAIN in the file deploy.env, which must have the same value as the same variable in the file .env
To create 4 APP/Laravel and 2 Nginx/Webserver containers, run the following command:
./scripts/deploy-version.sh --new-version=v9 --num-nginx-scale=2 --num-php-scale=4
By default, if no option is passed as an argument in the command, then they will have the following values:
--new-version=: Previous version + 1--num-nginx-scale=: Value that is in the variableDOCKER_COMPOSE_WEBSERVER_SCALEof the file services/nginx/.env.compose--num-php-scale=: Value that is in the variableDOCKER_COMPOSE_APP_SCALEof the file services/app/.env.compose
./scripts/loadbalancer-nginx.sh
Use this command to update the
services/nginx/servers/app.conffile or any other (web server, server blocks) in NGINX, with the names of the APP/Laravel containers that will be used in the NGINXupstreamdirective used in HTTP load balancer handling
The script/command has the following options/arguments:
-
--not-reload-nginx: If this option is not passed, then the NGINX processes inside the container will be reloaded, causing updates to the (web server, server blocks).conffiles located inservices/nginx/serversto be published/visible on the internet -
--php-container-name=: Option used so that Docker can filter PHP/Laravel containers with the commanddocker ps --filter name="$PHP_CONTAINER_NAME"- By default the name of PHP/Laravel containers filtered by the docker will be:
^/v([0-9]+)${COMPOSE_PROJECT_NAME}_app_\d+ - This option is only needed when containers are not generated by the ./scripts/deploy-version.sh script or
docker-up-appcommand
- By default the name of PHP/Laravel containers filtered by the docker will be:
-
--nginx-container-name=: Option used so that Docker can filter NGINX/Webserver containers with the commanddocker ps --filter name="$NGINX_CONTAINER_NAME"- By default the name of the NGINX/Webserver containers filtered by the docker will be:
^v\d+${COMPOSE_PROJECT_NAME}_webserver - This option should only be used in the script if the
--not-reload-nginxoption is not passed. Because NGINX containers will have to be retrieved to be updated - This option is only needed when containers are not generated by the ./scripts/deploy-version.sh script or
docker-up-webservercommand
- By default the name of the NGINX/Webserver containers filtered by the docker will be:
-
--loadbalancer-name=: The value of this argument/option will be used to name the NGINXupstreamdirective in the.conffile -
--filename-server=: Name of the.conffile that will be used to edit and add theupstreamdirective with the names of the PHP/Laravel containers- It is only necessary the name of the
.conffile found in theservices/nginx/serversfolder - Before the
serverdirective, it must have the following content so that the file can be updated and the information will be added between the lines###SET_UPSTREAM ###END_SET_UPSTREAM
- It is only necessary the name of the
The following is an example of using the script:
./scripts/loadbalancer-nginx.sh --loadbalancer-name=loadbalancer-xyz --filename-server=site.conf
./scripts/update-app.sh
- Use this command when OPcache is enabled in PHP/Laravel containers and you are also using volumes in the docker in Laravel application with the same PHP/Laravel containers
- In executing this script, a set of artisan commands will also be executed, such as:
route:cache,config:cache,view:cacheandmigrate(if the--force-migrationsoption is passed in script/command)- Also use to automate the project update process on the local machine using GIT
The script contains the following options/arguments:
-
--with-reload-phpfpm: By default GIT updates in the project(git pull), do not update PHP-FPM in containers so that OPcache is also updated, so passing this option will update PHP-FPM processes inside the container, through the signSIGUSR2 -
--force-migrations: By default thephp artisan migrate --forcecommand will not be executed. Passing this option then the script also runsartisan migrateon the project -
--container-name=: Name of the container that will be used in the docker commanddocker ps --filter name="$LARAVEL_CONTAINER_NAME"to run the PHP-FPM process update and also run theartisancommands- By default the name of PHP/Laravel containers filtered by the docker will be:
^/v([0-9]+)${COMPOSE_PROJECT_NAME}_app_\d+ - This option is only needed when containers are not generated by the ./scripts/deploy-version.sh script or
docker-up-appcommand
- By default the name of PHP/Laravel containers filtered by the docker will be:
-
--container-workdir=: Option used in the--workdirargument in thedocker execcommand, which has the same value as the--pathargument, if--container-workdiris not present in the command -
--path=: Absolute path to the folder where the Laravel project is located, so the script can perform a simplecd $WEBPATH_GIT -
--branch=: Name of the GIT branch the script will performgit checkout $BRANCH -
--npm-run=: NPM commands that will run on the machine itself within the Laravel project
The following is an example of using the script:
./scripts/update-app.sh --with-reload-phpfpm --force-migrations --path="/var/www/app" --branch=main
Setup Auto-Renew Let's Encrypt SSL Certificates
- Before generating the certificates it is necessary to configure the
renew.envfile in the docker root folder- Edit the variable
RENEW_CERT_DOMAINS, adding the domains, subdomain, separated by comma that will be generated/renewed - Edit
RENEW_CERT_EMAILvariable for the email that should be sent certificate expiration notification by Let's Encrypt
- Edit the variable
- Let's Encrypt certificates (
cert.pem,chain.pem,fullchain.pemandprivkey.pem) must be in the./services/nginx/certsfolder - There should also be a file called
dhparam.pemin the same folder as the certificates- Use the following command to generate this file:
openssl dhparam -out ./services/nginx/certs/dhparam.pem 4096
- Use the following command to generate this file:
Generate SSL certificates manually
Configure renew.env to generate certificates via HTTP challenge
-
Add the following content to the
renew.envfile:RENEW_CERT_COMMAND_TARGET=gen-certs RENEW_CERT_IS_CHALLENGE_WEBROOT=true RENEW_CERT_COMMAND_OPTIONS="webroot=yes preferred_challenge=http-01" -
Run the
./scripts/renew-certs.shscript and follow the steps of certbot certificate generation
Configure renew.env to generate certificates via DNS challenge
-
Add the following content to the
renew.envfile:RENEW_CERT_COMMAND_TARGET=gen-certs-cloudflare -
Run the
./scripts/renew-certs.shscript and follow the steps of certbot certificate generation
Configure renew.env to generate the certificates via the DNS plugin certbot-dns-cloudflare
-
Add the following content to the
renew.envfile:RENEW_CERT_COMMAND_TARGET=gen-certs-cloudflare -
To use this challenge, you must create a file in the
services/nginx/certsfolder namedcloudflare.inicontainingdns_cloudflare_api_token = YOUR_TOKEN_AQUI -
Run the
./scripts/renew-certs.shscript and follow the steps of certbot certificate generation
Configure CRON to automatically generate SSL certificates
- Configure
renew.envfile with one of the three modes in the above menu - Configure CRON to generate certificates every time according to the scheduling expression through the command
./scripts/cron-renew-certs.sh
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.