Create a docker folder: m2.docker
mdkir m2.docker cd m2.docker
Defining some variables for Docker in .env
#inside .env - please use your own password for [your password] placeholder CONTAINER_PREFIX=m2docker SERVER_NAME=m2.docker SERVER_ALIAS=www.m2.docker DIRECTORY_NAME=m2.docker WEB_USER=techjeffyu WEB_ROOT=/var/www/html MYSQL_DB_HOST=${CONTAINER_PREFIX}_db_1 MYSQL_DATABASE=mage2 MYSQL_ROOT_USERNAME=root MYSQL_ROOT_PASSWORD=[your password] MYSQL_USER=jyu MYSQL_PASSWORD=[your password] DOCKER_EXEC=docker exec DOCKER_EXEC_INTERACTIVE=docker exec -i DOCKER_EXEC_TTY=${DOCKER_EXEC_INTERACTIVE} -t VARNISH_PORT=80
Create Docker configuration file:docker-compose.yml
For this docker, we will use Varnish, Apache, PHP7.1, MySQL5.7 and Redis server.
#docker-compose.yml # https://docs.docker.com/compose/compose-file version: "3.6" # https://docs.docker.com/compose/compose-file/#service-configuration-reference services: varnish: image: meanbee/magento2-varnish:latest environment: - VIRTUAL_HOST=m2.docker - VIRTUAL_PORT=80 - HTTPS_METHOD=noredirect ports: - "80:80" links: - web #custom name web: # https://docs.docker.com/compose/compose-file/#image # https://githheizenberg ub.com/udovicic/echo => https://hub.docker.com/r/udovicic/echo/ image: udovicic/echo:apache-php7.1 # https://docs.docker.com/compose/compose-file/#ports ports: - "8080:80" # https://docs.docker.com/compose/compose-file/#expose expose: - "8080" # https://docs.docker.com/compose/compose-file/#volumes volumes: - ./docker/xdebug.ini:/etc/php/7.1/mods-available/xdebug.ini - ./docker/php.ini:/etc/php/7.1/fpm/php.ini - ./html:/var/www/html # https://docs.docker.com/compose/compose-file/#environment environment: - TERM=xterm-256color - APACHE_RUN_USER=1000 # https://docs.docker.com/compose/compose-file/#network-configuration-reference networks: default: aliases: - ${SERVER_NAME} - ${SERVER_ALIAS} db: # https://hub.docker.com/_/mysql/ image: mysql:5.7 volumes: - ./docker/db/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} redis: # https://hub.docker.com/_/redis/ image: redis:latest
Dockerfile and vcl for Varnish
Dockerfile:
FROM million12/varnish MAINTAINER Ash Smith ENV VCL_CONFIG /data/varnish_1.vcl ENV VARNISHD_PARAMS -p default_ttl=86400 -p default_grace=86400 -p feature=+esi_ignore_https -p feature=+esi_disable_xml_check ADD etc/varnish.vcl /data/varnish_1.vcl
default.vcl
vcl 4.0; backend default { .host = "m2.docker", .port = "80" }
Create etc folder and create varnish.vcl file inside:
#varnish.vcl vcl 4.0; import std; # The minimal Varnish version is 4.0 # For SSL offloading, pass the following header in your proxy server or load balancer: 'SSL-OFFLOADED: https' backend default { .host = "127.0.0.1"; .port = "80"; } sub vcl_recv { # Ensure the true IP is sent onwards. # This was an issue getting xdebug working through varnish # whilst having a proxy infront of varnish (for local docker dev) if (req.http.X-Real-Ip) { set req.http.X-Forwarded-For = req.http.X-Real-Ip; } if (req.method == "PURGE") { if (!req.http.X-Magento-Tags-Pattern) { return (synth(400, "X-Magento-Tags-Pattern header required")); } ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern); return (synth(200, "Purged")); } if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } # We only deal with GET and HEAD by default if (req.method != "GET" && req.method != "HEAD") { return (pass); } # Bypass shopping cart, checkout and search requests if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") { return (pass); } # normalize url in case of leading HTTP scheme and domain set req.url = regsub(req.url, "^http[s]?://", ""); # collect all cookies std.collect(req.http.Cookie); # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") { # No point in compressing these unset req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") { set req.http.Accept-Encoding = "deflate"; } else { # unkown algorithm unset req.http.Accept-Encoding; } } # Remove Google gclid parameters to minimize the cache objects set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA" set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar" set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz" # static files are always cacheable. remove SSL flag and cookie if (req.url ~ "^/(pub/)?(media|static)/.*\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$") { unset req.http.Https; unset req.http.SSL-OFFLOADED; unset req.http.Cookie; } return (hash); } sub vcl_hash { if (req.http.cookie ~ "X-Magento-Vary=") { hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1")); } # For multi site configurations to not cache each other's content if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } # To make sure http users don't see ssl warning if (req.http.SSL-OFFLOADED) { hash_data(req.http.SSL-OFFLOADED); } } sub vcl_backend_response { if (beresp.http.content-type ~ "text") { set beresp.do_esi = true; } if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") { set beresp.do_gzip = true; } # cache only successfully responses and 404s if (beresp.status != 200 && beresp.status != 404) { set beresp.ttl = 0s; set beresp.uncacheable = true; return (deliver); } elsif (beresp.http.Cache-Control ~ "private") { set beresp.uncacheable = true; set beresp.ttl = 86400s; return (deliver); } if (beresp.http.X-Magento-Debug) { set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control; } # validate if we need to cache it and prevent from setting cookie # images, css and js are cacheable by default so we have to remove cookie also if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) { unset beresp.http.set-cookie; if (bereq.url !~ "\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\?|$)") { set beresp.http.Pragma = "no-cache"; set beresp.http.Expires = "-1"; set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; set beresp.grace = 1m; } } # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass if (beresp.ttl <= 0s || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Vary == "*")) { # Mark as Hit-For-Pass for the next 2 minutes set beresp.ttl = 120s; set beresp.uncacheable = true; } return (deliver); } sub vcl_deliver { if (resp.http.X-Magento-Debug) { if (resp.http.x-varnish ~ " ") { set resp.http.X-Magento-Cache-Debug = "HIT"; } else { set resp.http.X-Magento-Cache-Debug = "MISS"; } } else { unset resp.http.Age; } unset resp.http.X-Magento-Debug; unset resp.http.X-Magento-Tags; unset resp.http.X-Powered-By; unset resp.http.Server; unset resp.http.X-Varnish; unset resp.http.Via; unset resp.http.Link; }
Create docker folder
cd .. mkdir docker cd docker touch php.ini touch xdebug.ini
php.ini:
max_execution_time = 18000 max_input_time = 1800 memory_limit = 2048M session.save_path = "/tmp" session.save_handler = files
xdebug.ini:
zend_extension=xdebug.so xdebug.remote_autostart=0 xdebug.remote_enable=1 xdebug.remote_port=9000 xdebug.remote_connect_back=1
Create website folder
cd .. mkdir html
The final folder tree structure looks like
Install Docker Desktop
Mac: Docker Desktop for Mac
Create Docker and Varnish
#please run following commands: ##start docker docker-compose up -d ##View docker containers docker ps ##Stop docker docker-compose stop ##access one of containers docker exec -it [container name] /bin/bash
Create a DNS record in /etc/hosts
#/etc/hosts 127.0.0.1 localhost 127.0.0.1 m2.docker www.m2.docker
Install Magento 2
Just download Magento 2 source code from https://magento.com, and uncompressed the file into html folder. Then launch your favorite browser and type in http://m2.docker. After that just following the command on the screen. You will create a brand new Magento 2 ecommerce website for development or testing.