Add non-root variant to Dockerfile for dual image publishing#3520
Open
aaronburtle wants to merge 4 commits into
Open
Add non-root variant to Dockerfile for dual image publishing#3520aaronburtle wants to merge 4 commits into
aaronburtle wants to merge 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the container runtime stage to explicitly run Data API Builder as a non-root user (app) to satisfy container security scanners, aligning the Dockerfile with the base image’s intended default user.
Changes:
- Add explanatory comments documenting the rationale for running as non-root in the final image stage.
- Set
USER appin the runtime stage so scanners see a non-rootConfig.User.
Aniruddh25
requested changes
May 6, 2026
Aniruddh25
left a comment
Collaborator
There was a problem hiding this comment.
Copilot suggestion is valid.
6eb720f to
4cf4f53
Compare
souvikghosh04
requested changes
Jun 10, 2026
Aniruddh25
reviewed
Jul 8, 2026
Aniruddh25
reviewed
Jul 8, 2026
Aniruddh25
reviewed
Jul 8, 2026
Aniruddh25
reviewed
Jul 8, 2026
Aniruddh25
requested changes
Jul 8, 2026
Aniruddh25
left a comment
Collaborator
There was a problem hiding this comment.
Need some clarifications.
5 tasks
Aniruddh25
approved these changes
Jul 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why make this change?
Closes #3514
The published runtime image (
mcr.microsoft.com/azure-databases/data-api-builder) runs as root because the Dockerfile never issues aUSERinstruction. Image scanners like Checkmarx One read the image'sConfig.Userfield and flag any final stage that's empty orroot. Users who have to satisfy those scanners are blocked from adopting DAB unless they overridesecurityContext.runAsUserin their pod spec.DAB is just an ASP.NET Core process and does not need root privileges, so the fix is to declare a non-root user explicitly. The published
mcr.microsoft.com/dotnet/aspnet:10.0-azurelinux3.0base image already ships with a non-root user (UID/GID 1654, exposed via theAPP_UIDenv var), so nouseraddlayer is needed.What is this change?
Restructure the Dockerfile into a multi-target build that publishes two runtime variants from the same source:
runtime(default, last stage):<version>rootruntime-nonroot(opt-in via--target):<version>-nonroot$APP_UID)The root variant is the last stage in the Dockerfile, so a plain
docker build .with no--targetargument still produces the existing root-running image. No existing user sees a behavior change.Safeguards on the non-root variant
To minimize the chance of runtime breakage when users adopt the non-root tag:
chown $APP_UID:$APP_UID /App/logs(non-recursive) so the documented default file-sink path (runtime.telemetry.file→logs/dab-log.txt, relative toWORKDIR /App) is writable by the non-root user. Ownership of the published assemblies under/Appis intentionally left unchanged — a recursivechown -Rwould duplicate every assembly layer and roughly double the non-root image size for no runtime benefit, since DAB only needs write access to/App/logs. Only ownership of/App/logsis changed, not file modes./App/logsso the documented default file-sink path works with no extra volume or permission setup.USER $APP_UID(rather thanUSER app) per .NET container guidance — a numeric UID is friendlier to image scanners and to KubernetesrunAsNonRoot/runAsUserchecks, which cannot resolve a username to a UID at admission time.5000, which is above 1024, so binding works withoutCAP_NET_BIND_SERVICE. Users overridingASPNETCORE_URLSto a privileged port (<1024) must add--cap-add=NET_BIND_SERVICEor front DAB with a reverse proxy.Known caveats for consumers of the non-root variant
These are inherent to running any non-root container and cannot be fully eliminated in the image. They should be called out in release notes:
chown -R 1654:1654 /host/pathor, in Kubernetes, setsecurityContext.fsGroup: 1654.docker execdefaults to UID 1654. Usedocker exec --user 0for administrative actions inside a running container.FROM <this image>) that need to install packages or write outside/Appshould addUSER 0before those instructions, then restoreUSER $APP_UIDat the end.Manual testing performed
Both variants were built locally and verified end-to-end:
:<version>(default):<version>-nonrootdocker buildsucceedsConfig.User(what scanners read)app0(root)1654(app)/Appownershiproot:rootapp:app(recursive)/App/logspre-createddab-log20260519.txtwritten to/App/logs/by UID 1654)Follow-up work (separate PR)
The publish pipeline needs to be updated to build and push the second tag. That change lives outside this repo and will be done after this PR merges.