Skip to content

Add USER to the Dockerfile #3514

@aaronburtle

Description

@aaronburtle

Scanners will complain when we dont have a USER set in the Dockerfile, despite the container already having a user app. Add app as USER in Dockerfile to make scanners happy.

There are some issues however with adding a user to the Dockerfile. Mainly, this could be a breaking change.

Breakage Avoidable in the image?
1. Bind to port < 1024 Partially (may trigger scanner but we can document how user may fix)
2. Host volumes with mismatched UIDs No host-side concern we can document
3. Writing relative paths under /App Yes chown -R
4. docker exec lands as app, not root No
5. Downstream RUN/COPY in a derived Dockerfile No (derived image must USER 0 first)
6. K8s runAsUser admission rules Positive change, technically a policy break but will run automatically on hardened

We cannot make #4 and #5 go away without un-doing the scanner fix. This provides for 2 options.

1. Single image, minimize blast radius

What it actually changes for the typical user (docker run -p 5000:5000 ...): nothing observable. Default port works, config reads work, file-sink works.

What we tighten in the Dockerfile to remove all the avoidable breakages:

chown -R app:app /App so any feature writing relative paths under /App keeps working (eliminates #3 entirely, including any future code that writes there).
Keep the default port at 5000 (already > 1024) so #1 only bites users who explicitly override ASPNETCORE_URLS.
Document #1, #4, #5 in release notes as "if you do X, do Y."

2. Two image variants, zero breakage for existing users

Publish two tags from the same code:

mcr.microsoft.com/azure-databases/data-api-builder:<version> unchanged, still runs as root. Existing users see no diff.
mcr.microsoft.com/azure-databases/data-api-builder:<version>-nonroot runs as app, satisfies scanners.
Users with scanner alerts switch tag. Everyone else is untouched. Next major (v2.x) flips the default to non-root.

This is what nginx, redis, postgres, and the .NET team itself have all done historically when introducing non-root images. It's the gold-standard "no regressions" pattern.

The downside: it requires a small change in the publish pipeline. Adding a second docker build invocation with a different Dockerfile (or --target) and push a second tag.

Metadata

Metadata

Assignees

Labels

criCustomer Reported issuedocker

Type

Projects

Status

In Progress

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions