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

Make UID & GID configurable #147

Closed
HerHde opened this issue May 14, 2019 · 17 comments · Fixed by #151
Closed

Make UID & GID configurable #147

HerHde opened this issue May 14, 2019 · 17 comments · Fixed by #151

Comments

@HerHde
Copy link

HerHde commented May 14, 2019

Expected Behavior

It should be possible to set the uid or gid for the couchdb (linux) user using environment variables.

Current Behavior

The uid and gid are hardcoded to the default port 5984 as in #53 decided.

Possible Solution

Use the environment variables PUID and PGID to set them.

Context

The downside of the decision from #53, implemented in #64, is, that mounted volumes including config files are harder to edit when logged in on the host system with another uid like 1000. Prefixing them with a P avoids confusion with ids of the current user.
LinuxServer.io wrote about this. They create a user and group abc with the id 911 and change it with this script in their base images.

@wohali
Copy link
Member

wohali commented May 14, 2019

Would need explicit approval from someone like @tianon before doing this since it directly changes an "official" image in a new way.

@HerHde
Copy link
Author

HerHde commented May 14, 2019

Alright, even when the default values stay the same?

@tianon
Copy link

tianon commented May 17, 2019

Given that Docker has built-in behavior which allows for switching to an arbitrary user (and doing so in a more secure/reliable way than environment variables and/or a shell script could possibly provide) via --user (which can take either a name or an explicit number), we typically prefer to leverage that (which when combined with --security-opt no-new-privileges is quite a bit more secure). The primary orchestration systems also typically provide some functionality for setting this parameter (user: in Swarm, etc).

For a couple implementation examples, see docker-library/rabbitmq#60, docker-library/cassandra#48, docker-library/mongo#81, redis/docker-library-redis#48, docker-library/mysql#161, MariaDB/mariadb-docker#59, docker-library/percona#21, docker-library/ghost#54, docker-library/postgres#253, docker-library/redmine#136.

I'd be happy to help take a look here too if that's something you'd be interested in help implementing or reviewing. 👍 ❤️

@HerHde
Copy link
Author

HerHde commented May 18, 2019

Do I understand right, that this allows me to configure the uid and guid via CLI or compose file to... lets say --user 1000:1000 setting the uid:gid for couchdb to 1000:1000?
Or do I have to use 5984:5984 as the user is already set to that uid/gid at the moment?

@HerHde
Copy link
Author

HerHde commented May 18, 2019

In other words, do I understand "arbitrary" right and are there no further dependencies to 5984?

@tianon
Copy link

tianon commented May 21, 2019

With the image as it stands right now, it won't work, but it should be possible for the image to be updated to support running with --user 1000:1000 natively if that's something the project wants to do (and examples of making that very conversion in other images are what all those links I provided above are).

For example, the current docker-entrypoint.sh script assumes it's always run as root and does gosu couchdb ... unilaterally in addition to a number of chown and chmod calls that will fail if the image is run as non-root -- we typically gate those sorts of things in an if [ "$(id -u)" = '0' ]; then block. Another potential stumbling block is the default volume/folder permissions -- if they're made wide enough, then running as an arbitrary UID should "just work" in general, although there are exceptions to that (for example, some parts of PostgreSQL's initdb assume that there should be an /etc/passwd entry for the current user, which doesn't really have to be true).

In some images, we take the approach of requiring users to pass storage with appropriate permissions instead to avoid having wider permissions on the defaults.

@drvan
Copy link

drvan commented Aug 9, 2019

@tianon I'm trying to run couchdb on openshift which doesn't allow containers to start/run as root - I'm attempting to follow the examples you listed above to allow use of --user but I'm primarily trying to solve this by trial/error, with limited success.

I've put all the chown/chmods in if [ "$1" = '/opt/couchdb/bin/couchdb' -a "$(id -u)" = '0' ];, per your suggestion. There's a touch line here that I'm not entirely sure what to do with (move it into the Dockerfile?) that I've simply commented out for now. The current result is that I can now run this by specifying the explicit couchdb uid (--user 5984:5984) but any other user causes erlang to crash with what looks like permission errors. As of now, here's what I have: https://gist.github.com/drvan/b7bd8a2015bac91b64eabe60d90fb6a1

Any guidance/direction would be incredibly helpful, and happy to submit a PR when all is said and done.

@tianon
Copy link

tianon commented Aug 9, 2019

Does the volume you're providing have appropriate permissions for the user you're trying to run as? (or wide enough for that user to create/use it regardless like 777?)

