I’ve recently gone on a Docker crusade at work.
Because our office develops applications in multiple languages across various platforms, we have developers from .NET backgrounds using Windows machines, and developers from the Rails world using Macbooks.
In order to allow developers from any platform to contribute, I have been Dockerizing our applications. Docker provides our cross-platform team two main benefits:
- Environment standardization
- Both Windows and MacOS hosts can use the same Docker image, meaning all dependencies and configurations can be identical across environments
- Easy app setup with
docker-composereduces overhead for onboarding new team members
- Application isolation
- Developers need to run multiple applications simultaneously. With Docker, we can prevent things like dependency or port conflicts
After a few months developing applications with Docker on Mac, I’ve found some issues that any new adopters should be aware of.
Slow I/O and Execution
With any virtualization, we expect to see some amount of slowdown. On Docker for Mac, however, issues with I/O and slow application execution can cause the development experience to range from a 2x slowdown to a completely unusable 100x or more slowdown when used with some build tools.
Docker on Mac has documented issues with slow reads and writes on mounted volumes. Running I/O-heavy tools, such as EmberJS’s Broccoli build tool, on Docker for Mac has been nearly unusable from my experience.
The slowness isn’t just limited to I/O, however. Running tests should be a generally I/O-light task, yet in two Rails applications, test execution time varies as follows:
|Default Volume||Cached Volume||Delegated Volume||No Volume||Native Execution|
The Docker team has been working on adding more types of file syncing. You can see that the recent Docker changes do increase performance, but even Docker with no file syncing (the “No Volume” column) takes about twice as long to execute tests when compared to native execution in OSX.
SSH Key Management
For cloning private dependencies or sshing into application servers, developers often need ssh keys to be available from within a Docker container.
With Docker on Linux, users mount their
.ssh directory as a
volume on a Docker container
or use SSH agent forwarding to allow
the container private key access.
Docker for Mac SSH agent forwarding is on the roadmap, but does not yet have an elegant solution. I’ve worked around the issue by adding the key and ssh configuration to the container at build time.
- Add a
docker/directory to your application
- Add any necessary ssh configuration to
# docker/ssh_config # Add any convenience SSH configuration Host staging Hostname 18.104.22.168 # Use the key for ssh commands IdentityFile /root/.ssh/id_rsa
.gitignoreor similar for your version control.
- Copy your
- Build your container with the following additions to your Dockerfile:
# Dockerfile RUN mkdir -p /root/.ssh ADD docker/ssh_config /root/.ssh/config ADD docker/id_rsa /root/.ssh/id_rsa RUN chmod 600 /root/.ssh/id_rsa
Warning: This will add your private key to a layer in your Docker image. Do not use this approach if you will share you Docker images.
Unfreeable Disk Usage
Each time you rebuild a docker container, Docker allocates memory for a
docker.qcow2 file. Unfortunately, Docker for Mac does not free memory when
you delete containers and images.
docker.qcow2 file grows to over 60GB. There is no way to slim down this
file–deleting images does not actually free the space on disk.
While Docker has many benefits, Docker for Mac’s slowness is a huge killer of developer productivity. For some less I/O intensive applications, Docker for Mac may still be a valid option, but it is not the universal virtualization solution I had hoped it would be.
My coworkers and I are currently evaluating alternatives. We are currently exploring the performance of Docker on Windows 10 and Ubuntu 16.04.