0

I'm running a container as non-root (see Dockerfile below), and am a bit confused to why it's successfully binding to port 80. I'd expect this to not have permission to bind to anything below 1024. This is running locally on Docker for Windows (which uses WSL2).

Any ideas?

FROM mcr.microsoft.com/dotnet/aspnet:7.0
EXPOSE 80
WORKDIR /app

...usual COPY stuff...

# Change user to non-root (gecos means don't interactively prompt for various info about the user)
RUN adduser --disabled-password --gecos '' appuser
USER appuser

ENTRYPOINT ["dotnet", "MyWebApi.dll"]
docker run --rm -p 80:80 myimage

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app

Running this against the containers shows it is running as that nonroot user...

docker exec <containerid> id

Output: uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)

Dan
  • 5,692
  • 3
  • 35
  • 66

1 Answers1

0

The important difference here is inside and outside of the container.

Inside the container, you are not root, outside (unless you went for the rootless installation) you still are.

Inside the container also the same rules don't apply as for outside.

If you look at a standard container:

$ docker run -ti --rm ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
5af00eab9784: Pull complete
Digest: sha256:0bced47fffa3361afa981854fcabcd4577cd43cebbb808cea2b1f33a3dd7f508
Status: Downloaded newer image for ubuntu:latest
root@fed10d20aebd:/# cat /proc/sys/net/ipv4/ip_unprivileged_port_start
0

This means the lowest port to be "used" by an unprivileged user is 0 as opposed to the same setting on a default centOS installation, so outside the container, looking like this:


$ cat /proc/sys/net/ipv4/ip_unprivileged_port_start
1024

This is the usual limitation you'd expect, where you can't bind to a port lower than 1024 as unprivileged user.

All in all this allows you to bind to port 80 inside while being unprivileged and then outside you still are privileged, because the docker user is and you can bind to 80 again, which allows you to map host port 80 to container port 80.

Rick Rackow
  • 1,490
  • 8
  • 19
  • Thanks for your answer. I must admit, I didn't really understand the reason why privileges outside would make a difference as far as user rights inside the container. The answer that was linked as a duplicate suggests that the default `ip_unprivileged_port_start` has changed in a later version of Docker makes sense. – Dan Aug 10 '23 at 13:17