构建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




