November 9, 2016·4 min read·engineeringdockerosxfsfilesystems

Docker for Mac fixes ownership changes on shared files

Docker for Mac 1.12.3 repairs an ownership mismatch that broke package installation, alongside networking and shared filesystem fixes.

A package installer can fail on a perfectly readable file because changing its owner requires a different operation from reading its contents. Docker for Mac has supplied an unusually concrete example of that distinction. An ownership update inside a container became an extended attribute update on the Mac, where the permissions governing that update differed from the semantics the Linux program expected. The resulting error appeared in application tooling, although the defect belonged to the shared filesystem.

Docker for Mac 1.12.3, released on 9 November, fixes ownership changes on read-only files and files with mode zero. The contemporary release notes also record fixes for reads that never completed and a crash during simultaneous volume mounts. Those changes matter to the promise that a build environment behaves consistently when the source directory lives on a developer's laptop.

I value Docker's repeatable build description because it makes an environment transferable. A shared directory adds host filesystem behavior to that environment, and this release makes that dependency easier to understand.

Ownership crosses two permission models

The August report in issue 117 began with confusion about files appearing under the Mac user's ownership. Docker contributor David Sheets explained that Docker for Mac normally runs without elevated privileges, apart from a small networking process. Container root therefore does not imply that the filesystem sharing process runs as root on the host.

The filesystem documentation at this release explains the translation. A container initially sees a shared object's owner as the requesting process's user and group. After a container changes that ownership, osxfs stores the requested values in the host object's com.docker.owner extended attribute. Later ownership queries return the stored values. Actual host access still uses the permissions of the person running Docker.

This distinction permits a Linux program to observe ownership changes without requiring the corresponding host account to own files under those numeric identifiers. It also means that storing Linux ownership metadata is itself a host filesystem operation. The container-visible metadata and the host's authority to update its storage are separate questions.

Sheets identified the failing case in August. OS X would not let the sharing process modify extended attributes on a file to which it lacked write access. An operation that should change ownership therefore failed when its implementation tried to write the attribute. His October update describes the fix using an access control list entry to give those attributes behavior closer to inode metadata. That update predates today's stable release and explains the mechanism behind its brief changelog entry.

Why npm exposed the problem

Issue 263 shows how the mismatch appeared in a real toolchain. The reporter used the Wercker CLI to execute development steps inside a container. Installing dependencies from the npm registry worked, while a dependency fetched from GitHub failed when npm tried to change ownership within its Git cache. The same reported workflow worked under Docker on Linux.

The error named chown and returned EACCES for a Git pack index file. That is useful evidence because the failure occurred after the tooling had reached a specific filesystem operation. A diagnosis confined to package download connectivity would have examined the wrong part of the installation. The package source changed the installer behavior enough to encounter a permission defect that the registry package path did not expose.

A separate report, issue 633, concerns changing ownership of a read-only file on a mounted volume. Its narrow subject matches the release note directly. Taken together, the reports distinguish the general ownership model from the particular operation that violated expected behavior. Host user mapping alone does not explain why chown should fail on a readable file.

I regard this as an important compatibility fix because package managers should not need to understand how osxfs stores ownership. Keeping that translation inside the filesystem preserves the usefulness of existing build tools.

Correctness and performance remain separate

The release also changes networking resource use. DNS consumes fewer host UDP sockets, and VPNKit improves connection limiting to avoid exhausting host sockets. UDP forwarding now handles larger datagrams up to the configured macOS kernel limit, and forwarding errors can discard a packet while processing continues. These are resource management and error handling changes, with a different cause from the ownership defect.

Storage performance needs its own explanation. The release makes disk flushing configurable for database-like workloads to work around a regression in 1.12.1. That statement does not establish that every shared-directory workload becomes faster. The contemporary osxfs documentation discusses syscall latency separately from sequential throughput, and explains how repeated filesystem round trips can dominate operations involving many files.

The same documentation describes the cost of maintaining coherence between OS X and Linux views. An application may generate temporary files that the host never needs to inspect, yet the filesystem cannot automatically assume that their contents are private. More caching can reduce communication, but it requires decisions about when the other side must observe changes. Fixing ownership metadata does not remove those coherence requirements.

The practical consequence of 1.12.3 is more specific. Existing container tools gain the expected ability to change ownership on shared read-only files, while networking and mount fixes address other failures at the host boundary. A Dockerfile still describes the image build, and a bind-mounted source tree still brings the host filesystem's semantics into the running environment. The updated ownership implementation makes those two parts cooperate for operations that previously failed during dependency installation.