

Web developer, Linux enthusiast, father and husband. I like to write about programming.
When I just started developing PHP applications I used Mamp or Xamp to set up a local Lamp stack. Later this became Vagrant in combination with VirtualBox and eventually Docker.
The main advantage of Docker is portability, performance and it is scalable. This pays off, especially when you work in a team.
When using commerce with Magento 2 it is possible to use the Magento Cloud Docker environment.
You may already have some experience with Docker, but it might help as a mnemonic. If this is completely new to you, it is good to read the following.
The main difference between Docker and a VM is mainly the architecture between the two. A VM is a computer software that mimics a real computer. For this he uses a hypervision — also called a "guest machine".
A hypervision can be a piece of software, firmware or hardware that the VM runs on. The hypervison itself runs on a real computer, this is called the "host machine".
The hypervison has a complete virtualization stack, such as network adapters, storage and CPU with its own operating system to run programs.
Containers and VM are similar, but the main difference between containers and a VM is that containers use the host computer kernel, which in turn shares it with other containers.
A container does not need a complete virtualization stack and its own os to run programs.
However, if you want to delve deeper into the difference between docker and a VM, I recommend reading "A Beginner-Friendly Introduction to Containers, VMs and Docker".
For those who have already worked with Docker, you may recognize the time it can take to set up a working Docker environment. Especially if you don't have a DevOps team or sysadmin to set this up.
Now there are existing Docker environments for Magento 2 that you can find on Github, but my experience and that of my team was not always flawless. Often they were not up to date, they did not work as you would like, or you had to make adjustments yourself. Eventually we ended up with Warden.
Warden is a CLI utility that makes installing a Magento environment effortless even if you have little or no knowledge of Docker. According to the Warden documentation:
Warden is a CLI utility for orchestrating Docker based developer environments, and enables multiple local environments to run simultaneously without port conflicts via the use of a few centrally run services for proxying requests into the correct environment’s containers.
This means that you can effortlessly run different local environments at the same time without conflicting with each other. Warden has the following features:
To install Warden you first need Docker. Furthermore, it only runs on Linux or macOS - as far as I know there is no way to run warden on Windows yet. If you are running macOS, I recommend installing Docker Desktop for Mac. For Linux, that's Docker for Linux. You also need docker compose and Mutagen 0.11.4 or higher.
Install Docker
First make sure you have a package manager like Homebrew for macOS to install Docker Desktop for Mac, then run:
brew cask install docker
This installs the following: Docker Desktop, Docker Community Edition, Docker CE.
To install Docker for Linux you can use Docker engine.
With snapcraft:
sudo snap install docker
With apt-get:
sudo apt-get install docker-ce docker-ce-cli containerd.io
Install warden
brew install davidalger/warden/warden
warden svc up
Warden Global Services
Now that you have installed warden you can start warden by running:
warden up
This starts Warden's Global services. See
docker ps
❯ warden up
Creating network "warden" with the default driver
Creating traefik ... done
Creating portainer ... done
Creating tunnel ... done
Creating dnsmasq ... done
This includes traefik, portainer, dnsmasq and mailhog. This will give you access to the GUI and can be reached by going to the following urls:
Warden has some useful commands that you can use to work with warden.
start warden:
warden up
stop warden:
warden down
start warden environment
warden env start
stop warden environment
warden env down
SSH in warden environment
warden shell
Run a command in Warden environment
warden env exec php-fpm bin/magento
Open MySQL session
warden db connect -A
Show PHP logs
warden env logs --tail 0 -f php-fpm php-debug
It only takes a few steps to set up a Warden environment for Magento 2.
Configure your Magento Marketplace credentials
composer global config http-basic.repo.magento.com <username> <password>
Let’s start by creating a project.
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition --ignore-platform-reqs example && cd example/
Add a .env file to your project.
warden env-init <example> magento2
This creates an .env file in the root of your project. Want to customize your PHP version for example, you can do it here.
This .env file is used for the warden env commands. See warden env -h for more details.
You can create an SSL certificate as follows:
warden sign-certificate example.test
Make sure the name matches “TRAEFIK_DOMAIN” which is in your .env
Now run:
warden env up -d
When you run this for the first time, the following are created:
This also starts the Mutagen sync session that syncs your files to your Docker container.
❯ warden env up -d
Creating network "example_default" with the default driver
Creating example_elasticsearch_1 ... done
Creating example_rabbitmq_1 ... done
Creating example_db_1 ... done
Creating example_redis_1 ... done
Creating example_mailhog_1 ... done
Creating example_php-fpm_1 ... done
Creating example_php-debug_1 ... done
Creating example_nginx_1 ... done
Creating example_varnish_1 ... done
Connecting traefik to example_default network
Connecting tunnel to example_default network
Starting example_redis_1 ... done
Starting example_elasticsearch_1 ... done
Starting example_db_1 ... done
Starting example_rabbitmq_1 ... done
Starting example_mailhog_1 ... done
Recreating example_php-fpm_1 ... done
Recreating example_php-debug_1 ... done
Recreating example_nginx_1 ... done
Recreating example_varnish_1 ... done
Created session sync_CQ4ZVwER7plFTM0pOaMGrFUnhopfXMcKksgfpPfNPJK
Waiting for initial synchronization to complete
...................................................................
Files in the webroot are synced into the container using a Mutagen sync session with the exception of pub/media which remains mounted using a delegated mount.
Then run your docker ps to see if everything is running.
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
230ac50b96e9 wardenenv/varnish:6.0 "/bin/sh -c 'envsubs..." 2 minutes ago Up 2 minutes 80/tcp example_varnish_1
c366710da20c wardenenv/nginx:1.16 "/bin/sh -c 'envsubs..." 2 minutes ago Up 2 minutes 80/tcp example_nginx_1
706638d284aa wardenenv/php-fpm:7.3-magento2-debug "docker-entrypoint p..." 2 minutes ago Up 2 minutes 9000/tcp example_php-debug_1
06431cb0868a wardenenv/php-fpm:7.3-magento2 "docker-entrypoint p..." 2 minutes ago Up 2 minutes 9000/tcp example_php-fpm_1
100e10dfc2a8 wardenenv/redis:5.0 "docker-entrypoint.s..." 2 minutes ago Up 2 minutes 6379/tcp example_redis_1
1959774622b3 wardenenv/mariadb:10.3 "docker-entrypoint.s..." 2 minutes ago Up 2 minutes 3306/tcp example_db_1
713ff0174084 wardenenv/mailhog:1.0 "MailHog" 2 minutes ago Up 2 minutes 1025/tcp, 8025/tcp example_mailhog_1
9749c6aa8793 wardenenv/elasticsearch:6.8 "/usr/local/bin/dock..." 2 minutes ago Up 2 minutes 9200/tcp, 9300/tcp example_elasticsearch_1
b34f4a4c97ec wardenenv/rabbitmq:3.7 "docker-entrypoint.s..." 2 minutes ago Up 2 minutes 4369/tcp, 5671-5672/tcp, 15671-15672/tcp, 25672/tcp example_rabbitmq_1
29f678215b8c traefik:2.1 "/entrypoint.sh trae..." 19 hours ago Up 2 minutes 127.0.0.1:80->80/tcp, 127.0.0.1:443->443/tcp traefik
aa9fc5a1c1c1 portainer/portainer "/portainer" 19 hours ago Up 19 hours 9000/tcp portainer
58e4713d0345 jpillora/dnsmasq "webproc --config /e..." 19 hours ago Up 19 hours 127.0.0.1:53->53/udp dnsmasq
5687702db805 panubo/sshd:1.1.0 "/entry.sh /usr/sbin..." 19 hours ago Up 19 hours 127.0.0.1:2222->22/tcp tunnel
Now that the containers have been created and are running, we can proceed with the installation of Magento.
Open an ssh connection to your project
warden shell
Skip to the next step if you have an existing Magento project
## Install Application
bin/magento setup:install \
--backend-frontname=backend \
--amqp-host=rabbitmq \
--amqp-port=5672 \
--amqp-user=guest \
--amqp-password=guest \
--db-host=db \
--db-name=magento \
--db-user=magento \
--db-password=magento \
--http-cache-hosts=varnish:80 \
--session-save=redis \
--session-save-redis-host=redis \
--session-save-redis-port=6379 \
--session-save-redis-db=2 \
--session-save-redis-max-concurrency=20 \
--cache-backend=redis \
--cache-backend-redis-server=redis \
--cache-backend-redis-db=0 \
--cache-backend-redis-port=6379 \
--page-cache=redis \
--page-cache-redis-server=redis \
--page-cache-redis-db=1 \
--page-cache-redis-port=6379
## Configure Application
bin/magento config:set --lock-env web/unsecure/base_url \
"https://${TRAEFIK_SUBDOMAIN}.${TRAEFIK_DOMAIN}/"
bin/magento config:set --lock-env web/secure/base_url \
"https://${TRAEFIK_SUBDOMAIN}.${TRAEFIK_DOMAIN}/"
bin/magento config:set --lock-env web/secure/offloader_header X-Forwarded-Proto
bin/magento config:set --lock-env web/secure/use_in_frontend 1
bin/magento config:set --lock-env web/secure/use_in_adminhtml 1
bin/magento config:set --lock-env web/seo/use_rewrites 1
bin/magento config:set --lock-env system/full_page_cache/caching_application 2
bin/magento config:set --lock-env system/full_page_cache/ttl 604800
bin/magento config:set --lock-env catalog/search/engine elasticsearch7
bin/magento config:set --lock-env catalog/search/enable_eav_indexer 1
bin/magento config:set --lock-env catalog/search/elasticsearch7_server_hostname elasticsearch
bin/magento config:set --lock-env catalog/search/elasticsearch7_server_port 9200
bin/magento config:set --lock-env catalog/search/elasticsearch7_index_prefix magento2
bin/magento config:set --lock-env catalog/search/elasticsearch7_enable_auth 0
bin/magento config:set --lock-env catalog/search/elasticsearch7_server_timeout 15
bin/magento config:set --lock-env dev/static/sign 0
bin/magento deploy:mode:set -s developer
bin/magento cache:disable block_html full_page
bin/magento indexer:reindex
bin/magento cache:flush
## Generate an admin user
ADMIN_PASS="$(pwgen -n1 16)"
ADMIN_USER=localadmin
bin/magento admin:user:create \
--admin-password="${ADMIN_PASS}" \
--admin-user="${ADMIN_USER}" \
--admin-firstname="Local" \
--admin-lastname="Admin" \
--admin-email="${ADMIN_USER}@example.com"
printf "u: %s\np: %s\n" "${ADMIN_USER}" "${ADMIN_PASS}"
# Exit shell
exit
The following steps are the same as discussed above to the point of installing Magento. The first thing you need is a database export of your existing project, then import it as follows:
pv /path/to/<your_database_export>.sql | warden db import
Or copy your database export to your php-fpm container and use magerun with the drop tables option to import your database:
cp /path/to/<your_database_export>.sql <container_id>:/var/www/html
warden env exec php-fpm n98-magerun db:import --drop-tables <your_database_export>.sql
Magerun is included by default when you install Warden, so you don't have to manually install it yourself.
When that is done you have to put the urls correctly in the
core_config_data
table:With Magerun:
warden env exec php-fpm n98-magerun config:set web/unsecure/baseurl http://app.example.test/
warden env exec php-fpm n98-magerun config:set web/secure/baseurl https://app.example.test/
warden env exec php-fpm n98-magerun web/unsecure/base_media_url http://app.example.test/media/
warden env exec php-fpm n98-magerun web/secure/base_media_url https://app.example.test/media/
Or you can open an interactive mysql session in your current project by:
warden db connect -A
And then by executing the following sql query:
UPDATE `core_config_data` SET value = 'http://app.example.test' WHERE path = 'web/unsecure/baseurl';
UPDATE `core_config_data` SET value = 'https://app.example.test' WHERE path = 'web/secure/baseurl';
UPDATE `core_config_data` SET value = 'http://app.example.test/media/' WHERE path = 'web/unsecure/base_media_url';
UPDATE `core_config_data` SET value = 'https://app.example.test/media/' WHERE path = 'web/secure/base_media_url';
Now that your installation is ready you can restart Warden.
warden env down && warden env up -d
Go to your application in your browser: https://app.example.test
Now that everything is up and running, you can connect to your database as follows.
Tableplus
Create a new connection > MySQL > Create
Sequel Pro
PHPStorm
1. Database > Data Source > MySQL
SSH/SSL > Use SSH tunnel > Select configuration >
2. SSH/SSL > Use SSH tunnel > Select configuration >
3. Test connection
Check if grunt is installed:
❯ grunt --version
grunt-cli v1.3.2
If not:
npm install -g grunt-cli
Add the following to your app/etc/env.php
<?php
return [
'system' => [
'default' => [
'design' => [
'footer' => [
'absolute_footer' => '<script src="/livereload.js?port=443"></script>'
]
]
]
]
];
Add your Gruntfile and package.json if you don't already have them.
cp Gruntfile.js.sample Gruntfile.js
cp package.json.sample package.json
Install node packages
npm install
Copy files to your Docker php-fpm container:
docker cp Gruntfile.js <container_id>:/var/www/html
docker cp package.json <container_id>:/var/www/html
docker cp node_modules <container_id>:/var/www/html
Perform the following:
warden env exec php-fpm grunt clean && grunt less
Finally
warden env exec php-fpm grunt watch
So far we've learned how to set up a local Docker environment for Magento with Warden. In the next article, I will talk about how to set up multiple store views in Magento 2 and Warden.
Sources:
Previously published on: https://rickdaalhuizen.com/posts/how-to-install-a-local-magento-2-environment-with-docker/
Create your free account to unlock your custom reading experience.