-
Notifications
You must be signed in to change notification settings - Fork 4
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
Running Docker Containers as Current Host User #14
Comments
Thanks for your detailed explanation @jtreminio, was really helpful 👏 👏 |
Insightful and helpful, however I have a question, we are looking to use something like this approach to dynamically setup user(s) inside the container to match host user ids, you know, to deal with permissions for volumes and so on, however, we want to be able to build 1 image that we can then run in different environments, with some kind of parameters that pass the actual user id from that particular environment, we would like to avoid having to build a different image per environment, any insight into how to resolve current user and pass to compose yml? Preferably without using previous external shell steps, because docker restart policies would not be able to run that in the event of a container restart, or can it? |
Great article! I've always got halfway to it. It's nice to use this as a reference. |
Juan--What a great a article and clever solution. I struggled with this for months and can't for the life of me understand why your info isn't part of the Docker docs. I'm now running Docker in my container as my local user and it's great (and it worked the first damn time! Nothing ever does that for me!). Next time you make a trip down from Dallas to San Antonio I'll buy lunch! Thank you, again. |
@dcaballero Unfortunately the ID reassignment needs to happen at the pre-boot stage. If you simply run a script in a running container that does all the work, it may not have your expected results. Any users currently running a process in the container may experience issues since their user ID would technically no longer exist. |
@edulan @lephleg @rogerpence Thank you all for the kind words! I am glad you may have found some use for this! |
I was wondering if only mapping the user IDs would work. If the current user belongs to root group, things will work out just fine -
Any problems with this solution? |
I tried all kind of approaches, but when you hop projects you can't really expect to have anything readily available in place. Custom scripting takes time to write and as a contractor you are expected to jump right in from pretty much day one. Here is an excerpt from one of the
Best part of this approach is that I do not need to modify images or containers in any way, I can spin up already built image and bind to local files. I can bind any local user to any containerized user id, all at the same time. |
Hello, Thank you for great article. I try to modify redis image
part of my composer file
I start it by shell script
Then I check /data folder on my host
Why do I get redis under root? My current user is 1000:1000 |
@akorz If you share a directory with a container, and the directory did not exist before running the docker command, docker creates the directory as the user running the daemon (usually root). |
@jtreminio |
Awesome! |
Hello thanks a lot |
Hi, thanks for this apporach and clarification , however I still see a problem if we mount a volume here my compose file:tests: in Dockerfile, I am using your approach
|
Thanks for a comprehensive write-up of the issues and solutions. It seems that for your solution to work the id for the internal user account defined at build time needs to match the id for the host account used at run time. This is fine if you're building and running on the same machine but won't necessarily work if you're using different machines, e.g. building the image on a CI server but running on a developer's workstation, possibly in a different company or with a different Linux distribution. Would you agree that this is a concern or have I missed something? |
I'm going to use this for strategy for a docker container I'm building to run ansible playbooks that have a lot of dependencies. The problems to solved were keeping ssh keys secure and developing the container on Mac but running it on Linux in production. Having Ansible run as the current user and using ssh keys on the host machines saves me having to make a service user and giving it ssh keys and access to our servers. I'll need to do that later once I move manual processes into pipelines ( like Jenkins ) , but that's a problem to be solved another day :) |
@jtreminio - You saved our day!! let me know if you are visiting Tamil Nadu, India. I'll buy Briyani for you!!! :) After so many attempts/google searches, your blog gave us proper guidelines on how to solve the issue. |
Hi, I'm getting the following error, when I start the container:
My
My
|
Works great for me, error: I was able to solve it by change the
|
Great article, thank you so much. Very complete and so clear nice work. |
Very helpful! I'm trying to get this to work for Tdarr. For my model, I need to change your example from www-data to Tdarr, but otherwise it should be quite similar. Dockerfile
Build command
However, when I try to build the new image, I get an error when the userdel command runs. It seems like a process is already running under the user Tdarr, but why would that be true during the build process?
Any tips? |
@carlfischerjba I have that same problem. I can't bind the image to a specific user in build time, I need to distribute an image and make it work in other environments that I don't own. Still doing research, if anybody finds a solution for that please share :) |
@gpiffaretti Did you notice the article on the very first post of this issue? All basic information are in that excellent article and in some of the commends in this github issue. Try to understand everything and ask specific questions here. The article was made to solve exactly your problem I think. |
@jeff47 You are trying to override the user If that worked nothing from the image |
@gpiffaretti wrote:
You can specify the user in your The advantage is that you're not running as root and that any files written into bind mounts will be owned by you rather than root or some other arbitrary uid that may not match a user account on the host. You also do not need to match the image to the host or agree on a particular uid to be present everywhere the app might be deployed. You can't enforce running as non-root in the image itself since it's dependent on the right steps being taken at runtime but you could combine it with the suggestions in the article and create another non-root user to use as the default (replace the Depending on how your application is designed, there can be some issues around file permissions. You shouldn't be writing anything inside the container as a best practice but if you do there may be issues since the non-root user may not be allowed to write in certain locations. Writing to a volume or bind mount is ok but again it may not be writable by the new user, especially if you don't know what that user is going to be until runtime. In some images, I've had to set very relaxed permissions or certain directories so that when a volume is mounted there it gets permissions that allow any user to write. Not ideal but the best I've come up with so far. The ideal situation is if you never write anything to disk and only interact with services over the network, then permissions are not an issue and you can run your container as any user. |
@jeff47 I guess the base image sets FROM haveagitgat/tdarr:latest
ARG PUID
ARG PGID
USER root
RUN userdel -f Tdarr && \
groupdel Tdarr && \
groupadd -g ${PGID} Tdarr && \
useradd -l -u ${PUID} -g Tdarr Tdarr && \
chown -R ${PUID}:${PGID} /home/Tdarr/Tdarr
USER ${PUID}:${PGID} |
Looking at the In addition to setting the user it installs things in that user's home directory I'm not familiar with the software in question but my understanding is that using |
@jtreminio how did you get this working? I can't get the user ID and group ID dynamically in the command, docker returns an error. See this longer issue report by me: docker-library/php#1067 Update: got it working, ARG's need to be added below FROM too if you need them during the build process. |
I split the Docker run into multiple steps:
See https://devops.sentianse.com/blog/docker-run-mirror-host-user for details. |
still running strong, this one:) one important caveat: if the directory, which one bind-mounts to the container, does not exist yet on the host machine, that folder will be created by docker and, this took me several hours to understand, that folder will have root owner with 755 permissions. if the container (and its internal non-root user) then tries to create files in that directory it will consequently fail with it doesn't matter what one does in the image instructions, the problem is the bind mount. it works with named (docker managed) volumes etc. and there seems to be absolutely no way to work around that since it happens at container creation time and there's no way hooking into that. once it's created you also can't if anyone finds a proper solution I'm all ears. in the meantime I simply check in the entrypoint script if the directory inside the container has the proper owner and permissions and fail the run if it doesn't, notifying the user to create that directory before starting the container. that's the best UX I could come up with.. |
Excellent post @jtreminio 👏👏👏 Here I leave the Alpine version of your fix, but all the kudos are for you! FROM php:8-alpine
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN deluser --remove-home www-data &&\
addgroup -S -g ${GROUP_ID} www-data &&\
adduser -S -u ${USER_ID} -D www-data www-data &&\
chown www-data:www-data -R /app |
Last item on the "dockerise my world" todo list... make my containers run as non-root users. Aha ... and here I find the absolute Bible on the subject. Well done :-) |
hey guys, what about this : ARG USER_ID=1000 RUN find / -not -path "*/proc/*" -group www-data -exec chgrp -h ${GROUP_ID} {} ; RUN usermod -u ${USER_ID} www-data i'm excluding */proc/* cose otherwise this trigger an error while building (dont know why, but this should refer to some docker internal configuration) i'm actually trying this possibility, but not sure if that work well yet ! :) |
WARNING: Do NOT use If you think about it, Why give your process the abiilty to overwrite files that it should never overwrite? This is increasing the attack surface for hackers. So most likely you can get away with chown on just a couple of folders, with no -R. Alternatively use Follow principle of least privileges: Focus on making all necessary files readable, only make a few folders writable (/tmp etc). |
the fact that i'm using -R (using find /) is that i'm not always aware of with folder where created/used during the build process of a docker image i didnt builded myself. also note that i'm filtering all folder/file with a specific -group and -user to filter only file that are already owned by www-data so i'm not applying a chown on ALL file, but only previous file that was owned by www-data with older ID, and i apply the new ID to those folders/files :) for php-apache and another container with php and composer, the build time for those command are instant-like ... also note that using this solution make the remove of www-data (or any other user/group) not necessary anymore, and also let you modify permission without be aware of wich file was created previously by this user during the build process of the image you are importing FROM. to be more clear, i'm not using a chmod -R at all, i'm just applying new user_id/group_id for file owned by www-data then i change the uid/gid of www-data to match this specific user_id/group_id. in fact when i do a exec sh with docker inside my container root owned file are still owned by root but for exemple var/html are owned by www-data with the proper user_id/group_id defined with ARG. edit : i guess you missreading what my command do ... read it again cose "Focus on making all necessary files readable, only make a few folders writable (/tmp etc)." is exactly what those command do actually. |
here is a exemple for composer with php-fpm dockerfile : FROM php:${PHP_VERSION}-fpm ARG USER_ID=1000 RUN apt-get -qqy update; RUN apt-get -qqy install libicu-dev libpng-dev git zip unzip RUN docker-php-ext-configure intl && docker-php-ext-install intl RUN docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql RUN docker-php-ext-install gd COPY --from=selectedcomposer /usr/bin/composer /usr/bin/composer WORKDIR /var/www/app/ RUN find / -not -path "*/proc/*" -group www-data -exec chgrp -h ${GROUP_ID} {} ; RUN usermod -u ${USER_ID} www-data RUN chown www-data:www-data /var/www USER www-data RUN mkdir /var/www/.composer docker-composer.yml networks: and the output of ls -l from /var outpout of /etc/passwd : everything work perfectly :) |
Hi @jtreminio, while this is a fascinating and insightful read, from whence I learned a lot even on topics outside the main focus, I must ultimately defer to standard practices and NOT use your quote unquote solutions because frankly, they are really unsecure workarounds that bring more hassle that they fix. |
You mentioned that this is not necessary when running docker on windows. when I cli into the running container, items are owned by root and the abc user. If i look in the passwd file, I don't see the host user from the windows machine. |
great article - i learned a lot here. some questions:
|
https://jtreminio.com/blog/running-docker-containers-as-current-host-user/
The text was updated successfully, but these errors were encountered: