How can I upgrade pip inside a venv inside a Dockerfile?

Calaf picture Calaf · Sep 7, 2018 · Viewed 11.6k times · Source

While running

$ sudo docker build -t myproj:tag .

I am hit with the message

You are using pip version 10.0.1, however version 18.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

and given recent occasional subtleties manifesting themselves with the error:

"/usr/bin/pip" "from pip import main" "ImportError: cannot import .."

I'd rather yield and indeed upgrade.

And so I add the pip upgrade command in the DockerFile, after the venv is built, since the pip that matters is the one inside the venv (am I getting this right?). So my Dockerfile now has this:

...
RUN python -m venv venv
RUN pip install --upgrade pip
...

But doing so does not avoid the "You are using pip 10.x" message. What am I missing?

Update

Though a promising suggestion, neither

RUN source venv/bin/activate
RUN pip install --upgrade pip

nor

RUN source venv/bin/activate
RUN python -m pip install --upgrade pip

eliminate the "You are using pip version 10.0.1, ..." message.

Answer

David Maze picture David Maze · Sep 10, 2018

The single easiest answer to this is to just not bother with a virtual environment in a Docker image. A virtual environment gives you an isolated filesystem space with a private set of Python packages that don't conflict with the system install, but so does a Docker image. You can just use the system pip in a Docker image and it will be fine.

FROM python:3.7
RUN pip install --upgrade pip
WORKDIR /usr/src/app
COPY . .
RUN pip install .
CMD ["myscript"]

If you really want a virtual environment, you either need to specifically run the wrapper scripts from the virtual environment's path

RUN python -m venv venv
RUN venv/bin/pip install --upgrade pip

or run the virtual environment "activate" script on every RUN command; the environment variables it sets won't carry over from one step to another. (Each RUN command in effect does its own docker run; docker commit sequence under the hood and will launch a new shell in a new container; the Dockerfile reference describes this a little bit.)

RUN python -m venv venv
RUN . venv/bin/activate \
 && pip install --upgrade pip
COPY . .
RUN . venv/bin/activate \
 && pip install .
CMD ["venv/bin/myscript"]

Trying to activate the virtual environment in its own RUN instruction does nothing beyond generate a no-op layer.

# This step does nothing
RUN . venv/bin/activate
# And therefore this upgrades the system pip
RUN pip install --upgrade pip