87

I am making simple image of my python Django app in Docker. But at the end of the building container it throws next warning (I am building it on Ubuntu 20.04):

WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead

Why does it throw this warning if I am installing Python requirements inside my image? I am building my image using:

sudo docker build -t my_app:1 .

Should I be worried about warning that pip throws, because I know it can break my system?

Here is my Dockerfile:

FROM python:3.8-slim-buster

WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
alper
  • 2,919
  • 9
  • 53
  • 102
V.D.
  • 1,215
  • 1
  • 7
  • 17
  • 3
    `npm`, and others, will also give you errors/warnings. It's good practice to not run as root, even within containers. You can create a user, as part of your Dockerfile, and use that to install/build/run. – Justin Aug 05 '21 at 20:43
  • 1
    @KarlKnechtel If I understand correctly, the `RUN pip ...` command in the Dockerfile is run by the container's root user by default, regardless of which host system user invoked `docker build ...`. That is why the accepted answer adds a new user in the Dockerfile. @justin is saying that creating a new docker user is best practices in any case, which is very interesting and perhaps not widely known. – user550701 Aug 30 '21 at 18:27
  • My question was addressed to OP, not to Justin. – Karl Knechtel Aug 30 '21 at 20:18
  • 4
    "Do you understand what is causing the process to run as root?" The question is actually what is causing Pip to run as the 'root' user. It's not sudo. It's actually the docker default behavior. If you want `RUN` commands not to run as root, you have to add a user in the Dockerfile. – user550701 Aug 31 '21 at 05:46

4 Answers4

77

This behavior was introduced in pip 21.1 as a "bug fix".

As of pip 22.1, you can now opt out of the warning using a parameter:

pip install --root-user-action=ignore

You can ignore this in your container by using the environment:

ENV PIP_ROOT_USER_ACTION=ignore

#11035

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • Ha, bug fix! UX de-enhancement. – Kevin Buchs Feb 24 '23 at 15:10
  • As the other answers mention and this answer omits -- this is warning you about a bad practice and a configuration mistake that you've made in your Dockerfile. – pradyunsg Aug 23 '23 at 11:12
  • I don't know if it's a "bad practice" in a container, which is.. containerized into a sandboxed environment as-is. It's highly opinionated for the lowest common denominator @pradyunsg – Maximilian Burszley Aug 25 '23 at 16:32
60

The way your container is built doesn't add a user, so everything is done as root.

You could create a user and install to that users's home directory by doing something like this;

FROM python:3.8.3-alpine

RUN pip install --upgrade pip

RUN adduser -D myuser
USER myuser
WORKDIR /home/myuser

COPY --chown=myuser:myuser requirements.txt requirements.txt
RUN pip install --user -r requirements.txt

ENV PATH="/home/myuser/.local/bin:${PATH}"

