Improve Docker performance on macOS using Mutagen

4 Aug 2021

Hello! Today I would like to share my experience of improving Docker performance on macOS with Mutagen.

Docker on macOS

Docker on macOS has performance issues by default. It's related to mounting volumes and osxfs file system. It seriously affects applications with many I/O operations. So, a Symfony-based web application can handle a request for a few seconds.

Options

There are several options for using Docker on macOS.

  • Try to use native Docker for Mac.
  • Use Linux in Virtualbox, abstract from macOS.
  • Use Docker Sync
  • Use Mutagen

Mutagen

In this post, I'm going to describe Mutagen configuration. Mutagen provides files synchronization in real-time.

Installation

Firstly need to install Mutagen on macOS and start service:

brew install mutagen-io/mutagen/mutagen
mutagen daemon start

Demo project

As a demo project, I used placeholder-service - a service for generating images placeholders.

Creating extra docker-compose

Then need to create an additional docker-compose file for Mutagen: docker-compose-osx.yml. As soon as we have a separate config, Mutagen doesn't affect docker for Linux.

version: '3'
services:
  php-fpm:
    container_name: placeholder-service_php_fpm_1
    volumes:
      - placeholder-service-www:/var/www
  nginx:
    volumes:
      - placeholder-service-www:/var/www
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./docker/nginx/sites/:/etc/nginx/sites-available
      - ./docker/nginx/conf.d/:/etc/nginx/conf.d
      - ./docker/logs:/var/log
volumes:
  placeholder-service-www:

There is a named volume: placeholder-service-www. There is also unique name placeholder-service_php_fpm_1 for php-fpm container.

Configuring Mutagen

After that need to create mutagen.yml configuration file.

sync:
  defaults:
    mode: "two-way-resolved"
    flushOnCreate: true
    ignore:
      vcs: true
    configurationBeta:
      permissions:
        defaultFileMode: 0666
        defaultDirectoryMode: 0666
  placeholder-service-www:
    alpha: "./"
    beta: "docker://placeholder-service_php_fpm_1/var/www"
    ignore:
      paths:
        - ".idea"
        - "var"
        - "vendor"

# Set up the service and any volumes before creating sessions.
beforeCreate:
  - docker-compose -f docker-compose.yml -f docker-compose-osx.yml up --build --detach

# Set up the main services after creating sessions. At this point, sessions will
# have been established and code pushed to the shared volume.
# After this is done, we can start up the deployment scripts.
afterCreate:
  - docker-compose -f docker-compose.yml -f docker-compose-osx.yml up --build --detach
  - docker-compose exec php-fpm composer install

# Tear down all services and remove the code volume after terminating sessions.
afterTerminate:
  - docker-compose -f docker-compose.yml -f docker-compose-osx.yml down --remove-orphans || true

# Define common utility commands.
commands:
  logs: docker-compose -f docker-compose.yml -f docker-compose-osx.yml logs --follow

There are a merging of docker-compose.yml and docker-compose-osx.yml configuration files. There is also configuration for placeholder-service-www volume, that implement automatic synchronisation for /var/www directory of placeholder-service_php_fpm_1 container.

Permissions

Permissions are configured in configurationBeta sections. Problems with permissions also can be fixed by granting full access to /var/www. Then need to disable tracking permissions for git.

docker-compose exec php-fpm chmod -R 777 /var/www
git config core.fileMode false

Run demo project, benchmarking

Installation is described in Readme. Firstly let's run a demo project without Mutagen:

git clone https://github.com/antonshell/placeholder-service.git
cd placeholder-service/
docker-compose up
docker-compose exec php-fpm composer install

Loading sample page takes 480ms.

Then stop containers and run with Mutagen:

docker-compose down --remove-orphans || true
mutagen project start || mutagen project terminate

docker-compose exec php-fpm chmod -R 777 /var/www
git config core.fileMode false

Loading sample page takes 83ms.

Demo project available on github. There is also Pull Request with Mutagen configuration. That's all for today. Thank you for your attention!

Tags: Docker, Macos, Mutagen