You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

构建Docker容器时升级pip报错,寻求问题排查方案

解决CentOS7 Docker镜像中升级pip时的目录非空错误

问题背景

你在基于CentOS 7.2.1511构建Docker镜像时,执行RUN pip install --upgrade pip步骤遇到了卸载旧版本pip失败的错误,具体报错为OSError: [Errno 39] Directory not empty: '/usr/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches'

你的Dockerfile内容如下:

FROM centos:7.2.1511
RUN yum install -y epel-release && yum repolist
RUN yum install -y python-pip python-devel
RUN pip install --upgrade pip
RUN yum install -y --enablerepo=epel httpd mod_wsgi openldap-devel mariadb-devel yum-plugin-ovl git
RUN yum install -y gcc
VOLUME ["/var/www/website.com/"]
WORKDIR /var/www/website.com/
ADD requirements/ requirements/
RUN pip install -i http://local.pypi:8080/root/pypi/ --trusted-host local-web-test01 -r requirements/base.txt -v
RUN rm /etc/httpd/conf.d/*.conf
ADD conf/website.com.conf /etc/httpd/conf.d/
#Config for git clone permissions
ADD conf/.ssh/ /usr/share/httpd/.ssh/
RUN chown apache:apache -R /usr/share/httpd/.ssh/
RUN chmod 600 /usr/share/httpd/.ssh/id_rsa
VOLUME ["/var/www/website.com/static"]

完整错误日志:

---> Running in 9c255c769abc
Collecting pip
Downloading https://files.pythonhosted.org/packages/0f/74/ecd13431bcc456ed390b44c8a6e917c1820365cbebcb6a8974d1cd045ab4/pip-10.0.1-py2.py3-none-any.whl (1.3MB)
Installing collected packages: pip
Found existing installation: pip 8.1.2
Uninstalling pip-8.1.2:
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/usr/lib/python2.7/site-packages/pip/commands/install.py", line 326, in run
    strip_file_prefix=options.strip_file_prefix,
  File "/usr/lib/python2.7/site-packages/pip/req/req_set.py", line 736, in install
    requirement.uninstall(auto_confirm=True)
  File "/usr/lib/python2.7/site-packages/pip/req/req_install.py", line 742, in uninstall
    paths_to_remove.remove(auto_confirm)
  File "/usr/lib/python2.7/site-packages/pip/req/req_uninstall.py", line 115, in remove
    renames(path, new_path)
  File "/usr/lib/python2.7/site-packages/pip/utils/__init__.py", line 267, in renames
    shutil.move(old, new)
  File "/usr/lib64/python2.7/shutil.py", line 299, in move
    rmtree(src)
  File "/usr/lib64/python2.7/shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "/usr/lib64/python2.7/shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "/usr/lib64/python2.7/shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "/usr/lib64/python2.7/shutil.py", line 256, in rmtree
    onerror(os.rmdir, path, sys.exc_info())
  File "/usr/lib64/python2.7/shutil.py", line 254, in rmtree
    os.rmdir(path)
OSError: [Errno 39] Directory not empty: '/usr/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches'
You are using pip version 8.1.2, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Removing intermediate container 9c255c769abc
Service 'web' failed to build: The command '/bin/sh -c pip install --upgrade pip' returned a non-zero code: 2

问题原因

这个错误的本质是CentOS yum源提供的python-pip包(版本8.1.2)与pip官方发布的升级包在文件结构上存在冲突

系统通过yum安装的pip,会将cachecontrol相关的依赖文件直接放在系统的site-packages目录中;而pip自身升级时,会尝试卸载旧版本,但卸载流程无法处理系统级安装的残留文件——当它试图删除/pip/_vendor/cachecontrol/caches目录时,发现里面还有yum安装的文件,导致shutil.rmtree因为目录非空而失败。

解决办法

下面提供几个可行的解决方案,按推荐程度排序:

方案1:使用官方get-pip.py安装最新pip(推荐)

完全跳过yum安装的pip,用官方脚本直接安装适配Python2.7的最新pip版本,这样可以彻底替换系统的pip,避免卸载冲突。修改Dockerfile中的pip相关步骤:

# 替换原有的python-pip安装和pip升级步骤
RUN yum install -y python-devel wget
# 下载适配Python2.7的get-pip脚本(Python2.7最后支持pip20.3.4)
RUN wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
RUN python get-pip.py
# 清理临时脚本
RUN rm -f get-pip.py

方案2:升级时跳过卸载旧pip

如果需要保留yum安装的pip作为基础,可以在升级命令中添加--ignore-installed pip参数,强制覆盖安装,跳过卸载步骤:

# 修改原升级命令
RUN pip install --upgrade pip --ignore-installed pip

⚠️ 注意:这个方案可能导致系统中存在两套pip的文件,有潜在的兼容性风险,仅作为临时替代方案使用。

方案3:先卸载yum的pip再安装

先通过yum卸载系统的python-pip包,再用get-pip.py安装最新版本,确保没有残留文件干扰:

RUN yum install -y epel-release && yum repolist
RUN yum install -y python-devel
# 卸载yum提供的pip
RUN yum remove -y python-pip
RUN wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
RUN python get-pip.py
RUN rm -f get-pip.py

验证修改

修改完成后,重新构建镜像,确认pip --version可以输出正确的新版本号,后续的pip install -r requirements/base.txt步骤也能正常执行。

内容的提问来源于stack exchange,提问作者Ciasto piekarz

火山引擎 最新活动