Posted on 25 September 2019, updated on 6 December 2023.

If you develop in Docker, you probably mount a volume containing your source code from your host’s filesystem. If your host’s is running on OSX (or Windows), you might encounter slowness issues. I had a bit of trouble figuring out why and how to fix it. Is it language-related? Is it OS-related?

The cause: the file system calls

Your source code is mounted from your osx host’s filesytem to your Docker (Linux) filesystem. For them to communicate together, every call to your mounted volume uses the osxfs shared file system solution. As described in this post, a call will undergo the following process, back and forth:

  • turned into a FUSE message in the Linux VFS
  • proxied over a virtio socket by transfused
  • forwarded onto a UNIX domain socket by HyperKit
  • deserialized, dispatched and executed as a macOS system call by osxfs

Now, some languages, such as php or python, expect system calls to be instantaneous. Thus, they will retry until they get an answer. These thousands of parasite calls will result in an overhead causing latency. Although Docker has made some effort to reduce this problem, it is still insufficient, but cool opensource projects such as docker-sync solve the problem.

A workaround with docker-sync

Docker-sync is a tool that allows a two way and asynchronous synchronization. It will drastically improve the performances and make the comparable to running docker on a linux host.

Here is a guide to quickly solve your issue:

Install docker-sync

Install docker sync with rubby on any OS with the command: `gem install docker-sync`.

Configure your project to use docker-sync

Let’s say you have a Dockerfile and a docker-compose.yaml. A minimal docker-compose.yaml would look something like that

Create a docker-sync.yaml file and past in this configuration. More options are available, you can check them here:

Create the volume that will keep the src defined above by running docker volume create api-sync

Update your docker compose to refer to this volume

Run the command docker-sync start --config=<path-to-docker-sync.yaml>

You should define sync for every volume you mount from your host. For instance, if your db stores persistent data...

Note that if you change your docker-sync.yaml, run docker-sync clean and docker-sync start to refresh your volumes. Run docker-sync stop to stop docker-sync

Use docker-sync

You are now ready to use your app docker-compose up -d.

I hope it will solve your problem quickly. Note that this solution is also available for windows. Please go support docker-sync on Github. Also, check our other articles on docker and DevOps tools.