简体   繁体   中英

How to use scl enable to run python3 app in dockerfile

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"]

Note:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM