deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

Docker Engine 29.8 --umask flag fixes permission drift in exec sessions and healthchecks

Docker Engine 29.8 adds a native --umask flag covering a container's main process, exec sessions and healthchecks, closing a gap where entrypoint-based umask fixes quietly stopped working.

Docker Engine 29.8 --umask flag fixes permission drift in exec sessions and healthchecks

A native umask setting arrives in Docker Engine 29.8

Docker Engine 29.8.0, released on 3 September 2026, adds a HostConfig.Umask setting and a matching --umask flag to docker run and docker create. According to documentation referenced in a hands-on write-up on dev.to, the setting governs the container's main process, exec sessions, and healthchecks — and that breadth is the entire point of the change.

The gap the old workaround left behind

Previously the accepted way to control a container's umask was an entrypoint script: set the mask, then exec into the real application. That fixes PID 1, and PID 1's children inherit the value. The problem is that a process launched by docker exec is attached directly into the container's namespaces by the runtime — it is not a child of PID 1 and never inherits its umask. Healthcheck commands sit outside that inheritance chain too.

The dev.to author measured the difference. With an entrypoint setting umask 027, the main process produced files at mode 640 as intended, while files created in an exec session landed at 644. Healthcheck probes did the same, consistently across repeated runs at a two-second interval rather than a single pass. Replacing the script with --umask 027 gave 640 in all three places, with results stable across consecutive checks.

For reference, the write-up reports that with no umask set, Alpine's defaults produce 644 files and 755 directories; --umask 027 yields 640 and 750; --umask 000 yields 666 files.

Validation is strict, except when it isn't

The flag parses its input as an unsigned integer using Go's strconv.ParseUint, so values such as 099, -1, symbolic notation like u=rwx, or an empty string are all rejected before the container is even created, with errors that point at the actual problem.

What surprised the author is what slips through. A umask can carry a leading fourth octal digit for the setuid, setgid and sticky bits, and Docker's help text specifies no range. Passing 1777 is accepted silently but applied as 0777; 2027 and 4027 likewise collapse to 0027. There is no warning in the daemon log and no error returned to the client, so a value copied from elsewhere may quietly lose its special-bit prefix.

There is also a scripting hazard: docker inspect with the format string for HostConfig.Umask returns the value as a plain decimal integer — 23 for an octal 027 — so monitoring scripts searching for the literal string 027 will never match.

Where the new flag doesn't reach

Two limitations stand out from the dev.to testing. docker update has no umask option, so a running container's mask cannot be changed after creation; the container has to be recreated. And Docker Compose, checked at v5.1.1, rejects a umask key in the service definition as an unknown property, leaving Compose-managed services dependent on entrypoint or command overrides — and still exposed to the exec and healthcheck gap the feature exists to close.

Everything else behaved as advertised, according to the write-up: --umask 027 combined with --user 1000:1000 still produced 640, files written through a bind mount carried the same mode on the host as inside the container, a named volume with --umask 077 gave 600, and ten parallel exec sessions against the same container all reported 0027 with no divergence, suggesting the daemon applies the setting stably under concurrent access.

Why it matters

The inconsistency was easy to miss precisely because the foreground process behaved correctly — whoever wrote the entrypoint tested the thing they could see running. The failures surfaced only where a deploy script or monitoring sidecar encountered a file more permissive than policy intended, which is exactly the quiet security drift that umasks exist to prevent. The new flag makes the policy container-wide rather than PID-1-wide for the first time, which is a meaningful hardening step for anyone running multi-tenant or sensitive workloads. But until Compose support lands, and given the silent truncation of special-bit prefixes, teams should verify the mask actually in effect rather than assume the value they passed is the one applied.

  • #docker
  • #containers
  • #devops
  • #file-permissions
  • #linux

Related posts