内网环境 Docker 如何pip install package

内网环境用 Docker 基础镜像构建新镜像时,安装包通常有几种处理方式,核心思路是:不要在构建时访问公网,把依赖提前准备好或放到内网源里

方案一:把安装包放进构建目录,用 COPY 拷进镜像

适合安装少量 .deb.rpm.tar.gz.whl 等离线包。

例如目录结构:

my-image/
├── Dockerfile
└── packages/
    ├── nginx_1.24.0.deb
    ├── libxxx.deb
    └── app.tar.gz

Dockerfile 示例:

FROM ubuntu:22.04

COPY packages/ /tmp/packages/

RUN dpkg -i /tmp/packages/*.deb || apt-get install -f -y \
    && rm -rf /tmp/packages/*

如果是 CentOS / Rocky / RHEL:

FROM rocky:9

COPY packages/ /tmp/packages/

RUN dnf install -y /tmp/packages/*.rpm \
    && rm -rf /tmp/packages/*

Python 离线 wheel 包示例:

FROM python:3.11

COPY wheels/ /tmp/wheels/
COPY requirements.txt /tmp/

RUN pip install --no-index --find-links=/tmp/wheels -r /tmp/requirements.txt \
    && rm -rf /tmp/wheels

方案二:搭建内网软件源,构建时从内网源安装

适合依赖较多、需要长期维护的环境。比如搭建:

内网 apt 源
内网 yum/dnf 源
内网 pip 源
内网 npm 源
内网 Maven 仓库
内网 Docker Registry

Ubuntu/Debian 示例:

FROM ubuntu:22.04

RUN sed -i 's|http://archive.ubuntu.com/ubuntu|http://内网apt源/ubuntu|g' /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y curl vim nginx \
    && rm -rf /var/lib/apt/lists/*

CentOS/Rocky 示例:

FROM rocky:9

COPY internal.repo /etc/yum.repos.d/internal.repo

RUN dnf install -y nginx curl vim \
    && dnf clean all

Python pip 内网源示例:

FROM python:3.11

COPY requirements.txt /app/

RUN pip install -i http://内网pip源/simple --trusted-host 内网pip源 \
    -r /app/requirements.txt

方案三:提前在外网机器下载依赖,再带入内网

外网机器下载:

apt-get download curl vim nginx

或者下载 Python wheel:

pip download -r requirements.txt -d wheels/

然后把这些文件拷贝到内网,再在 Dockerfile 里:

COPY wheels/ /tmp/wheels/
RUN pip install --no-index --find-links=/tmp/wheels -r requirements.txt

方案四:直接在外网构建好镜像,再导入内网

外网构建:

docker build -t myapp:1.0 .
docker save myapp:1.0 -o myapp_1.0.tar

拷贝到内网后加载:

docker load -i myapp_1.0.tar

这种方式适合内网机器完全不能访问任何源,只负责运行镜像。


推荐做法

如果只是少量包:
把安装包放到构建目录,然后 COPY 进去安装。

如果是公司长期使用:
搭建内网 apt/yum/pip/npm/Maven 源 + 内网 Docker Registry。

如果内网完全隔离:
外网构建好镜像,docker save 导出,内网 docker load 导入。

一个常见的离线 Dockerfile 模板是:

FROM ubuntu:22.04

COPY packages/ /tmp/packages/

RUN dpkg -i /tmp/packages/*.deb || true \
    && apt-get install -f -y \
    && rm -rf /tmp/packages/*

不过要注意:apt-get install -f 仍然可能需要访问软件源。如果完全离线,必须把所有依赖包也一起准备好。

可以用 pip download 的这些参数指定目标 Python 版本 / 系统平台 / ABI,而不是按当前机器的 Python 环境下载。

1. 下载目标 Python 3.10 的包,走公司内网源

假设你的目标容器是:

Python 3.10
Linux x86_64
CPython

命令可以这样写:

python -m pip download \
  -r requirements.txt \
  -d wheels/ \
  -i http://pypi.company.com/simple \
  --trusted-host pypi.company.com \
  --only-binary=:all: \
  --python-version 310 \
  --implementation cp \
  --abi cp310 \
  --platform manylinux2014_x86_64

其中:

-d wheels/                下载到 wheels 目录
-i                        指定公司内网 PyPI 镜像源
--python-version 310      目标 Python 版本是 3.10
--implementation cp       CPython
--abi cp310               Python 3.10 的 CPython ABI
--platform manylinux2014_x86_64 目标 Linux x86_64 平台
--only-binary=:all:       只下载 wheel,不下载源码包

pip 官方文档说明,pip download 可以通过 --platform--python-version--implementation--abi 为“非当前运行环境”的解释器和系统下载依赖;使用这些选项时需要配合 --only-binary=:all:--no-deps。(Pip)


2. Python 版本对应关系

常见写法:

Python 3.8   -> --python-version 38   --abi cp38
Python 3.9   -> --python-version 39   --abi cp39
Python 3.10  -> --python-version 310  --abi cp310
Python 3.11  -> --python-version 311  --abi cp311
Python 3.12  -> --python-version 312  --abi cp312

例如下载 Python 3.11 兼容包:

python -m pip download \
  -r requirements.txt \
  -d wheels/ \
  -i http://pypi.company.com/simple \
  --trusted-host pypi.company.com \
  --only-binary=:all: \
  --python-version 311 \
  --implementation cp \
  --abi cp311 \
  --platform manylinux2014_x86_64

pip 的 --python-version 会参与 wheel 和 Requires-Python 兼容性判断;官方也建议如果指定其中一个目标环境参数,最好同时指定 platform、Python version、implementation、ABI,避免误下载当前机器兼容但目标环境不兼容的包。(Pip)


3. 如果下载机器和目标容器 Python 版本一致

这是最简单、最稳的方式。比如你下载机器本身就是 Python 3.10,目标 Docker 镜像也是 Python 3.10:

python3.10 -m pip download \
  -r requirements.txt \
  -d wheels/ \
  -i http://pypi.company.com/simple \
  --trusted-host pypi.company.com

这种方式通常不需要手动写 --python-version--abi--platform,因为 pip 默认按当前解释器和系统选择包。pip 文档说明这些选项默认会使用当前系统/解释器的值。(Pip)


4. 下载后在 Dockerfile 里离线安装

目录结构:

project/
├── Dockerfile
├── requirements.txt
└── wheels/
    ├── xxx.whl
    ├── yyy.whl
    └── ...

Dockerfile:

FROM python:3.10-slim

WORKDIR /app

COPY requirements.txt .
COPY wheels/ /wheels/

RUN pip install --no-index --find-links=/wheels -r requirements.txt

--no-index 表示不访问 PyPI 或镜像源,只从本地 --find-links=/wheels 目录找包;pip 文档也说明 pip download 下载出的目录可以后续通过 pip install --find-links 用于离线或受限环境安装。(Pip)


5. 如果报 “No matching distribution found”

常见原因有三个:

第一,内网源里没有对应版本的 wheel 包。比如目标是 Python 3.10,但内网源只有 cp39 的包。

第二,平台写错了。比如目标镜像是 Alpine Linux,通常不是 manylinux2014_x86_64,而可能需要 musllinux_1_2_x86_64。如果是 ARM 服务器,需要类似:

--platform manylinux2014_aarch64

第三,某些包没有 wheel,只有源码包。你用了:

--only-binary=:all:

这种情况下 pip 会直接失败。解决方式是先在和目标镜像一致的环境里构建 wheel:

python -m pip wheel \
  -r requirements.txt \
  -w wheels/ \
  -i http://pypi.company.com/simple \
  --trusted-host pypi.company.com

然后 Docker 构建时再离线安装。


6. 推荐流程

公司内网环境建议这样做:

# 1. 明确目标镜像 Python 版本
docker run --rm python:3.10-slim python -V

# 2. 下载 Python 3.10 Linux x86_64 兼容 wheel
python -m pip download \
  -r requirements.txt \
  -d wheels/ \
  -i http://pypi.company.com/simple \
  --trusted-host pypi.company.com \
  --only-binary=:all: \
  --python-version 310 \
  --implementation cp \
  --abi cp310 \
  --platform manylinux2014_x86_64

# 3. Dockerfile 里离线安装

如果你们基础镜像固定,比如 python:3.10-slim,最稳的是用同版本基础镜像起一个临时容器,在里面执行 pip downloadpip wheel,这样下载出来的包和最终运行环境最一致。

posted @ 2026-06-16 17:18  X1OO  阅读(36)  评论(0)    收藏  举报