Im trying to run a python3 application in a docker container using CentOS 7 as the base image. So if I'm just playing with it interactively, I type scl enable rh-python36 bash
That obviously switches my standard python2 environment to the python3.6 environment I install earlier(in the Dockerfile) Now, earlier in the dockerfile I run the following:
SHELL ["scl", "enable", "rh-python36"]
(and many variations of this)
This enables me to do all of my pip installations in this python3 environment. However, when I actually want to run my app.py with CMD, it defaults to the python2. I've tried playing with ENTRYPOINT and variations of CMD, but I cant seem to make the python3 environment active when the container finally runs. How can I get this running correctly with python3?
Here's the dockerfile:
FROM centos:7
RUN mkdir -p /usr/src/app && \
yum install -y centos-release-scl && \
yum install -y rh-python36 && \
yum install -y rh-python36-python-tkinter
SHELL ["scl", "enable", "rh-python36"]
WORKDIR /usr/src/app
COPY . .
WORKDIR /usr/src/app/codeBase
RUN pip install --no-cache-dir -r /usr/src/app/codeBase/requirements.txt
EXPOSE 9000
CMD ["python", "run.py"]
I've also tried the alias solution, but I'm afraid it doesnt change the python exe for the CMD: Here's the totally runnable version with that that still prints out python 2.7.5:
FROM centos:7
RUN mkdir -p /usr/src/app && \
yum install -y centos-release-scl && \
yum install -y rh-python36 && \
yum install -y rh-python36-python-tkinter
WORKDIR /usr/src/app
RUN alias python=$(find / -type f -name "python*" | grep "python3.6$")
CMD ["python", "-V"]
It just seems as though none of this persists in the new shell created with CMD
SHELL
is completely the wrong Dockerfile
command for this. You'll probably want to put that in a RUN
stanza instead.
The purpose of SHELL
is to define the shell used to execute RUN
commands. So something like
SHELL ["sh", "-c"] # The default
RUN echo "foo"
ends up running
sh -c 'echo "foo"'
Of course, replacing SHELL
with a command which doesn't support this use case will simply break the RUN
command for you.
Maybe try something like
FROM centos:7
RUN mkdir -p /usr/src/app && \
yum install -y centos-release-scl && \
yum install -y rh-python36 && \
yum install -y rh-python36-python-tkinter
WORKDIR /usr/src/app
COPY . .
WORKDIR /usr/src/app/codeBase
RUN scl enable rh-python36 pip install --no-cache-dir -r ./requirements.txt
EXPOSE 9000
CMD ["scl", "enable", "rh-python36", "python", "run.py"]
I am leaving this answer up as context to the question, but this does not solve the issue. My attempt was to modify where python
is pointing, but if executing in a RUN
command, the shell will exit and you'll lose the alias
. Modifying the PYTHONPATH
via bash is also a no-go, per this question . Thanks to @tripleee for the catch
Unfortunately, it looks like yum install -y rh-python36
puts that python3.6 in a really weird spot:
find / -type f -name "python*" | grep "python3.6$"
/opt/rh/rh-python36/root/usr/bin/python3.6
You can use that to alias
your python
command in your Dockerfile
:
RUN mkdir -p /usr/src/app && \
yum install -y centos-release-scl && \
yum install -y rh-python36 && \
yum install -y rh-python36-python-tkinter
# Here
RUN alias python=$(find / -type f -name "python*" | grep "python3.6$")
Which should allow you to retain your CMD
and also ties it to the correct site-packages
:
import sys
sys.path
['', '/opt/rh/rh-python36/root/usr/lib64/python36.zip', '/opt/rh/rh-python36/root/usr/lib64/python3.6', '/opt/rh/rh-python36/root/usr/lib64/python3.6/lib-dynload', '/opt/rh/rh-python36/root/usr/lib64/python3.6/site-packages', '/opt/rh/rh-python36/root/usr/lib/python3.6/site-packages']
It looks like this also might remove the need to scl enable
that python environment, as you can then just use python -m pip...
:
# No scl has been run
python -m pip install requests
# running python in the terminal
import requests
r = requests.get('http://google.com')
# runs like a charm
So I figured this out thanks to the answer from C.Nivs and an answer here . The alias works in an interactive shell, but not for the CMD. What I ended up doing was similar, only in my case I'm creating a new executable in /usr/bin that calls the special python36 exe:
RUN echo -e '#!/bin/bash\n$(find / -type f -name "python*" | grep "python3.6$") "$@"' > /usr/bin/py3 && \
chmod +x /usr/bin/py3
CMD ["py3", "-V"]
now py3 runs a script calling the python3 install specifically with whatever argument
Configuring the shell environment variables by overriding them all to use scl_source, as seen from following "Method #2" from Austin Dewey's blog works for me.
FROM centos:7
SHELL ["/usr/bin/env", "bash", "-c"]
RUN \
yum install -y centos-release-scl && \
yum install -y rh-python38-python-devel
ENV \
BASH_ENV="/usr/bin/scl_enable" \
ENV="/usr/bin/scl_enable" \
PROMPT_COMMAND=". /usr/bin/scl_enable"
RUN echo -e "\n\
unset BASH_ENV PROMPT_COMMAND ENV\n\
source scl_source enable rh-python38\n\
" > /usr/bin/scl_enable
RUN \
python3 -m ensurepip && \
python3 -m pip install --upgrade pip && \
python3 -m pip install setuptools wheel
docker build --tag python:3.8-test - < Dockerfile
docker run --rm -i -t python:3.8-test
python --version
Python 3.8.11
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.