COPY --chown=myuser:myuser . .

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
markwalker_
  • 12,078
  • 7
  • 62
  • 99
  • 2
    I still see the warning until I move `RUN pip install --upgrade pip` below `USER myuser` – Mathilda Aug 28 '21 at 23:53
  • 8
    I get `Option d is ambiguous (debug, disabled-login, disabled-password)` because Ubuntu 18.04, `adduser` does not have a `-D` flag – user550701 Aug 31 '21 at 06:26
  • 7
    [Some argue](https://stackoverflow.com/questions/39855304/how-to-add-user-with-dockerfile) that `useradd` is more portable and should be preferred: [Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user) also suggests `useradd` instead. – user550701 Aug 31 '21 at 06:43
  • When I followed this, pip warns that "Running pip as the 'root' user can result in broken permissions". It seems the python docker official recommendation conflicts with pip's official recommendation. How to handle this – doraemon Dec 13 '21 at 10:42
  • shouldn't `RUN pip install --upgrade pip` called after the user is created? – alper Apr 15 '22 at 20:30
  • @alper no, this ensures that the system pip is current before setting up the user and using it. – markwalker_ Apr 15 '22 at 20:58
  • But root user cannot call it due to `Running pip as the 'root' user`error – alper Apr 16 '22 at 09:53
  • @alper it's not an error, it's a warning. So it does run, it just warns you to make sure you're aware of what you're doing – markwalker_ Apr 16 '22 at 09:54
  • 1
    Than its better to call as: `pip install --upgrade pip >/dev/null 2>&1` to suppress the warning since you are aware of what you are doing – alper Apr 16 '22 at 10:05
31

UPDATE 220930

The good news of this answer here is just that you can ignore the warning, but ignoring the warning is not best practice anymore for pip version >=22.1. At the time of writing this answer, the new trick for pip version >=22.1 was not known to me.

pip version >=22.1

Follow the answer of Maximilian Burszley. It was not known to me at the time of writing and allows you to avoid the warning with a tiny parameter.

pip version >=21.1 and <22.1

You can ignore this warning since you create the image for an isolated purpose and it therefore is organizationally as isolated as a virtual environment. Not technically, but that does not matter here.

It usually should not pay off to invest the time and create a virtual environment in an image or add a user as in the other answer only to avoid the warning, since you should not have any issues with this. It might cloud your view during debugging, but it does not stop the code from working.

Just check pip -V and pip3 -V to know whether you need to pay attention not to mistakenly use pip for Python 2 when you want pip for Python 3. But that should be it, and if you install only pip for python 3, you will not have that problem anyway.

pip version <21.1

In these older versions, the warning does not pop up anyway, see the other answer again. And it is also clear from the age of the question that this warning did not show up in older versions.

questionto42
  • 7,175
  • 4
  • 57
  • 90
  • 8
    I'm thinking the same. Wondering if anyone has any objection to this answer! I am not planning to have multiple users inside my docker container, which I inherit from Python:3.9 btw. I don't see why I should make the effort for creating user inside my Dockerfile! It would make it harder to maintain too! – Hossein Kalbasi Jan 13 '22 at 09:52
  • 1
    I object to "you can just ignore that warning" in general; it doesn't take many "just ignore that" things to pile up before important information is getting lost in the warnings. Instead, suppress the warnings you don't want as described in [Maximilian Burszley's answer](https://stackoverflow.com/a/72551258/107294). – cjs Sep 27 '22 at 12:52
  • 1
    @cjs Warnings are not errors. Though I would like to get rid of any warnings, I also do not like adding overhead to the Docker setup. This answer is more about what you do even though you know better. If you need a warning-free setup, go for the other answer, which got my upvote anyway. – questionto42 Sep 28 '22 at 23:27
  • @questionto42standswithUkraine Correct, warnings are not errors. Since we are in full agreement about that, perhaps you should re-read my answer with that in mind. And [Maximilian Burszley's answer](https://stackoverflow.com/a/72551258/107294) does not add any overhead to the Docker setup. – cjs Sep 29 '22 at 09:42
  • @cjs My last comment did not mean to say that you mixed warnings and errors, you did not. This answer here is more to say that this warning does not harm, and that you *can* ignore it. I agree that a tiny parameter is not too much overhead, I will follow the other answer in the future and added an update to the answer here. – questionto42 Sep 29 '22 at 17:13
  • Ok. I explained that warnings that you ignore _do_ cause harm, in my opinion; you disagree. Fair enough, but I guess you've never spent an hour debugging something only to realise that the computer had been explaining the exact problem to you all along, it was just new warning #21 added to the middle of the 20 warnings you'd been displaying but ignoring. – cjs Sep 30 '22 at 14:08
  • @cjs I think that this is just the wording now. I changed the answer, as you may have seen, since I agree with your comments that warnings can lead to confusion. Guess how I came to write an answer here? By debugging legacy containers. Yet, in the legacy code of older containers with an outdated pip version, ignoring this warning is fine, as I see it, since it does not stop the code from working, that is the main thing here. It only harms if you debug and the warning clouds your view (or just takes research time). I made it clearer in the answer. – questionto42 Sep 30 '22 at 16:12
  • Well, I'm glad to hear that we're in agreement there. But I don't think that Pip generates the warning in versions <22.1, does it? – cjs Sep 30 '22 at 16:54
  • @cjs I thought this is what the other answer says: the parameter is only there from v22.1 on. The `WARNING: Running pip as the 'root' user ...` is about the root user that starts pip, therefore this warning should be avoided with the new parameter for `pip`, and that looks as if the warning is thrown by `pip` itself, not by the system. – questionto42 Sep 30 '22 at 19:37
  • 1
    Yes, you're correct; on re-reading I see that the warning appeared in 21.1 and the flag to suppress it appeared later in 22.1. (But I think it's worth changing your third section title from "pip version <22.1 to "pip version ≥21.1 and <22.1", in case someone's wondering why they don't get the warning in some circumstances.) – cjs Sep 30 '22 at 23:23
12

I don't like ignoring warnings, as one day you will oversee an important one.

Here is a good explanation on best docker practices with python. Search for Example with virtualenv and you'll find this:

# temp stage
FROM python:3.9-slim as builder

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc

RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install -r requirements.txt


# final stage
FROM python:3.9-slim

COPY --from=builder /opt/venv /opt/venv

WORKDIR /app

ENV PATH="/opt/venv/bin:$PATH"

Works like charm. No warnings or alike. BTW they also recommend to create a non root user for security reasons.

EDIT: to get rid of all warnings you may also want to add the following entries to the builder part of your Dockerfile (applies for Debian 8.3.x):

ARG DEBIAN_FRONTEND=noninteractive
ARG DEBCONF_NOWARNINGS="yes"

RUN python -m pip install --upgrade pip && \
    ...
HeyMan
  • 1,529
  • 18
  • 32
  • Why did you use `--no-install-recommends`? – alper Apr 15 '22 at 20:35
  • I cannot tell you the core reason since this flag is used by the quoted solution linked in my answer. Here is a general explanation of the `--no-install-recommends` flag: https://askubuntu.com/a/65093/737843. – HeyMan Apr 17 '22 at 07:55
  • 4
    @alper: It's a Docker image. It's not supposed to be used interactively, so you want to install just what is necessary. – MSalters May 04 '22 at 09:25
  • `--no-install-recommends` is a Debian flag for apt-get , so in doesn't install package optional dependencies, see https://unix.stackexchange.com/q/77053/16640 – Franklin Piat May 27 '22 at 08:17
  • I still see a WARNING – Dmitrii Kalashnikov Oct 05 '22 at 12:00
  • I can also use `/usr/local` instead of `/opt` like this: `RUN python3 -m venv --system-site-packages /usr/local;` This way, there's usually no need to explicitly prepend `/usr/local/bin` to PATH, because it is already there (not guaranteed though). I think they are both legit. See also: https://unix.stackexchange.com/questions/11544/what-is-the-difference-between-opt-and-usr-local – nggit Jun 25 '23 at 04:12