@drvan
Copy link

drvan commented Aug 9, 2019

Forgive my lack of docker knowledge - I'm not providing a volume via -v or --mount when I test locally, so to answer your question, I'm not entirely sure.

While digging into this over the past few hours, I think I solved this for openshift - my understanding of openshift is that a random uid is used who exists in gid 0 - so for this use case, I've added the following:

RUN chgrp -R 0 /opt/couchdb && \
    chmod -R g=u /opt/couchdb

right before the VOLUME directive, as recommended by openshift docs. This works for non-root users in the root group (e.g. --user 1000:0), but I have no idea what other consequences this may have on the container itself, or if this is generalized enough to meet other use cases (e.g. dealing with root mounted volumes?). In short, I was hoping there was a right way to do this, but it looks like that might not be the case.

Sorry this is a bit of a word salad - there's a lot unknown unknowns for me here, trying my best to grok docker/permissions/openshift/couchdb at once.

@tianon
Copy link

tianon commented Aug 9, 2019

You can probably turn that into a more "generic" solution with chmod 777 /opt/couchdb instead of messing with the root group.

@wohali
Copy link
Member

wohali commented Aug 9, 2019

@drvan We've had a lot of problems with chmod inside of the startup script, especially recursive ones, causing severe performance problems.

If you're going to do a PR suggesting we change any of that, please review prior bugs on this (I don't have time to dig them out now) before putting the PR up. Thanks :)

@drvan
Copy link

drvan commented Aug 11, 2019

Thanks for the advice all - I've come to realize that my goal (running on OpenShift) is slightly different than the goal discussed here, and much more closely related to #71 , (this comment in particular) but I still feel I can contribute in some shape or form. I've narrowed down what I believe is feasible to one of the following:

  • Make permissions so wide that any uid/gid can be used (at the expense of running chmod -R 777 /opt/couchdb which feels like a bad idea outside of a docker container, but not sure if this is accepted practice in the docker world).
  • Modify the image so it can be run completely as couchdb (e.g. --user 5984:5984), but no other user. This aligns much more closely with the linked PRs above for other images. As an example, you can pull the cassandra image above, pass --user, but it will only work (for me, at least) if you pass the cassandra uid of 999. This checks the "make the image able to be run as non-root" box and requires minimal changes, but some orchestration frameworks don't let you pick an explicit uid easily as far as I can tell.
  • Modify the image so it can be run as any user as long as they belong to the root group (the OpenShift model). I suspect I'm not the only person who wants to use this on OpenShift. This would however drastically change the user/group model, and I'm unsure of any consequences this would introduce either within the application itself, or through docker.
  • Don't modify the image at all, and instead contribute documentation (somewhere) about how to create a wrapper image so that it can be modified in any of the above ways.

Please let me know which approach (if any) you'd like to me to take, and I can submit a PR as soon as possible. @wohali per your note, I've read through the issues you mentioned with respect to chmod and performance, and I'll ensure any proposed change won't re-introduce those issues.

@wohali
Copy link
Member

wohali commented Aug 11, 2019

I bow to @tianon 's advice on what the best approach is here, presumably that's #2 above - though it looks like perhaps cassandra's image may not be the best option? Can you confirm?

@willholley
Copy link
Member

willholley commented Aug 11, 2019 via email

@wohali
Copy link
Member

wohali commented Aug 12, 2019

Hi @willholley ,

I think your suggestion is out of scope for this issue. If you would like to pursue this further, please start a new thread on dev@couchdb.apache.org, not in this ticket.

Personally, given it's such a major change to the control surface, I think it would be better to defer anything like this until 4.0 - for the principle of least surprise.

@tianon
Copy link

tianon commented Aug 17, 2019

There are other examples which use 777 for some directories (mysql does for /var/run/mysqld, golang does for /go, ruby does for GEM_HOME, rabbitmq does for both the RabbitMQ data directory+/etc/rabbitmq, php does for /var/www/html, postgres does for /var/lib/postgresql/data, docker does 1777 for /certs, redmine does 1777 for its own tmp dir), and the typical downsides of doing so are lessened in a Docker context.

@wohali
Copy link
Member

wohali commented Aug 26, 2019

Looks like we're going to close this with #151. @tianon if anything there looks amiss, please speak now!

willholley added a commit that referenced this issue Sep 2, 2019
 * Adds guards around entrypoints commands that require root
 * Broaden permissions within the container filesystem to allow
   access by non-couchdb users.
 * Added an example to the documentation which specifies `--user`.

Fixes #147
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants