Recommended base image
As suggested in my comment, you could write a Dockerfile that looks like:
FROM python:3
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir nibabel pydicom matplotlib pillow med2image
# Note: we had to merge the two "pip install" package lists here, otherwise
# the last "pip install" command in the OP may break dependency resolution…
CMD ["cat", "/etc/os-release"]
And the command example above could confirm at runtime (docker build --pull -t test . && docker run --rm -it test) that this image is based on the GNU/Linux distribution "Debian stable".
Generic Dockerfile template
Finally to give a comprehensive answer, note that a good practice regarding Python dependencies consists in specifying them in a declarative way in a dedicated text file (in alphabetical order, to ease review and update) so that for your example, you may want to write the following file:
requirements.txt
matplotlib
med2image
nibabel
pillow
pydicom
and use the following generic
Dockerfile
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "./your-daemon-or-script.py"]
To be more precise, this is the approach suggested in the documentation of the Docker official image python, §. How to use this image
Recommended base image
As suggested in my comment, you could write a Dockerfile that looks like:
FROM python:3
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir nibabel pydicom matplotlib pillow med2image
# Note: we had to merge the two "pip install" package lists here, otherwise
# the last "pip install" command in the OP may break dependency resolution…
CMD ["cat", "/etc/os-release"]
And the command example above could confirm at runtime (docker build --pull -t test . && docker run --rm -it test) that this image is based on the GNU/Linux distribution "Debian stable".
Generic Dockerfile template
Finally to give a comprehensive answer, note that a good practice regarding Python dependencies consists in specifying them in a declarative way in a dedicated text file (in alphabetical order, to ease review and update) so that for your example, you may want to write the following file:
requirements.txt
matplotlib
med2image
nibabel
pillow
pydicom
and use the following generic
Dockerfile
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "./your-daemon-or-script.py"]
To be more precise, this is the approach suggested in the documentation of the Docker official image python, §. How to use this image
Some of the other answers/comments are suggesting to change your base image but if you want to keep your ubuntu 16.04 you can also simply specify your version of pip/python to use pip3 or pip3.5 like shown below.
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y --no-install-recommends \
python3.5 \
python3-pip \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN pip3 install nibabel pydicom matplotlib pillow
RUN pip3 install med2image
» pip install docker
Dockerfile Error RUN pip install -r requirements.txt
python - Setting a non-root user in a Dockerfile and installing pip packages - Stack Overflow
RUN pip install --upgrade pip and RUN pip install -r requirements.txt not working
Making library pip-installable vs. creating Docker image with the library inside
Videos
If you want to install in one image and run in the other, it's often easier to install into a virtualenv and copy the virtualenv, because then you get all the files, e.g. data files and executables and such like. Copying site-packages doesn't get you that.
You can then chown the virtualenv to your new user as you copy it.
Something like
FROM python:3.9-slim AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential gcc
RUN python -m venv /opt/venv
# Make sure we use the virtualenv:
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY setup.py .
COPY myapp/ .
RUN pip install .
FROM python:3.9-slim AS build-image
RUN useradd --create-home appuser
USER appuser
COPY --from=compile-image --chown=appuser /opt/venv /opt/venv
# Make sure we use the virtualenv:
ENV PATH="/opt/venv/bin:$PATH"
CMD ['myapp']
Note the use of --chown in COPY to ensure it changes ownership as you copy it.
(Based on https://pythonspeed.com/articles/activate-virtualenv-dockerfile/, https://pythonspeed.com/articles/multi-stage-docker-python/ https://pythonspeed.com/articles/root-capabilities-docker-security/)
You can add USER some_user to your Dockerfile o run with a specific user
cat Dockerfile
...
USER site
RUN echo 'RUNNING as $USER'
I ran the image
Or at execution
docker run -it --user site image_name bash
I don't know if there are limitations in the USER instruction só you could try add RUN root in the intermediate container and then RUN site in the final container.
, maybe the user you want is www-data
Hi.
In the company I'm working for, there's a Python library (repo) which all data scientists are currently using. They want to create a Docker image in ECR which will come with the project already inside of it and appended to the `PYTHONPATH` so they can use it inside SageMaker notebooks. My team insists that making it pip-installable is the appropriate way to distribute it.
What pros and cons do you see in each approach?
Note: all the library's dependencies are pip-installable (so no need to install anything via `apt-get`, etc.)
Hello,
I try to run my dockerfile on a RaspberryPi 4 with raspian-buster and I get this error:
Sending build context to Docker daemon 14.56MB
Step 1/9 : FROM python:slim
---> 6beb215998ec
Step 2/9 : WORKDIR /bot
---> Using cache
---> fd86572b0023
Step 3/9 : COPY libs-py.txt .
---> Using cache
---> f0f89e156d7a
Step 4/9 : RUN pip install --upgrade pip
---> Running in f8b9b524a31d
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.10/site-packages/pip/__main__.py", line 29, in <module>
from pip._internal.cli.main import main as _main
File "/usr/local/lib/python3.10/site-packages/pip/_internal/__init__.py", line 4, in <module>
from pip._internal.utils import _log
File "/usr/local/lib/python3.10/site-packages/pip/_internal/utils/_log.py", line 8, in <module>
import logging
File "/usr/local/lib/python3.10/logging/__init__.py", line 57, in <module>
_startTime = time.time()
PermissionError: [Errno 1] Operation not permitted
The command '/bin/sh -c pip install --upgrade pip' returned a non-zero code: 1
inxi: Argument "Raspberry Pi 4 Model B Rev 1.2" isn't numeric in sprintf at /usr/bin/inxi line 6969. CPU: Quad Core ARMv7 v7l (-MCP-) speed/min/max: 1500/600/1500 MHz Kernel: 5.10.63-v7l+ armv7l Up: 14d 8h 00m Mem: 528.8/3914.7 MiB (13.5%) Storage: 59.48 GiB (49.3% used) Procs: 176 Shell: bash 5.0.3 inxi: 3.0.32
On my Linux mashine with Linux Mint does it run without any problems. Has anybody a idea how i can solve this problem?
I have been trying to use the module "bonsai" in my AWS Lambda function. Unfortunately, the module does not work in a Linux Environment via pip installation, therefore I have to manually install it. With that being said I created a Docker Container that will include all the needed modules for my project.
MyDESKTOP:~/lambda_container$ ls
Dockerfile bonsai lambda_function.py requirements.txt
Currently, in my project directory, the "bonsai" folder includes all the code needed for that module:
MyDESKTOP:~/lambda_container/bonsai$ ls init.py, active_directory, ldapclient.py, ldapreference.py, pool.py, utils.py, pycache, asyncio, ldapconnection.py, ldapurl.py, py.typed, _bonsai.cpython-311-x86_64-linux-gnu.so, errors.py, ldapdn.py, ldapvaluelist.py, tornado _bonsai.py, geventldapentry.py, ldif.py, trio
I am calling the module in my lambda_function.py file using import bonsai. When I start up my container to test I get this error: {"errorMessage": "Unable to import module 'lambda_function': No module named 'bonsai'"
Here is my DockerFile:
FROM public.ecr.aws/lambda/python:3.11
COPY requirements.txt ${LAMBDA_TASK_ROOT} COPY bonsai ${LAMBDA_TASK_ROOT}
RUN pip install setuptools RUN pip install boto3 RUN pip install cryptography RUN pip install ldap3
COPY lambda_function.py ${LAMBDA_TASK_ROOT}
CMD [ "lambda_function.handler" ]In conclusion, How do you properly manually install a Python module in Docker?
Thank Y'all in advance!
I'm not sure why people have downvoted you, other than there is a well documented and easy way to go about this.
Docker images are layered, and you can build all your essential-for-all-images packages into one new docker image of our own making, and then extend from that.
For example, when you write your docker file, your first line will be
FROM someothercontainer
What you can do is then create a new image to use in your "FROM" in all future containers that you write, that will have this built in. The trivial example is to build a container something like
FROM ubuntu
apt-get install python
And then build this image as my-image-with-python-installed or whatever works.
Then, in the later container where you want to install your own unique-to-each-container stuff, you write your Dockerfile as such:
FROM my-image-with-python-installed
ADD my-local-package
...
The documentation on Docker's page is a bit low level as they want you to build the smallest base images you can, but you can find it here: https://docs.docker.com/develop/develop-images/baseimages/
Your documentation for the FROM command comes in here https://docs.docker.com/engine/reference/builder/#from but you'll need to build your base image first, but there is loads of articles out there on how to do that.
Edit:
It's very common to have a base image stored in a repository, especially if the contents don't change. This way you can access it from different build machines and don't have to rebuild it often if at all, setting up small local repositories is very easy, and many artifact management tools have this feature built in as well. If, however, you're building images on the fly but they all still have a common base it isn't necessary to store that in a repository - you just build the base image first and then as its local to that build machine all other images built on that machine will be able to access it.
A nice pattern for a Dockerfile is something like this:
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y python3 python3-pip
COPY requirements.txt /tmp/base_requirements.txt
RUN python3 -m pip install -r /tmp/base_requirements.txt
COPY my_package_name/ /usr/lib/python3.6/my_package_name/
This way the package is accessible in the path and can be imported.