Docker filesystem performance on OSX

How to work around poor filesystem performance with binds.

Development activities can involve lots of filesystem activity. Timing of NodeJS dev activities inside a Docker container on an OS X host is quite sensitive to the way we present the node_modules directory to the container. This is just a brief summary of the extensive literature (see References).

Summary

Mask high churn directories inside your source tree (e.g. node_modules) with a Docker volume.

Options

Bind mount

The default starting point is to bind mount the entire source directory to the container, and do work inside the container on it. By default the host's and the container's view of the directory will be entirely consistent.

services:
  app:
    working_dir: /app
    volumes:
      - type: bind
        source: '.'
        target: /app

Bind mount with delegated consistency

The next thing to try is to use the OS X consistency configuration to allow the container to have the authoritative view of the directory and allow Docker to update the host later:

services:
  app:
    working_dir: /app
    volumes:
      # Bind source to container
      - type: bind
        source: '.'
        target: /app
        consistency: delegated

Bind mount with volume masking node_modules

Another option is to allow most filesystem activity to happen in a Docker volume; bind the source directory to the container as before but then mask the node_modules with a Docker volume.

services:
  app:
    working_dir: /app
    volumes:
      - type: bind
        source: '.'
        target: /app
      - type: volume
        source: node_modules
        target: /app/node_modules
        volume:
          nocopy: true

Results

The following timing is on a moderately sized ReactJS project (about 14K LOC javascript) and shows that the volume masking option is a clear winner, getting close to local performance:

Type npm i npm t
Bind 3m39s 1m11s
Bind (delegated) 3m51s 1m21s
Volume 0m38s 0m13s
(Local) 0m31s 0m11s

(The delegated consistency performance wasn't any better than the default, which is surprising.)

References

Published on: 08 Jan 2019