The nginx config specifies the user "nginx", but this user does not exist on a clean base installation for the host OS so Docker maps it to some other user id. Somehow between 1.10 and 1.12 this seems to have changed from 104 to 101 so that caused file permission errors because 101 was "systemd-network" on the host and 104 was "syslog" (Ubuntu host).
Is there some way to guaranatee the uid for "nginx" doesn't change without having to add users directly on the host, since having to do this defeats the purpose of Docker.
Perhaps a simple solution would be for the docker entrypoint to chown the /var/cache/nginx and /var/log/nginx directories to "nginx"?
this user does not exist on a clean base installation for the host OS so Docker maps it to some other user id
This isn't exactly accurate. Docker doesn't do any mapping at all. The Linux kernel doesn't deal in user _names_ at all, and only cares about IDs -- names are a userspace abstraction to help us humans remember and conceptually deal with the IDs.
$ docker run -it --rm nginx id nginx
uid=101(nginx) gid=101(nginx) groups=101(nginx)
So, even if your host has an nginx user that's got an ID of (for example) 1000, this container will still by default run as UID 101 (which may or may not match anything in your host's /etc/passwd file).
If you have a new enough kernel, something like https://github.com/moby/moby/issues/8460#issuecomment-312459310 can be used to run the nginx image as an arbitrary user, but otherwise you can adjust the configuration file to use a port other than 80. Here's a working example to run nginx:latest as UID 1000:
$ docker run -it --rm --user 1000:1000 --tmpfs /var/cache/nginx:uid=1000 --tmpfs /run:uid=1000 --sysctl net.ipv4.ip_unprivileged_port_start=0 nginx
2018/01/03 19:06:05 [warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
Thanks for the explanation Tianon, I understand that the kernel deals in ids, but I didn't know how Docker works with username->id mapping. All I really know for sure is that when I upgraded from nginx:1.10 to nginx:1.12 the /var/cache/nginx directory (the same local persistent volume in both cases) was no longer writable by the container. So was this a change in /etc/passwd between the two base images? I'm reporting the issue in hopes that a better solution is available than to just get bit with broken containers upon upgrading.
I think it would be good to ensure that all images are created with the same, static uid for the nginx user:
$ docker run --rm -it nginx:latest id nginx
uid=101(nginx) gid=101(nginx) groups=101(nginx)
$ docker run --rm -it nginx:alpine id nginx
uid=100(nginx) gid=101(nginx) groups=101(nginx),101(nginx)
Having fixed uid & gid for nginx would help a lot in cases where you need to override the user at runtime and ensuring bind-mounts are accessible by nginx.
Certainly a big thing for running it on kubernetes.
@thresheek Thanks for fixing this. However, for existing containers this will cause some problems on the next update. What do you think about having the docker entrypoint chown the /var/cache/nginx and /var/log/nginx directories to "nginx"?
Chowning /var/log/nginx to non-root user will lead for the image to be vulnerable for CVE-2016-1247 (I do understand that the image doesnt carry logrotate or similar software, but still).
Also, chowning the directories to a preselected user in my opinion doesnt solve the broader issue of inability to run nginx as any uid/gid out of the box - so I've added a documentation remark on the uid/gid changes, and how to run as a non-root user on https://hub.docker.com/_/nginx/, section "Running nginx as a non-root user", hope this helps.
Most helpful comment
I think it would be good to ensure that all images are created with the same, static uid for the
nginxuser: