A few days ago there was a question on Twitter about using Docker in production instead of development. I was a little intrigued by the question because my experience has been in the exact opposite scenario. I almost never use Docker for development and almost always use it in production. I tweeted my response and this was the reply.
Because out of the box Docker and M2 are slow as molasses, and generic devops are cheaper than docker experts
I can’t speak to the cost of Docker experts (I’m not one, but my experience is that once you get through the annoyance of the Dockerfile it doesn’t require much more advanced knowledge than a regular sysadmin), but I found the response interesting because my experience with Docker in production has been so good that I’ve Dockerized practically everything, including this blog. But this guy knows his stuff, and I give a lot of weight to his perspective. But my experience has been different.
Except in one place. Magento 2 on Docker on Mac is a horrible experience and it is specifically because of file system performance. But on Linux I’ve had good experiences. However, those experiences were with Magento 1 and not Magento 2. Magento 2 relies on the file system more than Magento 1 so it is quite plausible that Magento 2 is slow as molasses on Docker.
So I decided to do a quick load test on a Linux system I have here (have I mentioned that I offer a load testing service for Magento?) and see if the results are worth pursuing further.
Caveat Number 1
This is a smoke test. I wanted to see how bad it was. And if the performance turned out to be not-so-bad my intention is to run a full load test, with checkout and everything (kind of like I do for my Magento load testing service) for Magento 2 on AWS using Aurora and ECS and compare the difference. As such, this result is intended only to be prelimary.
Caveat Number 2
Given that this is a prelimary test I wanted to give Docker every opportunity to do well. So all I did was turn the full page cache off and hit the Men’s Jackets page from the default sample data. A full, proper, load test may end up yielding completely different results.
Caveat Number 3
This test was run on an old machine
uname -a Linux dev 3.10.0-514.21.2.el7.x86_64 #1 SMP Tue Jun 20 12:24:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
It is a
Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
free -m total used free shared buff/cache available Mem: 15874 4456 1121 117 10296 10534 Swap: 8063 207 7856
php70 -v PHP 7.0.22 (cli) (built: Aug 2 2017 08:34:38) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.22, Copyright (c) 1999-2017, by Zend Technologies
php70 -v PHP 7.0.20 (cli) (built: Jun 7 2017 06:56:00) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.20, Copyright (c) 1999-2017, by Zend Technologies
Caveat Number 4
This was a single system that had MySQL running locally. So it was not production-like. Also, the two setups are not exactly the same. But I would be surprised if the differences would make such a huge difference so-as to completely invalidate the results. Also, because I ran this on my Linux development environment I set up an Nginx proxy between Nginx and Docker with a port mapping to the Docker container. This may account for some of the difference.
The testing scenario was done using some of the tooling I’ve developed for use with my load testing service. It ingests server counters, MySQL counters (which I did not use for this test), and tracks it against test concurrency, throughput and request timings. The cache was a local Redis instance, the DB was a local DB instance. Both instances connected using TCP.
The results of this test were about in line with what I was expecting. Bare metal had a slight advantage over the container. But not by much.
This graph shows the response times from the Docker test. The charts have been y-corrected and so we can see that bare metal is slightly faster than Docker on average. The average from the bare metal run (where I artificially dropped two requests that took >1000ms) was 404ms and the average from the Docker run was 469. So there was about a 15% overhead in the Docker scenario. But bear in mind that there was an extra networking layer in between Docker and the test not just on Nginx but also Redis and MySQL.
This test shows that bare metal is definitely faster than Docker. However, the difference is somewhat marginal. Plus, my gut says that if this test were to be performed in a production environment, with the DB and cache being on different machines, that the difference would be less. Magento 2 on Docker on Mac is a horrible fate that I would not wish on anyone, but when running on Linux the performance tradeoff seems fairly minor.
Hopefully, I’ll have the time to do a load test on Amazon using ECS. ‘tmight be fun.