Search code examples
dockerpython-2.7pipvirtualenv

Python 2.7 requirements won't install without virtualenv


I'm working on migrating away from a legacy Django 1.6 application that runs on Python 2.7. I still need to be able to run this project, which runs inside a Docker container.

The issue I'm facing is the project's requirements.txt file will only install if I setup a virtual environment, even inside the Docker container!

Can anyone tell me why this fails to install outside the virtual env?

# Use a base image that supports Python 2.7 (required for Django 1.6)
FROM ubuntu:16.04

# Create and set the working directory inside the container
WORKDIR /app

# Copy the project's requirements.txt file to the working directory
COPY requirements.txt /app

# Install some OS requirements
RUN apt-get update && \
    apt-get install -y wget build-essential git libpq-dev libxslt1-dev procps python \
    python-pip python-dev memcached libmemcached-tools postgresql-client apt-file zlib1g-dev \
    libjpeg-dev libxml2-dev libffi-dev libmysqlclient-dev

WORKDIR /app

COPY . /app

# Install project dependencies
RUN pip install --upgrade "pip < 21.0" && pip install virtualenv

# This will fail to complete
# RUN bash -c "pip install --no-cache-dir -r requirements.txt"

# This installs successfully
RUN bash -c "virtualenv /root/venv && source /root/venv/bin/activate && pip install --no-cache-dir -r requirements.txt"

This is my requirements.txt file, and below is the error that happens when I try building without virtualenv:

#0 22.67 Collecting django-livesettings==1.4-14
#0 22.74   Downloading django-livesettings-1.4-14.tar.gz (43 kB)
#0 24.85     ERROR: Command errored out with exit status 1:
#0 24.85      command: /usr/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-kXrMNl/django-livesettings/setup.py'"'"'; __file__='"'"'/tmp/pip-install-kXrMNl/django-livesettings/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-JQXBej
#0 24.85          cwd: /tmp/pip-install-kXrMNl/django-livesettings/
#0 24.85     Complete output (23 lines):
#0 24.85     Couldn't find index page for 'setuptools_hg' (maybe misspelled?)
#0 24.85     No local packages or download links found for setuptools_hg
#0 24.85     Traceback (most recent call last):
#0 24.85       File "<string>", line 1, in <module>
#0 24.85       File "/tmp/pip-install-kXrMNl/django-livesettings/setup.py", line 32, in <module>
#0 24.85         include_package_data = True,
#0 24.85       File "/usr/lib/python2.7/distutils/core.py", line 111, in setup
#0 24.85         _setup_distribution = dist = klass(attrs)
#0 24.85       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 269, in __init__
#0 24.85         self.fetch_build_eggs(attrs['setup_requires'])
#0 24.85       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 313, in fetch_build_eggs
#0 24.85         replace_conflicting=True,
#0 24.85       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 826, in resolve
#0 24.85         dist = best[req.key] = env.best_match(req, ws, installer)
#0 24.85       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1092, in best_match
#0 24.85         return self.obtain(req, installer)
#0 24.85       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1104, in obtain
#0 24.85         return installer(requirement)
#0 24.85       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 380, in fetch_build_egg
#0 24.85         return cmd.easy_install(req)
#0 24.85       File "/usr/lib/python2.7/dist-packages/setuptools/command/easy_install.py", line 657, in easy_install
#0 24.85         raise DistutilsError(msg)
#0 24.85     distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('setuptools_hg')
#0 24.85     ----------------------------------------
#0 24.85 ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

Now I initially thought that this had to do with the lack of pre-built wheels (and the fact that I'm using an Apple M2 chip), but using virtualenv won't change that, would it?

I tried commenting out the django-livesettings package, but then I got other errors. This time with Google Maps (or PyPDF2 if then comment Google Maps):

#0 31.38 Collecting googlemaps==4.2.0
#0 31.46   Downloading googlemaps-4.2.0.tar.gz (40 kB)
#0 33.23     ERROR: Command errored out with exit status 1:
#0 33.23      command: /usr/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-tAn896/googlemaps/setup.py'"'"'; __file__='"'"'/tmp/pip-install-tAn896/googlemaps/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-0kHtMO
#0 33.23          cwd: /tmp/pip-install-tAn896/googlemaps/
#0 33.23     Complete output (23 lines):
#0 33.23     Couldn't find index page for 'requests' (maybe misspelled?)
#0 33.23     No local packages or download links found for requests<3.0,>=2.20.0
#0 33.23     Traceback (most recent call last):
#0 33.23       File "<string>", line 1, in <module>
#0 33.23       File "/tmp/pip-install-tAn896/googlemaps/setup.py", line 39, in <module>
#0 33.23         "Topic :: Internet",
#0 33.23       File "/usr/lib/python2.7/distutils/core.py", line 111, in setup
#0 33.23         _setup_distribution = dist = klass(attrs)
#0 33.23       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 269, in __init__
#0 33.23         self.fetch_build_eggs(attrs['setup_requires'])
#0 33.23       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 313, in fetch_build_eggs
#0 33.23         replace_conflicting=True,
#0 33.23       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 826, in resolve
#0 33.23         dist = best[req.key] = env.best_match(req, ws, installer)
#0 33.23       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1092, in best_match
#0 33.23         return self.obtain(req, installer)
#0 33.23       File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1104, in obtain
#0 33.23         return installer(requirement)
#0 33.23       File "/usr/lib/python2.7/dist-packages/setuptools/dist.py", line 380, in fetch_build_egg
#0 33.23         return cmd.easy_install(req)
#0 33.23       File "/usr/lib/python2.7/dist-packages/setuptools/command/easy_install.py", line 657, in easy_install
#0 33.23         raise DistutilsError(msg)
#0 33.23     distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('requests<3.0,>=2.20.0')
#0 33.23     ----------------------------------------
#0 33.23 ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
------
failed to solve: process "/bin/sh -c bash -c \"pip install --no-cache-dir -r requirements.txt\"" did not complete successfully: exit code: 1

This one is even weirder, because requests<3.0,>=2.20.0 resolves perfectly fine if I simply type pip install requests<3.0,>=2.20.0 on the container shell

Please help!


Solution

  • Try this.

    🗎 Dockerfile

    FROM ubuntu:16.04
    
    RUN apt-get update && \
        apt-get install -y \
            wget \
            build-essential \
            git \
            libpq-dev \
            libxslt1-dev \
            procps \
            python \
            python-pip \
            python-dev \
            memcached \
            libmemcached-tools \
            postgresql-client \
            apt-file \
            zlib1g-dev \
            libjpeg-dev \
            libxml2-dev \
            libffi-dev \
            libmysqlclient-dev
    
    WORKDIR /app
    
    COPY requirements.txt .
    
    RUN pip install --upgrade "pip < 21.0"
    
    RUN pip install setuptools==44.1.1
    RUN pip install -r requirements.txt
    

    🗎 requirements.txt

    amqp==1.4.9
    anyjson==0.3.3
    ask-sdk-core==1.7.0
    ask-sdk-model==1.82.0
    ask-sdk-runtime==1.19.0
    asn1crypto==1.5.1
    Babel==1.3
    BeautifulSoup==3.2.1
    beautifulsoup4==4.3.2
    billiard==3.3.0.23
    bingads==10.4.1
    cachetools==3.1.1
    celery==3.1.10
    certifi==2018.10.15
    cffi==1.15.1
    chardet==4.0.0
    contextlib2==0.6.0.post1
    cryptography==2.1.4
    curlify==2.2.1
    decorator==3.4.0
    Django==1.6.2
    django-appconf==1.0.1
    django-braces==1.4.0
    django-cache-machine==0.9
    django-celery==3.1.10
    django-ckeditor==5.1.0
    django-compressor==1.5
    django-crum==0.6.1
    django-extensions==1.3.3
    django-extra-views==0.6.4
    django-hashers-passlib==0.2
    django-haystack==2.1.0
    django-ipware==1.0.0
    django-keyedcache==1.5.1
    django-livesettings==1.4.post14
    django-oauth-toolkit==0.9.0
    django-oscar==0.6.3
    django-pipeline==1.4.7
    django-redis==4.5.0
    django-rest-swagger==0.3.7
    django-summernote==0.6.3
    django-treebeard==2.0b2
    django-user-agents==0.3.2
    django-widget-tweaks==1.4.1
    django-wpadmin==1.6.3
    django-xhtml2pdf==0.0.3
    djangorestframework==3.2.5
    djangorestframework-jwt==1.11.0
    docopt==0.6.2
    ecdsa==0.18.0
    enum34==1.1.10
    Fabric==1.13.1
    facebook-business==12.0.1
    fedex==2.4.1
    future==1.0.0
    futures==3.4.0
    geoip2==2.1.0
    google-api-python-client==1.7.8
    google-auth==2.16.1
    google-auth-httplib2==0.1.0
    googlemaps==4.2.0
    html5lib==0.9999999
    httplib2==0.18.1
    idna==2.10
    ipaddress==1.0.23
    jsonfield==1.0.3
    klaviyo==2.0.4
    kombu==3.0.37
    lxml==3.3.5
    mailchimp3==2.0.8
    mailsnake==1.6.2
    Markdown==2.4.1
    maxminddb==1.5.4
    MySQL-python==1.2.5
    num2words==0.5.10
    oauth2client==1.5.2
    oauthlib==1.0.1
    paramiko==1.15.0
    passlib==1.7.4
    phonenumbers==5.9.2
    phpserialize==1.3
    Pillow==2.2.2
    psycopg2==2.5.2
    purl==0.8
    pyasn1==0.5.1
    pyasn1-modules==0.3.0
    pycountry==20.7.3
    pycparser==2.21
    pycrypto==2.6.1
    PyJWT==1.7.1
    pyOpenSSL==16.2.0
    PyPDF2==1.28.6
    python-dateutil==2.2
    python-memcached==1.53
    pytz==2013.9
    PyYAML==3.13
    rauth==0.7.3
    raven==6.10.0
    redis==2.10.1
    reportlab==3.5.59
    requests==2.27.1
    rsa==4.5
    simplejson==3.19.2
    six==1.16.0
    sorl-thumbnail==12.3
    South==1.0.2
    stripe==1.37.0
    suds-jurko==0.6
    typing==3.10.0.0
    ua-parser==0.8.0
    Unidecode==0.4.14
    uritemplate==3.0.1
    urllib3==1.24.1
    user-agents==1.1.0
    xhtml2pdf==0.0.6