Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add pip requirements to docker image in runtime

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?

like image 979
ralvarez Avatar asked Nov 10 '16 18:11

ralvarez


People also ask

What is Requirements TXT Docker?

the requirements. txt file is used in the Dockerfile to build the image with the packages. you shouldn't be installing packages in a container manually and saving the image as it's not reproducible. freeze the dependencies to the requirements. txt and in the Dockerfile install dependencies and copy project files.

Can a Docker container run multiple applications?

It's ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application. You can connect multiple containers using user-defined networks and shared volumes.

What is Workdir in Dockerfile?

The WORKDIR command is used to define the working directory of a Docker container at any given time. The command is specified in the Dockerfile. Any RUN , CMD , ADD , COPY , or ENTRYPOINT command will be executed in the specified working directory.


2 Answers

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.

like image 183
Roman Avatar answered Sep 21 '22 03:09

Roman


You may change the last statement i.e., CMD to below.

--specify absolute path of pip location in below statement

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

UPDATE: adding additional answer based on comments.

One thing must be noted that, if customized image is needed with additional requirements, that should part of the image rather than doing at run time.

Using below base image to test:

docker pull colstrom/python:legacy

So, installing packages should be run using RUN command of Dockerfile.
And CMD should be used what app you actually wanted to run as a process inside of container.

Just checking if the base image has any pip packages by running below command and results nothing.

docker run --rm --name=testpy colstrom/python:legacy /usr/bin/pip freeze

Here is simple example to demonstrate the same:

Dockerfile

FROM colstrom/python:legacy
COPY requirements.txt /requirements.txt
RUN ["/usr/bin/pip", "install", "-r", "/requirements.txt"]
CMD ["/usr/bin/pip", "freeze"]

requirements.txt

selenium

Build the image with pip packages Hope you know to place Dockerfile, requirements.txt file in fresh directory.

D:\dockers\py1>docker build -t pypiptest .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM colstrom/python:legacy
 ---> 640409fadf3d
Step 2 : COPY requirements.txt /requirements.txt
 ---> abbe03846376
Removing intermediate container c883642f06fb
Step 3 : RUN /usr/bin/pip install -r /requirements.txt
 ---> Running in 1987b5d47171
Collecting selenium (from -r /requirements.txt (line 1))
  Downloading selenium-3.0.1-py2.py3-none-any.whl (913kB)
Installing collected packages: selenium
Successfully installed selenium-3.0.1
 ---> f0bc90e6ac94
Removing intermediate container 1987b5d47171
Step 4 : CMD /usr/bin/pip freeze
 ---> Running in 6c3435177a37
 ---> dc1925a4f36d
Removing intermediate container 6c3435177a37
Successfully built dc1925a4f36d
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Now run the image If you are not passing any external command, then container takes command from CMD which is just shows the list of pip packages. Here in this case, selenium.

D:\dockers\py1>docker run -itd --name testreq pypiptest
039972151eedbe388b50b2b4cd16af37b94e6d70febbcb5897ee58ef545b1435

D:\dockers\py1>docker logs testreq
selenium==3.0.1

So, the above shows that package is installed successfully.

Hope this is helpful.

like image 22
Rao Avatar answered Sep 18 '22 03:09

Rao