Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add non-root user support #4397

Merged
merged 39 commits into from
Feb 15, 2023
Merged

Conversation

lbussell
Copy link
Contributor

@lbussell lbussell commented Feb 7, 2023

Fixes #2249. Also see dotnet/designs#271.

Adds non-root runtime-deps files so that any 8.0 image may be run with -u app or new images can be created with USER app at the end of the Dockerfile to run as non-root.

Other changes:

  • switch the default port from 80 to 8080
  • use the new environment variable ASPNETCORE_HTTP_PORTS instead of ASPNETCORE_URLS
  • don't unset ASPNETCORE_URLS in sdk images. Aspnetcore sees the (empty) URLS variable and overrides the new HTTP_PORTS variable

@richlander
Copy link
Member

richlander commented Feb 7, 2023

Soooo nice to see this PR (start to) land.

Configure web servers to bind to port 8080/8443 when present

It seems like it should only mention ports that are configured.

Aspnetcore sees the (empty) URLS variable and overrides the new HTTP_PORTS variable

That doesn't seems right. The diff suggests that the old variable is gone.

Home directory

It looks like we set the home directory for regular images and not for distroless/chiseled. We should document our policy.

Scope

Would be good to document the scope ... I think it is "all image types: runtime and SDK, Linux and Windows, regular and chiseled/distroless".

@mthalman
Copy link
Member

mthalman commented Feb 7, 2023

FYI: Looks like tests are failing for all versions other than 8.0.

eng/dockerfile-templates/Dockerfile.common-dotnet-envs Outdated Show resolved Hide resolved
eng/dockerfile-templates/Dockerfile.common-dotnet-envs Outdated Show resolved Hide resolved
eng/dockerfile-templates/runtime-deps/Dockerfile Outdated Show resolved Hide resolved
eng/dockerfile-templates/runtime-deps/Dockerfile Outdated Show resolved Hide resolved
eng/dockerfile-templates/runtime-deps/Dockerfile Outdated Show resolved Hide resolved
@richlander
Copy link
Member

FYI ... This is what Ubuntu 23.04 has.

$ docker run --rm ubuntu:23.04 cat /etc/passwd | grep ubuntu
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash

# Unset ASPNETCORE_URLS from aspnet base image
ASPNETCORE_URLS= \
{{if dotnetMajor != "6" && dotnetMajor != "7":# Unset ASPNETCORE_HTTP_PORTS from aspnet base image
ASPNETCORE_HTTP_PORTS= \^else:# Unset ASPNETCORE_URLS from aspnet base image
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jander-msft - I know you requested this. Can you explain the need for this?

Also, should the monitor Dockerfile be configured to run as non-root by default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jander-msft - I know you requested this. Can you explain the need for this?

.NET Monitor already runs its HTTP server at ports 52323 and 52325 by default. Either setting ASPNETCORE_HTTP_PORTS would override that behavior (which we don't want by default) or it is not observed (which would be bad to insinuate that it has some effect when it does not); I think the former would be the case if the environment variable is specified. I will very later today that this is the case.

Also, should the monitor Dockerfile be configured to run as non-root by default?

That would be great if that could be added too. Although, if this change is only scoped to .NET 8+, then this work shouldn't be necessary because .NET Monitor is only offering distroless and chiseled images for .NET 8+, which should already be using the non-root user.


# Create a non-root user and group
RUN addgroup \
--system \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the options be ordered consistently between addgroup and adduser? The system and id options are ordered in opposite order. A strict alphabetical order would be consistent with the rest of the Dockerfile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you but I think this would mean either 1.) changing all of the old distroless Dockerfiles in this PR, or 2.) conditioning the alphabetical order in the dockerfile templates for 8.0 (until the next servicing release, when we can change all the older Dockerfiles?)

@mthalman thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A 3rd option would be to use the existing pattern and log a follow-up issue to correct the ordering across the board.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this can be done as a follow-up issue to apply consistently.

&& mkdir -p /staging/var/lib/rpmmanifest \
# Remove duplicates that match on the first field (package name)
&& tac $tmpManifestPath | gawk '!x[$1]++' | sort > /staging/var/lib/rpmmanifest/container-manifest-2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the two blank lines intentional here? One feels more consistent. Typically two are only used between stages.

Suggested change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra line is present in old mariner 2.0 distroless dockerfiles as well, which I'm trying not to overwrite:

Should we file an issue for this as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we file an issue for this as well?

Yes, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #4418.

openssl-libs \
zlib \
&& tdnf clean all \
# Create a non-root user and group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason to do this all within one stage? It feels a bit inconsistent with the rest of the images (I am intentionally overlooking the shadow-utils issue). For consistency and readability, it feels to me that this should be a separate instruction. If you decide to keep with this pattern, I would suggest only calling tdnf clean all once.

Copy link
Contributor Author

@lbussell lbussell Feb 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shadow-utils issue is the reason it's all in one stage. Separating it into multiple stages anywhere in-between will increase the image size. I fixed the duplicate cleaning logic, that was a bug. Do you think that we should install shadow-utils only for the new user creation logic, and uninstall immediately after? i.e.

RUN tdnf install -y \
      shadow-utils \
    && groupadd \
        --system \
        ...
    && tdnf remove -y \
        shadow-utils \
    && tdnf clean all \

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that we should install shadow-utils only for the new user creation logic, and uninstall immediately after?

Yes, the instruction you included is the pattern I was expecting to see.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, misunderstood the original discussion, I'll work on that change now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems rather inefficient to me. We'd then need to "update" and clean up packages twice. What benefit does that approach have?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consistency of the patterns and layers across our Dockerfiles.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mthalman there is the --cacheonly / -C option if we want to avoid updating the cache from the previous layer.

libstdc++ \
zlib

# Create a non-root user and group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From an instruction ordering perspective, it feels like this layer is more stable than the package installs and should therefore be placed before the packages instruction. This doesn't provide any value to us but is a best practice and would be beneficial to some who copy our Dockerfiles. FYI, there is a degree of inconsistency across the Dockerfiles because the chiseled images create the user before installing the packages.

Related, it feels like we should do the same for the ENV instruction. We place the ENV first in the aspnet and sdk Dockerfiles. This should be fixed in a separate PR if everyone agrees.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #4419 to address this.

Copy link
Member

@MichaelSimons MichaelSimons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@jander-msft jander-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.NET Monitor LGTM

Comment on lines 48 to 58
set certsPkgPrefix to when(isMariner,
[
when(isDistrolessMariner, "prebuilt-ca-certificates", "ca-certificates"),
"",
dotnetDepsComment
],
[
"ca-certificates",
"",
dotnetDepsComment
]) ^
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks to be indented more than everything else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reverted to the original version of this file that exists on nightly - but since it does look weird, I can address it here.

@lbussell lbussell merged commit 4fced56 into dotnet:nightly Feb 15, 2023
mthalman pushed a commit to mthalman/dotnet-docker that referenced this pull request Feb 16, 2023
mthalman pushed a commit to mthalman/dotnet-docker that referenced this pull request Feb 16, 2023
@mthalman mthalman added the needs-announcement An announcement is needed to discuss customer impact label Jun 26, 2023
@mthalman
Copy link
Member

Documented breaking changes at dotnet/docs#35958, dotnet/docs#35959

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dockerfiles needs-announcement An announcement is needed to discuss customer impact
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants