To avoid the pain of setting up Let's Encrypt SSL and to work with a better load balancer / reverse proxy I decided to do a Laradock & Traefik setup. And I must say I have been pleasantly surprised so far!
Docker Base
As usual I use my Docker Base . I did do a small tweak so we can use Apache htpasswd for basic user authentication for Traefik console. With the Docker Base Ansible package
- Docker,
- Docker Compose,
- a UFW basic firewall setup and
- sudo user
are added on the fly. So you do not have to worry about a setup with a missing sudo user, Docker or Docker Compose and a basic firewall.
DNS
Do make sure you have the domains you want to use directing to the ip address of your server. In my case I have the DNS for larastud.io managed by Digital Ocean and there under network I added an A and AAA record for both the sub domain and FQDN.
LSDock
Then I git cloned my Laradock repo . It contains all Laradock goodies as well as a new traefik directory and several extra Docker Compose files. The production file we will not use here setting things up with SSL using Certbot, but the one starting with Traefik. It will also need some tweaks
Traefik Configuration
I then tweaked the .toml file (htpasswd password and email address docktored). This is the Traefik configuration file where you add the entry points and Let’s Encrypt ACME stuff:
Traefik .toml file:
debug = false logLevel = "ERROR" defaultEntryPoints = ["http", "https"] [api] dashboard = true entrypoint = "webentry" [entrypoints] #... # https://docs.traefik.io/configuration/api/#authentication # sudo apt-get install apache2-utils # htpasswd -nb admin secure_password [entrypoints.webentry] address = ":8080" [entrypoints.webentry.auth] [entrypoints.webentry.auth.basic] users = ["admin:key"] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [acme] email = "me@gmail.com" storage = "acme.json" entryPoint = "https" onHostRule = true onDemand = false [acme.httpChallenge] entryPoint = "http" [[acme.domains]] main = "larastud.io" sub = "monitor.larastud.io"
As you can see I also added authentication. Password generated with htpasswd . The Apache utils have already been generated using Docker Base so no need to install those again.
.Env
I also made sure Laradock .env file was added. One with the new Traefik variables
### TRAEFIK ################################################# TRAEFIK_HOST_HTTP_PORT=80 TRAEFIK_HOST_HTTPS_PORT=443
You can use the example one and tweak the passwords and or user names for MariaDB and such. Just add the rules for Traefik as well.
Launch Containers
Then I launched the containers:
docker-compose -f traefik-docker-compose.yml up -d
using this docker-compose file which is also in the lsdock repo:
version: '3' networks: frontend: driver: ${NETWORKS_DRIVER} backend: driver: ${NETWORKS_DRIVER} volumes: redis: driver: ${VOLUMES_DRIVER} mariadb: driver: ${VOLUMES_DRIVER} services: ### Workspace Utilities ################################## workspace: build: context: ./workspace args: - LARADOCK_PHP_VERSION=${PHP_VERSION} - LARADOCK_PHALCON_VERSION=${PHALCON_VERSION} - INSTALL_SUBVERSION=${WORKSPACE_INSTALL_SUBVERSION} - INSTALL_XDEBUG=${WORKSPACE_INSTALL_XDEBUG} - INSTALL_PHPDBG=${WORKSPACE_INSTALL_PHPDBG} - INSTALL_BLACKFIRE=${INSTALL_BLACKFIRE} - INSTALL_SSH2=${WORKSPACE_INSTALL_SSH2} - INSTALL_GMP=${WORKSPACE_INSTALL_GMP} - INSTALL_SOAP=${WORKSPACE_INSTALL_SOAP} - INSTALL_LDAP=${WORKSPACE_INSTALL_LDAP} - INSTALL_IMAP=${WORKSPACE_INSTALL_IMAP} - INSTALL_MONGO=${WORKSPACE_INSTALL_MONGO} - INSTALL_AMQP=${WORKSPACE_INSTALL_AMQP} - INSTALL_PHPREDIS=${WORKSPACE_INSTALL_PHPREDIS} - INSTALL_MSSQL=${WORKSPACE_INSTALL_MSSQL} - INSTALL_NODE=${WORKSPACE_INSTALL_NODE} - NPM_REGISTRY=${WORKSPACE_NPM_REGISTRY} - INSTALL_YARN=${WORKSPACE_INSTALL_YARN} - INSTALL_NPM_GULP=${WORKSPACE_INSTALL_NPM_GULP} - INSTALL_NPM_BOWER=${WORKSPACE_INSTALL_NPM_BOWER} - INSTALL_NPM_VUE_CLI=${WORKSPACE_INSTALL_NPM_VUE_CLI} - INSTALL_DRUSH=${WORKSPACE_INSTALL_DRUSH} - INSTALL_DRUPAL_CONSOLE=${WORKSPACE_INSTALL_DRUPAL_CONSOLE} - INSTALL_AEROSPIKE=${WORKSPACE_INSTALL_AEROSPIKE} - AEROSPIKE_PHP_REPOSITORY=${AEROSPIKE_PHP_REPOSITORY} - INSTALL_V8JS=${WORKSPACE_INSTALL_V8JS} - COMPOSER_GLOBAL_INSTALL=${WORKSPACE_COMPOSER_GLOBAL_INSTALL} - COMPOSER_REPO_PACKAGIST=${WORKSPACE_COMPOSER_REPO_PACKAGIST} - INSTALL_WORKSPACE_SSH=${WORKSPACE_INSTALL_WORKSPACE_SSH} - INSTALL_LARAVEL_ENVOY=${WORKSPACE_INSTALL_LARAVEL_ENVOY} - INSTALL_LARAVEL_INSTALLER=${WORKSPACE_INSTALL_LARAVEL_INSTALLER} - INSTALL_DEPLOYER=${WORKSPACE_INSTALL_DEPLOYER} - INSTALL_PRESTISSIMO=${WORKSPACE_INSTALL_PRESTISSIMO} - INSTALL_LINUXBREW=${WORKSPACE_INSTALL_LINUXBREW} - INSTALL_MC=${WORKSPACE_INSTALL_MC} - INSTALL_SYMFONY=${WORKSPACE_INSTALL_SYMFONY} - INSTALL_PYTHON=${WORKSPACE_INSTALL_PYTHON} - INSTALL_IMAGE_OPTIMIZERS=${WORKSPACE_INSTALL_IMAGE_OPTIMIZERS} - INSTALL_IMAGEMAGICK=${WORKSPACE_INSTALL_IMAGEMAGICK} - INSTALL_TERRAFORM=${WORKSPACE_INSTALL_TERRAFORM} - INSTALL_DUSK_DEPS=${WORKSPACE_INSTALL_DUSK_DEPS} - INSTALL_PG_CLIENT=${WORKSPACE_INSTALL_PG_CLIENT} - INSTALL_PHALCON=${WORKSPACE_INSTALL_PHALCON} - INSTALL_SWOOLE=${WORKSPACE_INSTALL_SWOOLE} - INSTALL_LIBPNG=${WORKSPACE_INSTALL_LIBPNG} - INSTALL_IONCUBE=${WORKSPACE_INSTALL_IONCUBE} - INSTALL_MYSQL_CLIENT=${WORKSPACE_INSTALL_MYSQL_CLIENT} - PUID=${WORKSPACE_PUID} - PGID=${WORKSPACE_PGID} - CHROME_DRIVER_VERSION=${WORKSPACE_CHROME_DRIVER_VERSION} - NODE_VERSION=${WORKSPACE_NODE_VERSION} - YARN_VERSION=${WORKSPACE_YARN_VERSION} - DRUSH_VERSION=${WORKSPACE_DRUSH_VERSION} - TZ=${WORKSPACE_TIMEZONE} - BLACKFIRE_CLIENT_ID=${BLACKFIRE_CLIENT_ID} - BLACKFIRE_CLIENT_TOKEN=${BLACKFIRE_CLIENT_TOKEN} volumes: - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER} extra_hosts: - "dockerhost:${DOCKER_HOST_IP}" # ports: # - "${WORKSPACE_SSH_PORT}:22" tty: true environment: - PHP_IDE_CONFIG=${PHP_IDE_CONFIG} networks: - frontend - backend labels: - traefik.enable=false ### PHP-FPM ############################################## php-fpm: build: context: ./php-fpm args: - LARADOCK_PHP_VERSION=${PHP_VERSION} - LARADOCK_PHALCON_VERSION=${PHALCON_VERSION} - INSTALL_XDEBUG=${PHP_FPM_INSTALL_XDEBUG} - INSTALL_PHPDBG=${PHP_FPM_INSTALL_PHPDBG} - INSTALL_BLACKFIRE=${INSTALL_BLACKFIRE} - INSTALL_SSH2=${PHP_FPM_INSTALL_SSH2} - INSTALL_SOAP=${PHP_FPM_INSTALL_SOAP} - INSTALL_IMAP=${PHP_FPM_INSTALL_IMAP} - INSTALL_MONGO=${PHP_FPM_INSTALL_MONGO} - INSTALL_AMQP=${PHP_FPM_INSTALL_AMQP} - INSTALL_MSSQL=${PHP_FPM_INSTALL_MSSQL} - INSTALL_ZIP_ARCHIVE=${PHP_FPM_INSTALL_ZIP_ARCHIVE} - INSTALL_BCMATH=${PHP_FPM_INSTALL_BCMATH} - INSTALL_GMP=${PHP_FPM_INSTALL_GMP} - INSTALL_PHPREDIS=${PHP_FPM_INSTALL_PHPREDIS} - INSTALL_MEMCACHED=${PHP_FPM_INSTALL_MEMCACHED} - INSTALL_OPCACHE=${PHP_FPM_INSTALL_OPCACHE} - INSTALL_EXIF=${PHP_FPM_INSTALL_EXIF} - INSTALL_AEROSPIKE=${PHP_FPM_INSTALL_AEROSPIKE} - AEROSPIKE_PHP_REPOSITORY=${AEROSPIKE_PHP_REPOSITORY} - INSTALL_MYSQLI=${PHP_FPM_INSTALL_MYSQLI} - INSTALL_PGSQL=${PHP_FPM_INSTALL_PGSQL} - INSTALL_PG_CLIENT=${PHP_FPM_INSTALL_PG_CLIENT} - INSTALL_INTL=${PHP_FPM_INSTALL_INTL} - INSTALL_GHOSTSCRIPT=${PHP_FPM_INSTALL_GHOSTSCRIPT} - INSTALL_LDAP=${PHP_FPM_INSTALL_LDAP} - INSTALL_PHALCON=${PHP_FPM_INSTALL_PHALCON} - INSTALL_SWOOLE=${PHP_FPM_INSTALL_SWOOLE} - INSTALL_IMAGE_OPTIMIZERS=${PHP_FPM_INSTALL_IMAGE_OPTIMIZERS} - INSTALL_IMAGEMAGICK=${PHP_FPM_INSTALL_IMAGEMAGICK} - INSTALL_CALENDAR=${PHP_FPM_INSTALL_CALENDAR} - INSTALL_FAKETIME=${PHP_FPM_INSTALL_FAKETIME} - INSTALL_IONCUBE=${PHP_FPM_INSTALL_IONCUBE} - INSTALL_YAML=${PHP_FPM_INSTALL_YAML} volumes: - ./php-fpm/php${PHP_VERSION}.ini:/usr/local/etc/php/php.ini - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER} expose: - "9000" extra_hosts: - "dockerhost:${DOCKER_HOST_IP}" environment: - PHP_IDE_CONFIG=${PHP_IDE_CONFIG} - FAKETIME=${PHP_FPM_FAKETIME} restart: unless-stopped depends_on: - workspace networks: - backend labels: - traefik.enable=false ### PHP Worker ############################################ php-worker: build: context: ./php-worker args: - PHP_VERSION=${PHP_VERSION} - INSTALL_PGSQL=${PHP_WORKER_INSTALL_PGSQL} - INSTALL_BCMATH=${PHP_WORKER_INSTALL_BCMATH} - INSTALL_SOAP=${PHP_WORKER_INSTALL_SOAP} - INSTALL_ZIP_ARCHIVE=${PHP_WORKER_INSTALL_ZIP_ARCHIVE} volumes: - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER} - ./php-worker/supervisord.d:/etc/supervisord.d restart: unless-stopped depends_on: - workspace extra_hosts: - "dockerhost:${DOCKER_HOST_IP}" networks: - backend labels: - traefik.enable=false ### NGINX Server ######################################### nginx: build: context: ./nginx args: - PHP_UPSTREAM_CONTAINER=${NGINX_PHP_UPSTREAM_CONTAINER} - PHP_UPSTREAM_PORT=${NGINX_PHP_UPSTREAM_PORT} - CHANGE_SOURCE=${CHANGE_SOURCE} volumes: - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER} - ${NGINX_HOST_LOG_PATH}:/var/log/nginx - ${NGINX_SITES_PATH}:/etc/nginx/sites-available - ${NGINX_SSL_PATH}:/etc/nginx/ssl # ports: # - "${NGINX_HOST_HTTP_PORT}:80" # - "${NGINX_HOST_HTTPS_PORT}:443" restart: unless-stopped depends_on: - php-fpm networks: - frontend - backend labels: - traefik.backend=nginx - traefik.frontend.rule=Host:larastud.io - traefik.docker.network=frontend - traefik.port=80 ### MariaDB ############################################## mariadb: build: ./mariadb volumes: - ${DATA_PATH_HOST}/mariadb:/var/lib/mysql - ${MARIADB_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d # https://github.com/laradock/laradock/issues/571#issuecomment-280874407 # https://github.com/laradock/laradock/pull/339/commits/ec3ebb9701de24d9c64d567c786a1601a5626f2d # ports: # - "${MARIADB_PORT}:3306" restart: unless-stopped environment: - MYSQL_DATABASE=${MARIADB_DATABASE} - MYSQL_USER=${MARIADB_USER} - MYSQL_PASSWORD=${MARIADB_PASSWORD} - MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} networks: - backend labels: - traefik.enable=false ### Redis ################################################ redis: build: ./redis volumes: - ${DATA_PATH_HOST}/redis:/data # ports: # - "${REDIS_PORT}:6379" restart: unless-stopped networks: - backend labels: - traefik.enable=false ### TRAEFIK ######################################### traefik: build: context: ./traefik command: --docker volumes: - /var/run/docker.sock:/var/run/docker.sock ports: - "${TRAEFIK_HOST_HTTP_PORT}:80" - "${TRAEFIK_HOST_HTTPS_PORT}:443" networks: - frontend - backend labels: - traefik.backend=traefik - traefik.frontend.rule=Host:monitor.larastud.io - traefik.port=8080
Immediately monitor.larastud.io and larastud.io started working with Let’s Encrypt SSL certificates. Only the main site showed an error 500. This was because I had not run composer yet nor had I added the Laravel .env file. So added .env and then got into workspace to run composer:
docker-compose exec --user=laradock workspace bash laradock@3d330cdb93ea:/var/www$ composer install
After that the main site was loading as well. Then I wondered about the nginx.conf… The set up I had with default was no longer being used now was it?. Well the SSl with self signed certificate was no longer being used. The proper root path was still being used. As for PHP, purrin’ like a kitten. Added a quick PHP Info and saw it in all its glory.