changing python version in docker - python

I am trying to have this repo on docker: https://github.com/facebookresearch/detectron2/tree/main/docker
but when I want to docker compose it, I receive this error:
ERROR: Package 'detectron2' requires a different Python: 3.6.9 not in '>=3.7'
The default version of the python I am using is 3.10 but I don't know why through docker it's trying to run it on python 3.6.9.
Is there a way for me to change it to a higher version of python while running the following dockerfile?
FROM nvidia/cuda:11.1.1-cudnn8-devel-ubuntu18.04
# use an older system (18.04) to avoid opencv incompatibility (issue#3524)
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
python3-opencv ca-certificates python3-dev git wget sudo ninja-build
RUN ln -sv /usr/bin/python3 /usr/bin/python
# create a non-root user
ARG USER_ID=1000
RUN useradd -m --no-log-init --system --uid ${USER_ID} appuser -g sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER appuser
WORKDIR /home/appuser
ENV PATH="/home/appuser/.local/bin:${PATH}"
RUN wget https://bootstrap.pypa.io/pip/3.6/get-pip.py && \
python3 get-pip.py --user && \
rm get-pip.py
# install dependencies
# See https://pytorch.org/ for other options if you use a different version of CUDA
RUN pip install --user tensorboard cmake # cmake from apt-get is too old
RUN pip install --user torch==1.10 torchvision==0.11.1 -f https://download.pytorch.org/whl/cu111/torch_stable.html
RUN pip install --user 'git+https://github.com/facebookresearch/fvcore'
# install detectron2
RUN git clone https://github.com/facebookresearch/detectron2 detectron2_repo
# set FORCE_CUDA because during `docker build` cuda is not accessible
ENV FORCE_CUDA="1"
# This will by default build detectron2 for all common cuda architectures and take a lot more time,
# because inside `docker build`, there is no way to tell which architecture will be used.
ARG TORCH_CUDA_ARCH_LIST="Kepler;Kepler+Tesla;Maxwell;Maxwell+Tegra;Pascal;Volta;Turing"
ENV TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST}"
RUN pip install --user -e detectron2_repo
# Set a fixed model cache directory.
ENV FVCORE_CACHE="/tmp"
WORKDIR /home/appuser/detectron2_repo
# run detectron2 under user "appuser":
# wget http://images.cocodataset.org/val2017/000000439715.jpg -O input.jpg
# python3 demo/demo.py \
#--config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \
#--input input.jpg --output outputs/ \
#--opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl

You can use pyenv: https://github.com/pyenv/pyenv
Just google docker pyenv container, will give you some entries like: https://gist.github.com/jprjr/7667947
If you follow the gist you can see how it has been updated, very easy to update to latest python that pyenv support. anything since 2.2 to 3.11
Only drawback is that container becomes quite large because it holds all glibc development tools and libraries to compile cpython, but often it helps in case you need modules without wheels and need to compile because it is already there.
Below is a minimal Pyenv Dockerfile Just change the PYTHONVER or set a --build-arg to anything pythonversion pyenv support have (pyenv install -l):
FROM ubuntu:22.04
ARG MYHOME=/root
ENV MYHOME ${MYHOME}
ARG PYTHONVER=3.10.5
ENV PYTHONVER ${PYTHONVER}
ARG PYTHONNAME=base
ENV PYTHONNAME ${PYTHONNAME}
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y locales wget git curl zip vim apt-transport-https tzdata language-pack-nb language-pack-nb-base manpages \
build-essential libjpeg-dev libssl-dev xvfb zlib1g-dev libbz2-dev libreadline-dev libreadline6-dev libsqlite3-dev tk-dev libffi-dev libpng-dev libfreetype6-dev \
libx11-dev libxtst-dev libfontconfig1 lzma lzma-dev
RUN git clone https://github.com/pyenv/pyenv.git ${MYHOME}/.pyenv && \
git clone https://github.com/yyuu/pyenv-virtualenv.git ${MYHOME}/.pyenv/plugins/pyenv-virtualenv && \
git clone https://github.com/pyenv/pyenv-update.git ${MYHOME}/.pyenv/plugins/pyenv-update
SHELL ["/bin/bash", "-c", "-l"]
COPY ./.bash_profile /tmp/
RUN cat /tmp/.bash_profile >> ${MYHOME}/.bashrc && \
cat /tmp/.bash_profile >> ${MYHOME}/.bash_profile && \
rm -f /tmp/.bash_profile && \
source ${MYHOME}/.bash_profile && \
pyenv install ${PYTHONVER} && \
pyenv virtualenv ${PYTHONVER} ${PYTHONNAME} && \
pyenv global ${PYTHONNAME}
and the pyenv config to be saved as .bash_profile in Dockerfile directory:
# profile for pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"
build with:
docker build -t pyenv:3.10.5 .
Will build the image, but as said it is quite big:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pyenv 3.10.5 64a4b91364d4 2 minutes ago 1.04GB
very easy to test any python version only changing PYTHONVER
docker run -ti pyenv:3.10.5 /bin/bash
(base) root#968fd2178c8a:/# python --version
Python 3.10.5
(base) root#968fd2178c8a:/# which python
/root/.pyenv/shims/python
if I build with docker build -t pyenv:3.12-dev --build-arg PYTHONVER=3.12.dev . or change the PYTHONVER in the Dockerfile:
docker run -ti pyenv:3.12-dev /bin/bash
(base) root#c7245ea9f52e:/# python --version
Python 3.12.0a0

This is an open issue with facebookresearch/detectron2. The developers updated the base Python requirement from 3.6+ to 3.7+ with commit 5934a14 last week but didn't modify the Dockerfile.
I've created a Dockerfile based on Nvidia CUDA's CentOS8 image (rather than Ubuntu) that should work.
FROM nvidia/cuda:11.1.1-cudnn8-devel-centos8
RUN cd /etc/yum.repos.d/ && \
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && \
dnf check-update; dnf install -y ca-certificates python38 python38-devel git sudo which gcc-c++ mesa-libGL && \
dnf clean all
RUN alternatives --set python /usr/bin/python3 && alternatives --install /usr/bin/pip pip /usr/bin/pip3 1
# create a non-root user
ARG USER_ID=1000
RUN useradd -m --no-log-init --system --uid ${USER_ID} appuser -g wheel
RUN echo '%wheel ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER appuser
WORKDIR /home/appuser
ENV PATH="/home/appuser/.local/bin:${PATH}"
# install dependencies
# See https://pytorch.org/ for other options if you use a different version of CUDA
ARG CXX="g++"
RUN pip install --user tensorboard ninja cmake opencv-python opencv-contrib-python # cmake from apt-get is too old
RUN pip install --user torch==1.10 torchvision==0.11.1 -f https://download.pytorch.org/whl/cu111/torch_stable.html
RUN pip install --user 'git+https://github.com/facebookresearch/fvcore'
# install detectron2
RUN git clone https://github.com/facebookresearch/detectron2 detectron2_repo
# set FORCE_CUDA because during `docker build` cuda is not accessible
ENV FORCE_CUDA="1"
# This will by default build detectron2 for all common cuda architectures and take a lot more time,
# because inside `docker build`, there is no way to tell which architecture will be used.
ARG TORCH_CUDA_ARCH_LIST="Kepler;Kepler+Tesla;Maxwell;Maxwell+Tegra;Pascal;Volta;Turing"
ENV TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST}"
RUN pip install --user -e detectron2_repo
# Set a fixed model cache directory.
ENV FVCORE_CACHE="/tmp"
WORKDIR /home/appuser/detectron2_repo
# run detectron2 under user "appuser":
# curl -o input.jpg http://images.cocodataset.org/val2017/000000439715.jpg
# python3 demo/demo.py \
#--config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \
#--input input.jpg --output outputs/ \
#--opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl
Alternatively, this is untested as the following images don't work on my machine (because I run arm64) so I can't debug...
In the original Dockerfile, changing your FROM line to this might resolve it, but I haven't verified this (and the image mentioned in the issue (pytorch/pytorch:1.10.0-cuda11.3-cudnn8-devel) might work as well.
FROM nvidia/cuda:11.1.1-cudnn8-devel-ubuntu20.04

Related

Install local package through a Dockerfile

I have started learning Docker and I have developed a Python package (not published anywhere, it is just used internally) that installs and works fine locally (here I will call it mypackage). However, when trying to install it in a Docker container, Python in the container fails to recognise it even though during the build of the image no error was raised. The Dockerfile looks like this:
# install Ubuntu 20.04
FROM ubuntu:20.04
# update Ubuntu packages
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update
RUN apt upgrade -y
RUN apt install -y apt-utils \
build-essential \
curl \
mysql-server \
libmysqlclient-dev \
libffi-dev \
libssl-dev \
libxml2-dev \
libxslt1-dev \
unzip \
zlib1g-dev
# install Python 3.9
RUN apt-get install -y software-properties-common gcc && \
add-apt-repository -y ppa:deadsnakes/ppa
RUN apt-get update && apt-get install -y python3.9 python3.9-dev python3.9-distutils python3-pip python3-apt python3.9-venv
# make symlink (overriding default Python3.8 installed with Ubuntu)
RUN rm /usr/bin/python3
RUN ln -s /usr/bin/python3.9 /usr/bin/python3
# copy package files and source code
RUN mkdir mypackage
COPY pyproject.toml setup.cfg setup.py requirements.txt ./mypackage/
COPY src mypackage/src/
# add path
ENV PACKAGE_PATH=/mypackage/
ENV PATH="$PACKAGE_PATH/:$PATH"
# install mypackage
RUN pip3 install -e ./mypackage
CMD ["python3.9", "main.py"]
So the above runs successfully, but if I run sudo docker run -it test_image bin/bash and run pip3 list, the package will not be there and a ModuleNotFoundError when running code depending on mypackage. Interestingly if I create a virtual environment by replacing this:
ENV PACKAGE_PATH=/mypackage/
ENV PATH="$PACKAGE_PATH/:$PATH"
by this:
ENV VIRTUAL_ENV=/opt/venv
RUN python3.9 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
it works. Ideally, I want to know why I need to create a virtual environment and how can I run local packages in a container without creating virtual environments.

Make Docker container use newest version of Python installed

I have a couple of Python modules that I use inside my Docker container and they require a higher version of Python that what's being used. I install Python and install the modules using:
RUN apt-get update || : && apt-get install python3 -y
RUN apt-get install -y python3-pip
COPY requirements.txt /project
RUN pip3 install -r requirements.txt
Expecting I would be using the latest version of Python in my Docker container but when I go into it's shell and run python3 --version is comes as 3.4.2 which is incredibly old for my program. How do I make the default Python to be the latest I installed above without messing over the System-level python?
The image runtime I'm using for the Docker container is: node:9-slim
I don't think you can find a prebuilt python3.9 package on a debian 8 distribution as your environment is pretty old.
The only solution is you build the python3.9 out from source code in your base container. A full workable Dockerfile as next:
FROM node:9-slim
RUN apt update; \
apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev; \
wget https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tgz; \
tar -zxvf Python-3.9.7.tgz; \
cd Python-3.9.7; \
./configure --prefix=/usr/local/python3; \
make && make install; \
ln -sf /usr/local/python3/bin/python3.9 /usr/bin/python3; \
ln -sf /usr/local/python3/bin/pip3.9 /usr/bin/pip3
Verify it:
$ docker build -t myimage:1 .
$ docker run --rm -it myimage:1 python3 --version
Python 3.9.7
$ docker run --rm -it myimage:1 pip3 --version
pip 21.2.3 from /usr/local/python3/lib/python3.9/site-packages/pip (python 3.9)

Setting alias in Dockerfile not working: command not found

I have the following in my Dockerfile:
...
USER $user
# Set default python version to 3
RUN alias python=python3
RUN alias pip=pip3
WORKDIR /app
# Install local dependencies
RUN pip install --requirement requirements.txt --user
When building the image, I get the following:
Step 13/22 : RUN alias pip=pip3
---> Running in dc48c9c84c88
Removing intermediate container dc48c9c84c88
---> 6c7757ea2724
Step 14/22 : RUN pip install --requirement requirements.txt --user
---> Running in b829d6875998
/bin/sh: pip: command not found
Why is pip not recognized if I set an alias right on top of it?
Ps: I do not want to use .bashrc for loading aliases.
The problem is that the alias only exists for that intermediate layer in the image. Try the following:
FROM ubuntu
RUN apt-get update && apt-get install python3-pip -y
RUN alias python=python3
Testing here:
❰mm92400❙~/sample❱✔≻ docker build . -t testimage
...
Successfully tagged testimage:latest
❰mm92400❙~/sample❱✔≻ docker run -it testimage bash
root#78e4f3400ef4:/# python
bash: python: command not found
root#78e4f3400ef4:/#
This is because a new bash session is started for each layer, so the alias will be lost in the following layers.
To keep a stable alias, you can use a symlink as python does in their official image:
FROM ubuntu
RUN apt-get update && apt-get install python3-pip -y
# as a quick note, for a proper install of python, you would
# use a python base image or follow a more official install of python,
# changing this to RUN cd /usr/local/bin
# this just replicates your issue quickly
RUN cd "$(dirname $(which python3))" \
&& ln -s idle3 idle \
&& ln -s pydoc3 pydoc \
&& ln -s python3 python \ # this will properly alias your python
&& ln -s python3-config python-config
RUN python -m pip install -r requirements.txt
Note the use of the python3-pip package to bundle pip. When calling pip, it's best to use the python -m pip syntax, as it ensures that the pip you are calling is the one tied to your installation of python:
python -m pip install -r requirements.txt
I managed to do that by setting aliases in the /root/.bashrc file.
I have followed this example to do get an idea on how to do that
PS I am using that in a jenkins/jenkins:lts container so as I looked around and as #C.Nivs said:
The problem is that the alias only exists for that intermediate layer in the image
So in order to do that I had to find a way to add the following commands:
ENV FLAG='--kubeconfig /root/.kube/config'
RUN echo "alias helm='helm $FLAG'" >>/root/.bashrc
CMD /bin/bash -c "source /root/.bashrc" && /usr/local/bin/jenkins.sh
for the CMD part you have to check the image you are using so you wouldn't interrupt its normal behaviour.

How to install python and ansible in windows docker container

I have my windows docker installed in my windows 10 machine. Now I need to install python and ansible in my docker container.
I got few references to install python and ansible in a Linux machine. But I could not find a source how to install python 3 and ansible in a windows10 docker container.
Once python is installed I can try to install ansible using pip command. But for that I am not sure how to start with python installation first. In docker I have installed Jenkins, and want to run my ansible playbooks in Jenkins. Kindly help. Thanks!
I build an ansible image periodically tracking the devel branch:
# syntax=docker/dockerfile:experimental
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND noninteractive
ENV PATH /ansible/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN apt-get update && \
apt-get -y install \
git \
openssh-client \
python3.7 \
python3.7-dev \
python3-pip \
python3-setuptools \
python3-pygit2 \
build-essential \
libssl-dev \
libffi-dev \
man
RUN groupadd -g 1000 ansible && \
useradd -u 1000 -g ansible -d /home/ansible -m -k /etc/skel -s /bin/bash ansible
RUN mkdir -p -m 0600 ~/.ssh && \
ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone -b devel https://github.com/ansible/ansible.git /ansible && \
chown -R 1000:1000 /ansible
RUN python3 -m pip install -r /ansible/requirements.txt
RUN ln -s /usr/bin/python3 /usr/bin/python
RUN echo '. /ansible/hacking/env-setup' >> /home/ansible/.bashrc
ENTRYPOINT ["/ansible/bin/ansible"]
Note:
ansible is not intended to be run from a windows control
server - you can use Linux containers on Windows
this example uses the docker build
enhancements
the image is configured following the common
environment
setup
for developing ansible modules
Build the image: DOCKER_BUILDKIT=1 docker build --rm --network host -t so:5776957 .
Run the container: docker run --rm --network host -e ANSIBLE_HOME=/ansible -e PYTHONPATH=/ansible/lib so:5776957 localhost -m ping
Instead of installing in container from yourself, you may try to use existing docker image which already have the same already installed. If you still want to build by yourself, you can look at the Dockerfile in the github repo.
https://hub.docker.com/r/zeeshanjamal16/ansibledocker

How to install xapian with Python 3.6 on Ubuntu 16.04?

I installed Python 3.6 on Ubuntu 16.04 on Docker using the ppa:jonathonf/python-3.6 repository. Now I'd like to install xapian so I can use it with Python. I have not found any ready-made packages, so I am trying to build it from sources. I set PYTHON3 and PYTHON3_LIB parameters to point to Python 3.6. During the build process I get the following error:
ImportError: libxapian.so.30: cannot open shared object file: No such file or directory
I tried xapian versions 1.3.7 and 1.4.5 without luck.
How can I install xapian?
Here's a Dockerfile to reproduce my error:
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y software-properties-common python-software-properties
RUN add-apt-repository ppa:jonathonf/python-3.6
RUN apt-get update \
&& apt-get install -y python3-pip docker.io python3.6 python3.6-dev software-properties-common \
python-software-properties build-essential wget unzip cmake python3-sphinx \
&& cd /usr/local/bin \
&& ln -s /usr/bin/python3.6 python
RUN python -m pip install --upgrade pip
# install xapian 1.4.5
RUN apt-get update && apt-get install -y curl uuid-dev zlib1g-dev
WORKDIR /root
RUN curl --silent --show-error --fail --next -O https://oligarchy.co.uk/xapian/1.4.5/xapian-core-1.4.5.tar.xz
RUN curl --silent --show-error --fail --next -O https://oligarchy.co.uk/xapian/1.4.5/xapian-bindings-1.4.5.tar.xz
RUN tar xvf xapian-core-1.4.5.tar.xz
RUN tar xvf xapian-bindings-1.4.5.tar.xz
WORKDIR /root/xapian-core-1.4.5
RUN ./configure && make && make install
WORKDIR /root/xapian-bindings-1.4.5
RUN ./configure PYTHON3=/usr/bin/python3.6 PYTHON3_LIB=/usr/lib/python3.6 --with-python3 && make && make install
RUN python -c "import xapian"
The problem is that the Xapian library (libxapian.so.30) is being installed into /usr/local/lib by default, but Ubuntu doesn't know that it's been put there yet. You can tell it by adding:
RUN ldconfig
after installing the core (so before you change WORKDIR to build the bindings).
There's some helpful information about ldconfig and library search paths on Ubuntu in the answers to this Unix Stackexchange question.

Categories