Docker promises to be a powerful solution for standardised development across environments. Adding a new tool to my development toolbox, however, adds another layer to the onion that is Magento 2(M2).
I found 1) mapped volumes and 2) Grunt to be the main issues when setting up an M2 environment in Docker. Admin and frontend areas were initially slow to load, with no apparent adherence to server timeout rules, as if Docker (in this case, NGINX) finished serving messages, but forgets to deliver it to the browser.
Reduce the Number of Docker Volumes
M2′s “vendor” folder houses pre-packaged modules including M2 core. In recent M2 releases it has grown exponentially in size. Excluding “vendor” from Docker’s mapped volumes improves load times significantly (by 10s of seconds). However, this exclusion introduces a new problem - vendor folder is now in isolation from the Docker environment and testing changes must now be done in Docker environment. The workaround here is to prepackage M2 code into the Docker image. This does feel a little like a hack.
Excluding vendor code brings page load times to a respectable 5-15 seconds - acceptable for testing, but not production standards.
Running Grunt Locally
Grunt, the trendy JS compiler tool, comes pre-packaged in more recent versions of M2. Grunt proves to be useful for M2 because it relieves the user from having to recompile LESS files for testing. In particular the “grunt watch” command automatically regenerates required CSS files from multiple location sources.
When mapped volumes are involved in the regeneration process, we found “grunt watch” commands to take in excess of 40 seconds to complete! This is not practical for implementing CSS changes.
My workaround is to rely on the local environment to run grunt watch, which still generates the requires filed in the right (mapped) folders, but without using Docker NGINX server. This reduces compilation times by factors of 3 to 4, to around 8-12 seconds.
Another problem arises, however, with the percona database container we use for the M2 database. Grunt requires a connection to the database for theme path, and databaes connection details are stored in Magento’s app/etc/env,php file. The clincher is this - connection host to the percona database is different when in local environment (”127.0.0.1″) and when in Docker environment (same as [container_name]).
To get around this, I unmapped the “app/etc/” folder so I have 1 copy of env.php for local, and 1 copy for Docker. The added bonus of this arrangement: I can now run M2′s bin/magento commands in local as well.
After some tweaking, the volumes in my docker-compose.yaml look something like this:
To conclude. M2 and Docker don’t play nice together out of the box. Given the benefits, it was worth the exploration. I expect further improvements can be made to our M2 images. More updates as they come.