{"id":3435,"date":"2017-09-12T09:05:50","date_gmt":"2017-09-12T09:05:50","guid":{"rendered":"https:\/\/cloudkul.com\/blog\/?p=3435"},"modified":"2018-07-17T13:06:34","modified_gmt":"2018-07-17T13:06:34","slug":"integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose","status":"publish","type":"post","link":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/","title":{"rendered":"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose"},"content":{"rendered":"<p>If you have been following our Magento 2 Docker architectures series, you are almost there to configure high level architecture for your e-commerce store. Although in all my previous blogs in this series, I have been using Magento 2 only but these docker architecture can be used for other frameworks as well. So before exploring today&#8217;s architecture, let us review our journey so far.<\/p>\n<p>In our previous blogs, we have covered,<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><a href=\"https:\/\/cloudkul.com\/blog\/magento-2-docker-installation\/\"><em><strong>Magento 2 setup on the single Docker container architecture using Dockerfile.<\/strong><\/em><\/a><\/li>\n<li><a href=\"https:\/\/cloudkul.com\/blog\/magento-2-docker-compose\/\"><em><strong>Magento 2 setup on the multi-container Docker architecture utilising Docker containers linking concept with the help of Docker-Compose tool.<\/strong><\/em><\/a><\/li>\n<li><a href=\"https:\/\/cloudkul.com\/blog\/magento-2-and-varnish-cache-integration-with-docker-compose\/\"><em><strong>Magento 2 setup and its integration with Varnish-Cache \u00a0utilising Docker containers linking concepts with the help of Docker-Compose tool.<\/strong><\/em><\/a><\/li>\n<li><a href=\"https:\/\/cloudkul.com\/blog\/understanding-communication-docker-containers\/\"><em><strong>Very brief introduction to Docker networks and Docker containers linking in Default bridge network.<\/strong><\/em><\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>All these above mentioned architecture can be used as per the server set up requirements. But there few things missing from these architectures that might not be needed in beginning but they can be essential need as our e-commerce store grows.<\/p>\n<p>We all have seen that <em><strong>our previous architectures lack SSL and do not have any mechanism to take database backup on the scheduled basi<\/strong><strong>s<\/strong><\/em>. Although we had secured our application code keeping it on our host but database is as important as server code.<\/p>\n<p>So in this blog, in addition to previous setups we will also configure SSL for our Magento 2 store and we will create a bash script that will make regular database backups on our docker hosts. Also as we had discussed in our last blog that we will achieve an extra layer of optimisation, so in this blog we will also integrate Redis-server as well.<\/p>\n<p>&nbsp;<\/p>\n<h2>Introduction to Redis<\/h2>\n<p>&nbsp;<\/p>\n<p>As Varnish-Cache works as a HTTP accelerator, Redis alongside its various features, \u00a0can be used as database cache. Quoting from docs itself,<\/p>\n<p>&nbsp;<\/p>\n<blockquote><p><em><strong>Redis is an open source, BSD licensed, advanced key-value store that can optionally be used in Magento for back end and session storage. It can be used to cache the database resulting in exploitation of less database resources, and provides a tunable persistent cache. It is a good alternative to memcacheD.<\/strong><\/em><\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p>When first time page is loaded, a database is queried on the server. Redis caches the query. Next time other user loads the page the results are provided from the redis without quering the actual database. It implements a persistent object cache (no expiration). An object cache works by caching the SQL queries in memory which are needed to load the web page. When the data of main database server is updatedc,then corresponding key in the redis is invalidated. So it provides the updated data instead of caching the data. If a query is not available in redis, the database provides the result and it adds the result to its cache.<\/p>\n<p><em><strong>Magento supports many backend caches like MemcacheD and APC that are commonly used. However, Redis has become a popular and powerful cache system for Magento and other web applications.<\/strong><\/em><\/p>\n<p>&nbsp;<\/p>\n<h2>Need For Nginx as SSL Termination<\/h2>\n<p>&nbsp;<\/p>\n<p>You all, who are not much familiar with nginx-varnish relationship, might have thought that <em><strong>why we are going to use nginx for SSL instead of configuring SSL with apache2 server itself.<\/strong><\/em> Take a note that, Varnish being a reverse proxy caching server sits in front of apache2 server. Also as Varnish is a HTTP accelerator it cannot deal with HTTPS traffic. <em><strong>So we must deploy a way to direct both HTTP and HTTPS traffic to Varnish cache server which in turn, if needed, forward it apache2 server.<\/strong><\/em><\/p>\n<p>Nginx comes in action here. <em><strong>Nginx serves as a reverse proxy server that receives traffic on port 80 and 443 and then proxy pass it to listening port of Varnish Cache server.<\/strong><\/em><\/p>\n<p>So continuing our legacy of multi-container Docker architecture, <em><strong>we will be using separate containers for apache2 server, mysql-server, varnish-cache server, redis-server and nginx-server (for ssl termination) for its integration with Magento 2 on Ubuntu 16.04.<\/strong><\/em><\/p>\n<p>The main\u00a0directory holding all the files\/directories will be considered as the project name. Custom project name can also be in set docker-compose.yml file. Here\u00a0<em><strong>we are creating separate directories for apache2, mysql-server, redis-server, varnish cache server and nginx server setup that hold their Dockerfile(s) and their associated volumes.<\/strong><\/em><\/p>\n<p>Take a note that: following the same approach,\u00a0<em><strong>Magento 2 files will be placed on our host. As it is a good practice to keep application files on host so that it will not be lost if containers or images get accidentally removed. These magento files will be mapped from host to running docker container<\/strong>.<\/em><\/p>\n<p>We are also using<em><strong> supervisor<\/strong><\/em> to control all five\u00a0of our servers\u00a0in their respective containers. Apart from controlling these servers, supervisor is also running various commands and scripts that will be mentioned later in this blog.<\/p>\n<p>To begin with create a directory on your Ubuntu 16.04 server for this project. Our directory architecture will be something like:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>docker-compose.yml<\/strong><\/li>\n<li><strong>web_server<\/strong><\/li>\n<\/ul>\n<blockquote><p><em>Dockerfile<\/em><\/p>\n<p><em>supervisord.conf<\/em><\/p><\/blockquote>\n<ul>\n<li><strong>\u00a0database_server<\/strong><\/li>\n<\/ul>\n<blockquote><p><em>Dockerfile<\/em><\/p>\n<p><em>mysql.sh<\/em><\/p>\n<p><em>supervisord.conf<\/em><\/p><\/blockquote>\n<ul>\n<li><strong>cache_server<\/strong><\/li>\n<\/ul>\n<blockquote><p>Dockerfile<\/p>\n<p>default.vcl<\/p>\n<p>supervisord.conf<\/p>\n<p>varnish<\/p><\/blockquote>\n<ul>\n<li><strong>redis_server<\/strong><\/li>\n<\/ul>\n<blockquote><p>Dockerfile<\/p>\n<p>supervisord.conf<\/p><\/blockquote>\n<ul>\n<li><strong>ssl_server<\/strong><\/li>\n<\/ul>\n<blockquote><p>Dockerfile<\/p>\n<p>default<\/p>\n<p>nginx.conf<\/p>\n<p>supervisord.conf<\/p><\/blockquote>\n<ul>\n<li><strong>magento2<\/strong><\/li>\n<\/ul>\n<blockquote><p><em>Unarchived Magento 2 files and directories.<\/em><\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p>The<em>\u00a0docker-compose.yml<\/em>\u00a0file is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">version: '3'\r\nservices:\r\n  ssl_server:\r\n   build:\r\n     context: .\/ssl_server\/\r\n   container_name: nginx\r\n   depends_on:\r\n     - web_server\r\n     - cache_server\r\n     - database_server\r\n     - redis_server\r\n   volumes:\r\n     - .\/ssl_server\/supervisord.conf:\/etc\/supervisor\/conf.d\/supervisord.conf\r\n     - .\/ssl_server\/default:\/etc\/nginx\/sites-enabled\/default\r\n     - .\/ssl_server\/nginx.conf:\/etc\/nginx\/nginx.conf\r\n   links:\r\n     - web_server\r\n     - cache_server\r\n     - database_server\r\n     - redis_server\r\n   ports: \r\n     - \"80:80\"\r\n     - \"443:443\"\r\n       \r\n  redis_server:\r\n    build:\r\n      context: .\/redis_server\/\r\n    container_name: redis\r\n    depends_on:\r\n      - web_server\r\n      - cache_server\r\n      - database_server\r\n    volumes:\r\n      - .\/redis_server\/supervisord.conf:\/etc\/supervisor\/conf.d\/supervisord.conf\r\n    links:\r\n      - web_server\r\n      - database_server\r\n\r\n    ports:\r\n      - \"6379:6379\"\r\n\r\n  cache_server:\r\n    build:\r\n      context: .\/cache_server\/\r\n    container_name: varnish\r\n    depends_on:\r\n      - web_server\r\n    volumes:\r\n      - .\/cache_server\/default.vcl:\/etc\/varnish\/default.vcl\r\n      - .\/cache_server\/varnish:\/etc\/default\/varnish\r\n      - .\/cache_server\/supervisord.conf:\/etc\/supervisor\/conf.d\/supervisord.conf\r\n    ports:\r\n      - \"6081:6081\"\r\n      - \"6082:6082\"\r\n    links:\r\n      - web_server\r\n      - database_server\r\n\r\n\r\n  web_server:\r\n    build:\r\n      context: .\/web_server\/\r\n    container_name: apache2\r\n    volumes:\r\n      - .\/magento2:\/var\/www\/html  \r\n      - .\/web_server\/supervisord.conf:\/etc\/supervisor\/conf.d\/supervisord.conf\r\n    ports:\r\n      - \"8080:8080\"\r\n    links:\r\n      - database_server\r\n    \r\n  database_server:\r\n    build:\r\n      context: .\/database_server\/\r\n      args:\r\n        - mysql_password=mention_your_mysql_root_password\r\n        - mysql_database=mention_your_database_name\r\n    container_name: mysql\r\n    volumes: \r\n      - .\/database_server\/supervisord.conf:\/etc\/supervisor\/conf.d\/supervisord.conf\r\n      - .\/database_server\/mysql.sh:\/etc\/mysql.sh\r\n    ports:\r\n      - \"3306:3306\"\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Here in YAML file above, we are defining five services: ssl_server, redis_server, cache_server, web_server and database_server.<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>The ssl_server is associated with Nginx server configuration. Container name is nginx, linked to all the other services and port 80 and 443 is allocated to it. There are three files that are being mapped from host to docker container and &#8220;context&#8221; points to it Dockerfile installing nginx version 1.10.<\/li>\n<li>The redis_server is associated with Redis-server configuration. Container name is redis, linked to web_server and port 6379 is allocated to it. There is\u00a0one file\u00a0being mapped from host to docker and &#8220;context&#8221; points to its Dockerfile installing redis-server.<\/li>\n<li>The\u00a0<i>cache_server<\/i>\u00a0is associated with our\u00a0<em>Varnish cache server<\/em>\u00a0configuration. Container name defined is\u00a0<em>varnish<\/em>, linked to\u00a0<em>web_server<\/em>\u00a0and\u00a0<em>port 6081 &amp; 6082<\/em>\u00a0is allocated to it. There are 3 files that are being mapped from host to docker container and &#8220;context&#8221; points to its Dockerfile installing\u00a0<em>Varnish version 4.1.<\/em><\/li>\n<li>The\u00a0<em>web_server<\/em>\u00a0is associated with our\u00a0<em>apache server<\/em>\u00a0configuration. Container name defined for this service is\u00a0<em>apache2<\/em>, linked to\u00a0<em>database_server<\/em>\u00a0and<em>\u00a0port 8080<\/em>\u00a0is allocated to it. There are\u00a0<em>four volumes or files are being mapped from host to docker container<\/em>\u00a0and \u201ccontext\u201d under \u201cbuild\u201d points to location of its Dockerfile.<\/li>\n<li>Also, the service\u00a0<em>database_server<\/em>\u00a0is associated with\u00a0<em>mysql-server<\/em>. Container name is defined as\u00a0<em>mysql<\/em>\u00a0and\u00a0<em>port 3306<\/em>\u00a0is allocated to it.\u00a0<em><strong>Mysql root password will be passed as build argument<\/strong><\/em>\u00a0and their are\u00a0<em>two volumes\/files mapped from host to docker container<\/em>. Same as\u00a0<em>web_server<\/em>, \u201ccontext\u201d points to location of its Dockerfile installing\u00a0<em>mysql-server-5.7.<\/em><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Lets take a look in our\u00a0<em>web_server\u00a0directory<\/em>. It contains 2 files.\u00a0<em>Dockerfile<\/em>\u00a0is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">FROM ubuntu:16.04\r\n\r\nLABEL maintainer=\"Alankrit Srivastava &lt;alankrit.srivastava256@webkul.com&gt;\"\r\n\r\nRUN apt-get update \\\r\n    &amp;&amp; apt-get -y install apache2 nano mysql-client \\\r\n    &amp;&amp; a2enmod rewrite \\\r\n    &amp;&amp; a2enmod headers \\\r\n    &amp;&amp; export LANG=en_US.UTF-8 \\\r\n    &amp;&amp; apt-get update \\\r\n    &amp;&amp; apt-get install -y software-properties-common \\\r\n    &amp;&amp; apt-get install -y language-pack-en-base \\\r\n    &amp;&amp; LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej\/php \\\r\n    &amp;&amp; apt-get update \\\r\n    &amp;&amp; apt-get -y install php7.1 php7.1-curl php7.1-intl php7.1-gd php7.1-dom php7.1-mcrypt php7.1-iconv php7.1-xsl php7.1-mbstring php7.1-ctype   php7.1-zip php7.1-pdo php7.1-xml php7.1-bz2 php7.1-calendar php7.1-exif php7.1-fileinfo php7.1-json php7.1-mysqli php7.1-mysql php7.1-posix php7.1-tokenizer php7.1-xmlwriter php7.1-xmlreader php7.1-phar php7.1-soap php7.1-mysql php7.1-fpm php7.1-bcmath libapache2-mod-php7.1 \\\r\n    &amp;&amp; sed -i -e\"s\/^memory_limit\\s*=\\s*128M\/memory_limit = 512M\/\" \/etc\/php\/7.1\/apache2\/php.ini \\\r\n    &amp;&amp; rm \/var\/www\/html\/* \\\r\n    &amp;&amp; sed -i \"s\/None\/all\/g\" \/etc\/apache2\/apache2.conf \\\r\n    &amp;&amp; sed -i \"s\/80\/8080\/g\" \/etc\/apache2\/ports.conf \/etc\/apache2\/sites-enabled\/000-default.conf \\\r\n##install supervisor and setup supervisord.conf file\r\n    &amp;&amp; apt-get install -y supervisor \\\r\n    &amp;&amp; mkdir -p \/var\/log\/supervisor\r\nenv APACHE_RUN_USER    www-data\r\nenv APACHE_RUN_GROUP   www-data\r\nenv APACHE_PID_FILE    \/var\/run\/apache2.pid\r\nenv APACHE_RUN_DIR     \/var\/run\/apache2\r\nenv APACHE_LOCK_DIR    \/var\/lock\/apache2\r\nenv APACHE_LOG_DIR     \/var\/log\/apache2\r\nenv LANG               C\r\n\r\nWORKDIR \/var\/www\/html\r\n\r\nCMD [\"\/usr\/bin\/supervisord\"]\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>And at last we have\u00a0<em>supervisord.conf<\/em>\u00a0file that supervisor use to run apache2 server and ownership commands. Its contents are shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">[supervisord]\r\nnodaemon=true\r\n\r\n[program:apache2]\r\ncommand=\/bin\/bash -c \"source \/etc\/apache2\/envvars &amp;&amp; exec \/usr\/sbin\/apache2 -DFOREGROUND\"\r\n\r\n[program:user_permission]\r\ncommand=\/bin\/bash -c \"chown -R www-data: \/var\/www\/\"<\/pre>\n<p>&nbsp;<\/p>\n<p>Moving on to our\u00a0<em>database_server directory,\u00a0<\/em>it contains 3 files.\u00a0<em>Dockerfile<\/em>\u00a0is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">FROM ubuntu:16.04\r\n\r\nLABEL maintainer=\"Alankrit Srivastava &lt;alankrit.srivastava256@webkul.com&gt;\"\r\n\r\nARG mysql_password\r\nARG mysql_database\r\nenv MYSQL_ROOT_PASSWORD ${mysql_password}\r\nenv MYSQL_DATABASE ${mysql_database}\r\n\r\nRUN apt-get update \\\r\n&amp;&amp; echo \"mysql-server-5.7 mysql-server\/root_password password ${mysql_password}\" | debconf-set-selections \\\r\n&amp;&amp; echo \"mysql-server-5.7 mysql-server\/root_password_again password ${mysql_password}\" | debconf-set-selections \\\r\n&amp;&amp; DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-server-5.7 &amp;&amp; \\\r\n    mkdir -p \/var\/lib\/mysql &amp;&amp; \\\r\n    mkdir -p \/var\/run\/mysqld &amp;&amp; \\\r\n    mkdir -p \/var\/log\/mysql &amp;&amp; \\\r\n    touch \/var\/run\/mysqld\/mysqld.sock &amp;&amp; \\\r\n    touch \/var\/run\/mysqld\/mysqld.pid &amp;&amp; \\\r\n    chown -R mysql:mysql \/var\/lib\/mysql &amp;&amp; \\\r\n    chown -R mysql:mysql \/var\/run\/mysqld &amp;&amp; \\\r\n    chown -R mysql:mysql \/var\/log\/mysql &amp;&amp;\\\r\n    chmod -R 777 \/var\/run\/mysqld\/ \\\r\n    &amp;&amp; sed -i -e\"s\/^bind-address\\s*=\\s*127.0.0.1\/bind-address = 0.0.0.0\/\" \/etc\/mysql\/mysql.conf.d\/mysqld.cnf \\\r\n##install supervisor and setup supervisord.conf file\r\n    &amp;&amp; apt-get install -y supervisor nano \\\r\n    &amp;&amp; mkdir -p \/var\/log\/supervisor \r\nCMD [\"\/usr\/bin\/supervisord\"]<\/pre>\n<p>&nbsp;<\/p>\n<p>As we have discussed many times we cannot perform any operation from Dockerfile that requires a particular service to be running.\u00a0<em><strong>As with case of database, we cannot create database from Dockerfile as mysql service is not running. For database and its user creation, we will create a bash script that will run whenever a container will launch, hence creating mentioned database and its user<\/strong><\/em><\/p>\n<p>We are using \u201c<em>mysql.sh<\/em>\u201d as the bash script as mentioned in\u00a0<em>Dockerfile<\/em>. Bash script \u201c<em>msyql.sh<\/em>\u201d resides on our host parallel to\u00a0<em>Dockerfile<\/em>.<\/p>\n<p>Contents of\u00a0<em>mysql.sh<\/em>\u00a0is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">#!\/bin\/bash\r\n\r\nset -u\r\nsleep 4\r\ndatabase_connectivity_check=no\r\nvar=1\r\nwhile [ \"$database_connectivity_check\" != \"mysql\" ]; do\r\n\/etc\/init.d\/mysql start\r\nsleep 2\r\ndatabase_connectivity_check=`mysqlshow --user=root --password=$MYSQL_ROOT_PASSWORD | grep -o mysql`\r\nif [ $var -ge 4 ]; then\r\nexit 1\r\nfi\r\nvar=$((var+1))\r\ndone\r\n\r\n\r\ndatabase_availability_check=`mysqlshow --user=root --password=$MYSQL_ROOT_PASSWORD | grep -ow \"$MYSQL_DATABASE\"`\r\n\r\nif [ \"$database_availability_check\" == \"$MYSQL_DATABASE\" ]; then\r\nexit 1\r\nelse\r\nmysql -u root -p$MYSQL_ROOT_PASSWORD -e \"grant all on *.* to 'root'@'%' identified by '$MYSQL_ROOT_PASSWORD';\"\r\nmysql -u root -p$MYSQL_ROOT_PASSWORD -e \"create database $MYSQL_DATABASE;\"\r\nmysql -u root -p$MYSQL_ROOT_PASSWORD -e \"grant all on $MYSQL_DATABASE.* to 'root'@'%' identified by '$MYSQL_ROOT_PASSWORD';\"\r\nsupervisorctl stop database_creation &amp;&amp; supervisorctl remove database_creation\r\necho \"Database $MYSQL_DATABASE created\"\r\nfi\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Apart from\u00a0<em>mysql.sh<\/em>\u00a0and\u00a0<em>Dockerfile,<\/em>\u00a0we are also mapping\u00a0<em>supervisord.conf file<\/em>. Its contents are shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">[supervisord]\r\nnodaemon=true\r\n \r\n\r\n[program:mysql]\r\ncommand=\/bin\/bash -c \"touch \/var\/run\/mysqld\/mysqld.sock;touch \/var\/run\/mysqld\/mysqld.pid;chown -R mysql:mysql \/var\/lib\/mysql;chown -R mysql:mysql \/var\/run\/mysqld;chown -R mysql:mysql \/var\/log\/mysql;chmod -R 777 \/var\/run\/mysqld\/;\/etc\/init.d\/mysql restart\"\r\n\r\n[program:database_creation]\r\ncommand=\/bin\/bash -c \"chmod a+x \/etc\/mysql.sh; \/etc\/mysql.sh\"<\/pre>\n<p>&nbsp;<\/p>\n<p>Moving on and taking a look on our cache_server directory, It contains 4 files. Dockerfile contents are shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">From ubuntu:16.04\r\n\r\nMAINTAINER Alankrit Srivastava alankrit.srivastava256@webkul.com\r\n\r\n##update server\r\n\r\nRUN apt-get update \\\r\n##install supervisor and setup supervisord.conf file\r\n&amp;&amp; apt-get install -y supervisor \\\r\n&amp;&amp; mkdir -p \/var\/log\/supervisor \\\r\n##install varnish\r\n&amp;&amp; apt-get -y install varnish \\\r\n&amp;&amp; rm \/etc\/varnish\/default.vcl \\\r\n&amp;&amp; rm \/etc\/default\/varnish \r\nEXPOSE 6082 6081\r\nCMD [\"\/usr\/bin\/supervisord\"]<\/pre>\n<p>&nbsp;<\/p>\n<p>We also have server configuration file named\u00a0<em>varnish<\/em>\u00a0whose contents are shown below.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\"># Configuration file for varnish\r\n#\r\n# \/etc\/init.d\/varnish expects the variables $DAEMON_OPTS, $NFILES and $MEMLOCK\r\n# to be set from this shell script fragment.\r\n#\r\n# Note: If systemd is installed, this file is obsolete and ignored.  You will\r\n# need to copy \/lib\/systemd\/system\/varnish.service to \/etc\/systemd\/system\/ and\r\n# edit that file.\r\n\r\n# Should we start varnishd at boot?  Set to \"no\" to disable.\r\nSTART=yes\r\n\r\n# Maximum number of open files (for ulimit -n)\r\nNFILES=131072\r\n\r\n# Maximum locked memory size (for ulimit -l)\r\n# Used for locking the shared memory log in memory.  If you increase log size,\r\n# you need to increase this number as well\r\nMEMLOCK=82000\r\n\r\n# Default varnish instance name is the local nodename.  Can be overridden with\r\n# the -n switch, to have more instances on a single server.\r\n# You may need to uncomment this variable for alternatives 1 and 3 below.\r\n# INSTANCE=$(uname -n)\r\n\r\n# This file contains 4 alternatives, please use only one.\r\n\r\n## Alternative 1, Minimal configuration, no VCL\r\n#\r\n# Listen on port 6081, administration on localhost:6082, and forward to\r\n# content server on localhost:8080.  Use a 1GB fixed-size cache file.\r\n#\r\n# This example uses the INSTANCE variable above, which you need to uncomment.\r\n#\r\n# DAEMON_OPTS=\"-a :6081 \\\r\n#              -T localhost:6082 \\\r\n# \t     -b localhost:8080 \\\r\n# \t     -u varnish -g varnish \\\r\n#            -S \/etc\/varnish\/secret \\\r\n# \t     -s file,\/var\/lib\/varnish\/$INSTANCE\/varnish_storage.bin,1G\"\r\n\r\n\r\n## Alternative 2, Configuration with VCL\r\n#\r\n# Listen on port 6081, administration on localhost:6082, and forward to\r\n# one content server selected by the vcl file, based on the request.\r\n#\r\nDAEMON_OPTS=\"-a :6081 \\\r\n             -T localhost:6082 \\\r\n             -f \/etc\/varnish\/default.vcl \\\r\n             -S \/etc\/varnish\/secret \\\r\n             -s malloc,256m\"\r\n\r\n\r\n## Alternative 3, Advanced configuration\r\n#\r\n# This example uses the INSTANCE variable above, which you need to uncomment.\r\n#\r\n# See varnishd(1) for more information.\r\n#\r\n# # Main configuration file. You probably want to change it :)\r\n# VARNISH_VCL_CONF=\/etc\/varnish\/default.vcl\r\n#\r\n# # Default address and port to bind to\r\n# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify\r\n# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.\r\n# VARNISH_LISTEN_ADDRESS=\r\n# VARNISH_LISTEN_PORT=6081\r\n#\r\n# # Telnet admin interface listen address and port\r\n# VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1\r\n# VARNISH_ADMIN_LISTEN_PORT=6082\r\n#\r\n# # The minimum number of worker threads to start\r\n# VARNISH_MIN_THREADS=1\r\n#\r\n# # The Maximum number of worker threads to start\r\n# VARNISH_MAX_THREADS=1000\r\n#\r\n# # Idle timeout for worker threads\r\n# VARNISH_THREAD_TIMEOUT=120\r\n#\r\n# # Cache file location\r\n# VARNISH_STORAGE_FILE=\/var\/lib\/varnish\/$INSTANCE\/varnish_storage.bin\r\n#\r\n# # Cache file size: in bytes, optionally using k \/ M \/ G \/ T suffix,\r\n# # or in percentage of available disk space using the % suffix.\r\n# VARNISH_STORAGE_SIZE=1G\r\n#\r\n# # File containing administration secret\r\n# VARNISH_SECRET_FILE=\/etc\/varnish\/secret\r\n# \r\n# # Backend storage specification\r\n# VARNISH_STORAGE=\"file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}\"\r\n#\r\n# # Default TTL used when the backend does not specify one\r\n# VARNISH_TTL=120\r\n#\r\n# # DAEMON_OPTS is used by the init script.  If you add or remove options, make\r\n# # sure you update this section, too.\r\n# DAEMON_OPTS=\"-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \\\r\n#              -f ${VARNISH_VCL_CONF} \\\r\n#              -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \\\r\n#              -t ${VARNISH_TTL} \\\r\n#              -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \\\r\n# \t       -S ${VARNISH_SECRET_FILE} \\\r\n#              -s ${VARNISH_STORAGE}\"\r\n#\r\n\r\n\r\n## Alternative 4, Do It Yourself\r\n#\r\n# DAEMON_OPTS=\"\"<\/pre>\n<p>&nbsp;<\/p>\n<p>And most importantly, our Varnish configuration language file. This VCL file is provided by Magento 2 itself and it works perfectly. Its contents are shown below.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">vcl 4.0;\r\n\r\nimport std;\r\n# The minimal Varnish version is 5.0\r\n# For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https'\r\n\r\nbackend default {\r\n    .host = \"apache2\";\r\n    .port = \"8080\";\r\n    .first_byte_timeout = 600s;\r\n}\r\n\r\nacl purge {\r\n    \"localhost\";\r\n}\r\n\r\nsub vcl_recv {\r\n    if (req.method == \"PURGE\") {\r\n        if (client.ip !~ purge) {\r\n            return (synth(405, \"Method not allowed\"));\r\n        }\r\n        # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header\r\n        # has been added to the response in your backend server config. This is used, for example, by the\r\n        # capistrano-magento2 gem for purging old content from varnish during it's deploy routine.\r\n        if (!req.http.X-Magento-Tags-Pattern &amp;&amp; !req.http.X-Pool) {\r\n            return (synth(400, \"X-Magento-Tags-Pattern or X-Pool header required\"));\r\n        }\r\n        if (req.http.X-Magento-Tags-Pattern) {\r\n          ban(\"obj.http.X-Magento-Tags ~ \" + req.http.X-Magento-Tags-Pattern);\r\n        }\r\n        if (req.http.X-Pool) {\r\n          ban(\"obj.http.X-Pool ~ \" + req.http.X-Pool);\r\n        }\r\n        return (synth(200, \"Purged\"));\r\n    }\r\n\r\n    if (req.method != \"GET\" &amp;&amp;\r\n        req.method != \"HEAD\" &amp;&amp;\r\n        req.method != \"PUT\" &amp;&amp;\r\n        req.method != \"POST\" &amp;&amp;\r\n        req.method != \"TRACE\" &amp;&amp;\r\n        req.method != \"OPTIONS\" &amp;&amp;\r\n        req.method != \"DELETE\") {\r\n          \/* Non-RFC2616 or CONNECT which is weird. *\/\r\n          return (pipe);\r\n    }\r\n\r\n    # We only deal with GET and HEAD by default\r\n    if (req.method != \"GET\" &amp;&amp; req.method != \"HEAD\") {\r\n        return (pass);\r\n    }\r\n\r\n    # Bypass shopping cart, checkout and search requests\r\n    if (req.url ~ \"\/checkout\" || req.url ~ \"\/catalogsearch\") {\r\n        return (pass);\r\n    }\r\n\r\n    # Bypass health check requests\r\n    if (req.url ~ \"\/pub\/health_check.php\") {\r\n        return (pass);\r\n    }\r\n\r\n    # Set initial grace period usage status\r\n    set req.http.grace = \"none\";\r\n\r\n    # normalize url in case of leading HTTP scheme and domain\r\n    set req.url = regsub(req.url, \"^http[s]?:\/\/\", \"\");\r\n\r\n    # collect all cookies\r\n    std.collect(req.http.Cookie);\r\n\r\n    # Compression filter. See https:\/\/www.varnish-cache.org\/trac\/wiki\/FAQ\/Compression\r\n    if (req.http.Accept-Encoding) {\r\n        if (req.url ~ \"\\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$\") {\r\n            # No point in compressing these\r\n            unset req.http.Accept-Encoding;\r\n        } elsif (req.http.Accept-Encoding ~ \"gzip\") {\r\n            set req.http.Accept-Encoding = \"gzip\";\r\n        } elsif (req.http.Accept-Encoding ~ \"deflate\" &amp;&amp; req.http.user-agent !~ \"MSIE\") {\r\n            set req.http.Accept-Encoding = \"deflate\";\r\n        } else {\r\n            # unkown algorithm\r\n            unset req.http.Accept-Encoding;\r\n        }\r\n    }\r\n\r\n    # Remove Google gclid parameters to minimize the cache objects\r\n    set req.url = regsuball(req.url,\"\\?gclid=[^&amp;]+$\",\"\"); # strips when QS = \"?gclid=AAA\"\r\n    set req.url = regsuball(req.url,\"\\?gclid=[^&amp;]+&amp;\",\"?\"); # strips when QS = \"?gclid=AAA&amp;foo=bar\"\r\n    set req.url = regsuball(req.url,\"&amp;gclid=[^&amp;]+\",\"\"); # strips when QS = \"?foo=bar&amp;gclid=AAA\" or QS = \"?foo=bar&amp;gclid=AAA&amp;bar=baz\"\r\n\r\n    # Static files caching\r\n    if (req.url ~ \"^\/(pub\/)?(media|static)\/\") {\r\n        # Static files should not be cached by default\r\n        return (pass);\r\n\r\n        # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines\r\n        #unset req.http.Https;\r\n        #unset req.http.X-Forwarded-Proto;\r\n        #unset req.http.Cookie;\r\n    }\r\n\r\n    return (hash);\r\n}\r\n\r\nsub vcl_hash {\r\n    if (req.http.cookie ~ \"X-Magento-Vary=\") {\r\n        hash_data(regsub(req.http.cookie, \"^.*?X-Magento-Vary=([^;]+);*.*$\", \"\\1\"));\r\n    }\r\n\r\n    # For multi site configurations to not cache each other's content\r\n    if (req.http.host) {\r\n        hash_data(req.http.host);\r\n    } else {\r\n        hash_data(server.ip);\r\n    }\r\n\r\n    # To make sure http users don't see ssl warning\r\n    if (req.http.X-Forwarded-Proto) {\r\n        hash_data(req.http.X-Forwarded-Proto);\r\n    }\r\n    \r\n}\r\n\r\nsub vcl_backend_response {\r\n\r\n    set beresp.grace = 3d;\r\n\r\n    if (beresp.http.content-type ~ \"text\") {\r\n        set beresp.do_esi = true;\r\n    }\r\n\r\n    if (bereq.url ~ \"\\.js$\" || beresp.http.content-type ~ \"text\") {\r\n        set beresp.do_gzip = true;\r\n    }\r\n\r\n    # cache only successfully responses and 404s\r\n    if (beresp.status != 200 &amp;&amp; beresp.status != 404) {\r\n        set beresp.ttl = 0s;\r\n        set beresp.uncacheable = true;\r\n        return (deliver);\r\n    } elsif (beresp.http.Cache-Control ~ \"private\") {\r\n        set beresp.uncacheable = true;\r\n        set beresp.ttl = 86400s;\r\n        return (deliver);\r\n    }\r\n\r\n    if (beresp.http.X-Magento-Debug) {\r\n        set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;\r\n    }\r\n\r\n    # validate if we need to cache it and prevent from setting cookie\r\n    if (beresp.ttl &gt; 0s &amp;&amp; (bereq.method == \"GET\" || bereq.method == \"HEAD\")) {\r\n        unset beresp.http.set-cookie;\r\n    }\r\n\r\n   # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass\r\n   if (beresp.ttl &lt;= 0s ||\r\n        beresp.http.Surrogate-control ~ \"no-store\" ||\r\n        (!beresp.http.Surrogate-Control &amp;&amp; beresp.http.Vary == \"*\")) {\r\n        # Mark as Hit-For-Pass for the next 2 minutes\r\n        set beresp.ttl = 120s;\r\n        set beresp.uncacheable = true;\r\n    }\r\n    return (deliver);\r\n}\r\n\r\nsub vcl_deliver {\r\n    if (resp.http.X-Magento-Debug) {\r\n        if (resp.http.x-varnish ~ \" \") {\r\n            set resp.http.X-Magento-Cache-Debug = \"HIT\";\r\n            set resp.http.Grace = req.http.grace;\r\n        } else {\r\n            set resp.http.X-Magento-Cache-Debug = \"MISS\";\r\n        }\r\n    } else {\r\n        unset resp.http.Age;\r\n    }\r\n\r\n    unset resp.http.X-Magento-Debug;\r\n    unset resp.http.X-Magento-Tags;\r\n    unset resp.http.X-Powered-By;\r\n    unset resp.http.Server;\r\n    unset resp.http.X-Varnish;\r\n    unset resp.http.Via;\r\n    unset resp.http.Link;\r\n}\r\n\r\nsub vcl_hit {\r\n    if (obj.ttl &gt;= 0s) {\r\n        # Hit within TTL period\r\n        return (deliver);\r\n    }\r\n    if (std.healthy(req.backend_hint)) {\r\n        if (obj.ttl + 300s &gt; 0s) {\r\n            # Hit after TTL expiration, but within grace period\r\n            set req.http.grace = \"normal (healthy server)\";\r\n            return (deliver);\r\n        } else {\r\n            # Hit after TTL and grace expiration\r\n            return (miss);\r\n        }\r\n    } else {\r\n        # server is not healthy, retrieve from cache\r\n        set req.http.grace = \"unlimited (unhealthy server)\";\r\n        return (deliver);\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Take a note that we have mentioned\u00a0<em>apache2 (apache container name)\u00a0<\/em>for backend host in our default.vcl file as our magento code will be mapped to apache container. Also, we also have supervisor for controlling varnish server. Its contents are shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">[supervisord]\r\nnodaemon=true\r\n\r\n[program:varnish3.0]\r\ncommand=\/bin\/bash -c \"\/usr\/sbin\/varnishd -P \/run\/varnishd.pid -a :6081 -F -T localhost:6082 -f \/etc\/varnish\/default.vcl -S \/etc\/varnish\/secret -s malloc,256m\"<\/pre>\n<p>&nbsp;<\/p>\n<p>Proceeding to redis_server directory, we have Dockerfile as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">From ubuntu:16.04\r\n\r\nMAINTAINER Alankrit Srivastava alankrit.srivastava256@webkul.com\r\n\r\n##update server\r\n\r\nRUN apt-get update \\\r\n&amp;&amp; apt-get install -y locales \\\r\n&amp;&amp; locale-gen en_US.UTF-8 \\\r\n&amp;&amp; export LANG=en_US.UTF-8 \\\r\n&amp;&amp; apt-get update \\\r\n&amp;&amp; apt-get install -y software-properties-common \\\r\n&amp;&amp; LC_ALL=en_US.UTF-8 add-apt-repository -y ppa:chris-lea\/redis-server \\\r\n&amp;&amp; apt-get update \\\r\n&amp;&amp; apt-get -y install redis-server \\\r\n&amp;&amp; sed -i -e\"s\/^bind\\s127.0.0.1\/bind 0.0.0.0\/\" \/etc\/redis\/redis.conf \\\r\n&amp;&amp; chown -R redis: \/var\/log\/redis\/ \\\r\n##install supervisor and setup supervisord.conf file\r\n&amp;&amp; apt-get install -y supervisor \\\r\n&amp;&amp; mkdir -p \/var\/log\/supervisor \r\nCOPY supervisord.conf \/etc\/supervisor\/conf.d\/supervisord.conf\r\nEXPOSE 6379\r\nCMD [\"\/usr\/bin\/supervisord\"]<\/pre>\n<p>&nbsp;<\/p>\n<p>and the supervisord.conf file,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">[supervisord]\r\nnodaemon=true\r\n\r\n[program:redis]\r\ncommand=\/usr\/bin\/redis-server \/etc\/redis\/redis.conf\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>And at last, lets take a look on our ssl_server directory. Its Dockerfile is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">From ubuntu:16.04\r\n\r\nMAINTAINER Alankrit Srivastava alankrit.srivastava256@webkul.com\r\n\r\n##update server\r\n\r\nRUN apt-get update \\\r\n##install nginx\r\n&amp;&amp; apt-get install -y locales \\\r\n&amp;&amp; locale-gen en_US.UTF-8 \\\r\n&amp;&amp; export LANG=en_US.UTF-8 \\\r\n&amp;&amp; apt-get update \\\r\n&amp;&amp; apt-get install -y software-properties-common \\\r\n&amp;&amp; LC_ALL=en_US.UTF-8 add-apt-repository -y ppa:nginx\/stable \\\r\n&amp;&amp; apt-get -y update \\\r\n&amp;&amp; apt-get -y install nginx \\\r\n&amp;&amp; rm \/etc\/nginx\/sites-enabled\/default \\\r\n## Generate self signed certificate\r\n&amp;&amp; cd \/etc\/nginx &amp;&amp; echo -e \"\\n\\n\\n\\n\\n\\n\\n\" | openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout \/etc\/nginx\/cert.key -out \/etc\/nginx\/cert.crt \\\r\n##install supervisor and setup supervisord.conf file\r\n&amp;&amp; apt-get install -y supervisor \\\r\n&amp;&amp; mkdir -p \/var\/log\/supervisor\r\nExpose 80 443\r\n\r\nCMD [\"\/usr\/bin\/supervisord\"]<\/pre>\n<p>&nbsp;<\/p>\n<p>And its default configuration file,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">server {\r\n   listen 80 default_server;\r\n  add_header 'Access-Control-Allow-Origin' '*';\r\n    server_name localhost; ## mention ip address or domain name                      \r\n#    return 302 https:\/\/$server_name$request_uri;\r\n \r\n   location \/ {\r\n    include \/etc\/nginx\/proxy_params;\r\n    proxy_pass http:\/\/varnish:6081;    \r\n    }\r\n}\r\nserver {\r\n listen 443;\r\n  add_header 'Access-Control-Allow-Origin' '*';\r\n  server_name localhost; ## mention ip address or domain name\r\n        ssl on;\r\n        ssl_certificate \/etc\/nginx\/cert.crt;\r\n        ssl_certificate_key \/etc\/nginx\/cert.key;\r\n        ssl_session_timeout 5m;\r\n        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;\r\n        ssl_ciphers \"HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES\";\r\n        ssl_prefer_server_ciphers on;\r\n location \/ {\r\n    include \/etc\/nginx\/proxy_params;\r\n    proxy_pass http:\/\/varnish:6081;\r\n}\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>As you can see that, nginx is listening to port 80 and 443 and forwarding the traffic to varnish container. In our configuration, we have used private SSL certificates. You can use your own certificates and mention their path in default configuration file.<\/p>\n<p>Contents of nginx.conf file is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">user www-data;\r\nworker_processes auto;\r\npid \/run\/nginx.pid;\r\ninclude \/etc\/nginx\/modules-enabled\/*.conf;\r\n\r\nevents {\r\n\tworker_connections 768;\r\n\t# multi_accept on;\r\n}\r\n\r\nhttp {\r\n\r\n\t##\r\n\t# Basic Settings\r\n\t##\r\n\r\n\tsendfile on;\r\n\ttcp_nopush on;\r\n\ttcp_nodelay on;\r\n\tkeepalive_timeout 65;\r\n\ttypes_hash_max_size 2048;\r\n\t# server_tokens off;\r\n\r\n\t# server_names_hash_bucket_size 64;\r\n\t# server_name_in_redirect off;\r\n\r\n\tinclude \/etc\/nginx\/mime.types;\r\n\tdefault_type application\/octet-stream;\r\n\r\n\t##\r\n\t# SSL Settings\r\n\t##\r\n\r\n\tssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE\r\n\tssl_prefer_server_ciphers on;\r\n\r\n\t##\r\n\t# Logging Settings\r\n\t##\r\n\r\n\taccess_log \/var\/log\/nginx\/access.log;\r\n\terror_log \/var\/log\/nginx\/error.log;\r\n\r\n\t##\r\n\t# Gzip Settings\r\n\t##\r\n\r\n\tgzip on;\r\n\tgzip_disable \"msie6\";\r\n\r\n\t# gzip_vary on;\r\n\t# gzip_proxied any;\r\n\t# gzip_comp_level 6;\r\n\t# gzip_buffers 16 8k;\r\n\t# gzip_http_version 1.1;\r\n\t# gzip_types text\/plain text\/css application\/json application\/javascript text\/xml application\/xml application\/xml+rss text\/javascript;\r\n\r\n\r\n\tinclude \/etc\/nginx\/conf.d\/*.conf;\r\n\tinclude \/etc\/nginx\/sites-enabled\/*;\r\n}\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>And its supervisord.conf file,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">[supervisord]\r\nnodaemon=true\r\n\r\n[program:nginx]\r\ncommand=\/usr\/sbin\/nginx -c \/etc\/nginx\/nginx.conf<\/pre>\n<p>&nbsp;<\/p>\n<p>And our last directory is\u00a0<em>magento2 directory.\u00a0<\/em>In our case, we have download Magento 2.2.5 from\u00a0<a href=\"https:\/\/magento.com\/tech-resources\/download\">https:\/\/magento.com\/tech-resources\/download<\/a>\u00a0and unarchived it in magento2 directory.\u00a0<em><strong>This directory will be mapped with \/var\/www\/html directory in apache2 docker container.<\/strong><\/em><\/p>\n<p>After extracting Magento 2 files in the desired directory, our project directory setup will be completed. Now in order to build the images with docker-compose.yml file, go to project parent directory and run command,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker-compose build<\/pre>\n<p>&nbsp;<\/p>\n<p>This command will build up all three images for apache2, mysql and varnish server. To check the built images, run command,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker images<\/pre>\n<p>&nbsp;<\/p>\n<p>Now to run the containers as a part of single project being as mentioned in docker-compose.yml file, run the command:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker-compose up -d<\/pre>\n<p>&nbsp;<\/p>\n<p>Your containers will get running. To list running containers under docker-compose, run command:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker-compose ps\r\n\r\ndocker ps<\/pre>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/cloudkul.com\/blog\/wp-content\/uploads\/2017\/09\/Screenshot-from-2017-09-12-141036.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3442\" src=\"https:\/\/cloudkul.com\/blog\/wp-content\/uploads\/2017\/09\/Screenshot-from-2017-09-12-141036.png\" alt=\"\" width=\"1293\" height=\"376\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><em><strong>Now, your server setup is all ready, now hit your domain name or IP to install Magento 2 store and configure it with Varnish Cache server as we did in\u00a0<a href=\"https:\/\/cloudkul.com\/blog\/magento-2-and-varnish-cache-integration-with-docker-compose\/.\">https:\/\/cloudkul.com\/blog\/magento-2-and-varnish-cache-integration-with-docker-compose\/.<\/a> Also test the Varnish cache using varnishhist tool.<\/strong><\/em><\/p>\n<p><strong>NOTE:-\u00a0<\/strong>Use name or id of the mysql container as database host.<\/p>\n<p>Now, to configure redis-server, go to magento2 directory in your main project directory and open file ~\/app\/etc\/env.php. It will be something just like this,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">&lt;?php\r\nreturn array (\r\n  'backend' =&gt; \r\n  array (\r\n    'frontName' =&gt; 'admin',\r\n  ),\r\n  'crypt' =&gt; \r\n  array (\r\n    'key' =&gt; '03fb403b80643a6a11255d40ac72631a',\r\n  ),\r\n  'session' =&gt; \r\n  array (\r\n    'save' =&gt; 'files',\r\n  ),\r\n  'db' =&gt; \r\n  array (\r\n    'table_prefix' =&gt; '',\r\n    'connection' =&gt; \r\n    array (\r\n      'default' =&gt; \r\n      array (\r\n        'host' =&gt; 'mysql,\r\n        'dbname' =&gt; 'magento_db',\r\n        'username' =&gt; 'magento_user',\r\n        'password' =&gt; 'databasepassword123',\r\n        'active' =&gt; '1',\r\n      ),\r\n    ),\r\n  ),\r\n  'resource' =&gt; \r\n  array (\r\n    'default_setup' =&gt; \r\n    array (\r\n      'connection' =&gt; 'default',\r\n    ),\r\n  ),\r\n  'x-frame-options' =&gt; 'SAMEORIGIN',\r\n  'MAGE_MODE' =&gt; 'default',\r\n  'cache_types' =&gt; \r\n  array (\r\n    'config' =&gt; 1,\r\n    'layout' =&gt; 1,\r\n    'block_html' =&gt; 1,\r\n    'collections' =&gt; 1,\r\n    'reflection' =&gt; 1,\r\n    'db_ddl' =&gt; 1,\r\n    'eav' =&gt; 1,\r\n    'customer_notification' =&gt; 1,\r\n    'full_page' =&gt; 1,\r\n    'config_integration' =&gt; 1,\r\n    'config_integration_api' =&gt; 1,\r\n    'translate' =&gt; 1,\r\n    'config_webservice' =&gt; 1,\r\n  ),\r\n  'install' =&gt; \r\n  array (\r\n    'date' =&gt; 'Thu, 07 Sep 2017 08:17:00 +0000',\r\n  ),\r\n);\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Add following piece of code in the last second line of this file:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">'cache' =&gt; \r\n  array (\r\n    'frontend' =&gt; \r\n    array (\r\n      'default' =&gt; \r\n      array (\r\n        'backend' =&gt; 'Cm_Cache_Backend_Redis',\r\n        'backend_options' =&gt; \r\n        array (\r\n          'server' =&gt; 'redis', \r\n          'port' =&gt; '6379',\r\n          'persistent' =&gt; '',\r\n          'database' =&gt; '0',\r\n          'force_standalone' =&gt; '0',\r\n          'connect_retries' =&gt; '1',\r\n          'read_timeout' =&gt; '10',\r\n          'automatic_cleaning_factor' =&gt; '0',\r\n          'compress_data' =&gt; '1',\r\n          'compress_tags' =&gt; '1',\r\n          'compress_threshold' =&gt; '20480',\r\n          'compression_lib' =&gt; 'gzip',\r\n        ),\r\n      ),\r\n      'page_cache' =&gt; \r\n      array (\r\n        'backend' =&gt; 'Cm_Cache_Backend_Redis',\r\n        'backend_options' =&gt; \r\n        array (\r\n          'server' =&gt; 'redis',\r\n          'port' =&gt; '6379',\r\n          'persistent' =&gt; '',\r\n          'database' =&gt; '1',\r\n          'force_standalone' =&gt; '0',\r\n          'connect_retries' =&gt; '1',\r\n          'read_timeout' =&gt; '10',\r\n          'automatic_cleaning_factor' =&gt; '0',\r\n          'compress_data' =&gt; '0',\r\n          'compress_tags' =&gt; '1',\r\n          'compress_threshold' =&gt; '20480',\r\n          'compression_lib' =&gt; 'gzip',\r\n        ),\r\n      ),\r\n    ),\r\n  ),<\/pre>\n<p>&nbsp;<\/p>\n<p>Please take a note that we have mentioned name of our redis-server container in server value in above code.<\/p>\n<p>Now go to redis-server container and restart the server as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">docker exec -ti redis bash\r\n\r\n\/etc\/init.d\/redis-server restart<\/pre>\n<p>&nbsp;<\/p>\n<p>You can also check if Redis-server is able to set keys or not,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">redis-cli\r\n\r\n127.0.0.1:6379&gt; set mykey KEY\r\nOK\r\n127.0.0.1:6379&gt; get mykey\r\n\"KEY\"\r\n127.0.0.1:6379&gt; exit\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>You can also use &#8216;info&#8217; command to get information and statistics about the server as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">redis-cli info<\/pre>\n<p>&nbsp;<\/p>\n<h2>Backing Up Databases from Mysql Docker Container<\/h2>\n<p>&nbsp;<\/p>\n<p>Our databases inside Docker Containers are as critical as our application code. So in order to keep their backup we schedule a shell script that will take backups of all the databases present in mysql-server container and keep them in archived from on our host.<\/p>\n<p>The database backup bash script is shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">#!\/bin\/bash\r\n\r\nset -u\r\n## Mention your database container name\r\ncontainer_name=mysql\r\n\r\n## Mention mysql root password\r\n\r\nMYSQL_ROOT_PASSWORD=mention_your_mysql_root_password\r\n\r\nDATE=`date +%F-%H-%M-%S`\r\n\r\nfor database in `echo 'show databases;' | docker exec -i mysql mysql --user=root --password=$MYSQL_ROOT_PASSWORD | grep -v Database | grep -v information_schema | grep -v mysql | grep -v performance_schema`\r\ndo\r\necho $database\r\ndocker exec $container_name mysqldump -u root -p$MYSQL_ROOT_PASSWORD $database &gt; $database-$DATE.sql &amp;&amp; tar -zcvf $database-$DATE.tar.gz $database-$DATE.sql &amp;&amp; rm $database-$DATE.sql &amp;&amp; echo \"$database-$DATE.tar.gz has been created on `date`\" &gt;&gt; database_backup.log\r\ndone<\/pre>\n<p>&nbsp;<\/p>\n<p>Now setup the cron to take regular backup.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">crontab -e<\/pre>\n<p>&nbsp;<\/p>\n<p>Add the script as,<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">0 *\/12 * * * bash path_to_script\/db_backup.sh<\/pre>\n<p>&nbsp;<\/p>\n<p>It will take database backups twice a day at interval of 12 hours.<\/p>\n<p>So far we have discussed an optimised architecture of Magento 2 using docker-compose tool. Having very complex and code structure, Magento 2 needs optimisation which we have achieved with Varnish-cache, redis-server cache and also our store is configured with SSL. Please refer to repository\u00a0<a href=\"https:\/\/github.com\/webkul\/magento2-varnish-redis-ssl-docker-compose\">https:\/\/github.com\/webkul\/magento2-varnish-redis-ssl-docker-compose<\/a>\u00a0setup same architecture.<\/p>\n<p>In our later blogs, we explore\u00a0see more applications of docker. Stay tuned.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you have been following our Magento 2 Docker architectures series, you are almost there <a class=\"text-primary\" title=\"read more\" href=\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\">[&#8230;]<\/a><\/p>\n","protected":false},"author":7,"featured_media":3447,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[32,2,35,20,25,1,36],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul\" \/>\n<meta property=\"og:description\" content=\"If you have been following our Magento 2 Docker architectures series, you are almost there [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudkul\" \/>\n<meta property=\"article:published_time\" content=\"2017-09-12T09:05:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-07-17T13:06:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cloudkul.com\/blog\/wp-content\/uploads\/2017\/09\/download-4.png\" \/>\n\t<meta property=\"og:image:width\" content=\"848\" \/>\n\t<meta property=\"og:image:height\" content=\"422\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alankrit Srivastava\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\",\"url\":\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\",\"name\":\"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul\",\"isPartOf\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/#website\"},\"datePublished\":\"2017-09-12T09:05:50+00:00\",\"dateModified\":\"2018-07-17T13:06:34+00:00\",\"author\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16\"},\"breadcrumb\":{\"@id\":\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudkul.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#website\",\"url\":\"https:\/\/cloudkul.com\/blog\/\",\"name\":\"Cloudkul\",\"description\":\"Host your eCommerce Store on AWS with Optimized Performance\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudkul.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16\",\"name\":\"Alankrit Srivastava\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g\",\"caption\":\"Alankrit Srivastava\"},\"description\":\"DevOps Manager at Webkul Software Privated Limited\",\"sameAs\":[\"http:\/\/cloudkul.com\"],\"url\":\"https:\/\/cloudkul.com\/blog\/author\/alankrit-srivastava256\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/","og_locale":"en_US","og_type":"article","og_title":"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul","og_description":"If you have been following our Magento 2 Docker architectures series, you are almost there [...]","og_url":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/","og_site_name":"Cloudkul","article_published_time":"2017-09-12T09:05:50+00:00","article_modified_time":"2018-07-17T13:06:34+00:00","og_image":[{"width":848,"height":422,"url":"https:\/\/cloudkul.com\/blog\/wp-content\/uploads\/2017\/09\/download-4.png","type":"image\/png"}],"author":"Alankrit Srivastava","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/","url":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/","name":"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose - Cloudkul","isPartOf":{"@id":"https:\/\/cloudkul.com\/blog\/#website"},"datePublished":"2017-09-12T09:05:50+00:00","dateModified":"2018-07-17T13:06:34+00:00","author":{"@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16"},"breadcrumb":{"@id":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/cloudkul.com\/blog\/integrate-magento-2-varnish-cache-redis-server-ssl-termination-using-docker-compose\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudkul.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Integrate Magento 2 with Varnish-Cache and Redis-Server with SSL Termination using Docker-Compose"}]},{"@type":"WebSite","@id":"https:\/\/cloudkul.com\/blog\/#website","url":"https:\/\/cloudkul.com\/blog\/","name":"Cloudkul","description":"Host your eCommerce Store on AWS with Optimized Performance","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudkul.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/fc06bfd7f18d9a606dd94062d205af16","name":"Alankrit Srivastava","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudkul.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/955c3dda2678272c436c5153832e401f?s=96&d=https%3A%2F%2Fs.gravatar.com%2Favatar%2F6148c37469011bc2f8e491ca8f5de495%3Fs%3D80&r=g","caption":"Alankrit Srivastava"},"description":"DevOps Manager at Webkul Software Privated Limited","sameAs":["http:\/\/cloudkul.com"],"url":"https:\/\/cloudkul.com\/blog\/author\/alankrit-srivastava256\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3435"}],"collection":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/comments?post=3435"}],"version-history":[{"count":17,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3435\/revisions"}],"predecessor-version":[{"id":3737,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/posts\/3435\/revisions\/3737"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/media\/3447"}],"wp:attachment":[{"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/media?parent=3435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/categories?post=3435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudkul.com\/blog\/wp-json\/wp\/v2\/tags?post=3435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}