Add pip requirements to docker image in runtime

ralvarez picture ralvarez · Nov 10, 2016 · Viewed 8.5k times · Source

I want to be able to add some extra requirements to an own create docker image. My strategy is build the image from a dockerfile with a CMD command that will execute a "pip install -r" command using a mounted volume in runtime.

This is my dockerfile:

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get install -y python-pip python-dev build-essential 
RUN pip install --upgrade pip

WORKDIR /root

CMD ["pip install -r /root/sourceCode/requirements.txt"]

Having that dockerfile I build the image:

sudo docker build -t test .

And finally I try to attach my new requirements using this command:

sudo docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash

My local folder "sourceCode" has inside a valid requirements.txt file (it contains only one line with the value "gunicorn"). When I get the prompt I can see that the requirements file is there, but if I execute a pip freeze command the gunicorn package is not listed.

Why the requirements.txt file is been attached correctly but the pip command is not working properly?

Answer

R0MANARMY picture R0MANARMY · Nov 10, 2016

TLDR

pip command isn't running because you are telling Docker to run /bin/bash instead.

docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash
                                                              ^
                                                             here

Longer explanation

The default ENTRYPOINT for a container is /bin/sh -c. You don't override that in the Dockerfile, so that remains. The default CMD instruction is probably nothing. You do override that in your Dockerfile. When you run (ignore the volume for brevity)

docker run -it test

what actually executes inside the container is

/bin/sh -c pip install -r /root/sourceCode/requirements.txt

Pretty straight forward, looks like it will run pip when you start the container.

Now let's take a look at the command you used to start the container (again, ignoring volumes)

docker run -v -it test /bin/bash

what actually executes inside the container is

/bin/sh -c /bin/bash

the CMD arguments you specified in your Dockerfile get overridden by the COMMAND you specify in the command line. Recall that docker run command takes this form

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

Further reading

  1. This answer has a really to the point explanation of what CMD and ENTRYPOINT instructions do

    The ENTRYPOINT specifies a command that will always be executed when the container starts.

    The CMD specifies arguments that will be fed to the ENTRYPOINT.

  2. This blog post on the difference between ENTRYPOINT and CMD instructions that's worth reading.