|
| 1 | +## Python Virtualenv |
| 2 | + |
| 3 | +https://zhuanlan.zhihu.com/p/81568689 |
| 4 | + |
| 5 | +如果你使用 Python 2,那就只能选择 [virtualenv][],你需要额外安装它。 |
| 6 | + |
| 7 | +[venv][] 是 [virtualenv][] 的子集,从 Python 3.3 起,被集成到 Python 标准库中。意味着 Python 3.2 以下的都用不来 venv。且 venv 有缺点,详见 [virtualenv][] 文档。 |
| 8 | + |
| 9 | +- `python -m venv venv` 会创建 venv 目录,默认是把 venv/bin/ 里面的文件都是软链接,指向全局环境的 python。 |
| 10 | +- `python -m venv --copies venv` 会创建 venv 目录,`--copies` 把全局环境的 python 全都拷贝到 venv 目录里。 |
| 11 | +- `virtualenv -p ~/.pyenv/versions/3.8.2/bin/python --copies venv` virtualenv 可以用 `-p` 指定拷贝哪个路径下的 python。 |
| 12 | + |
| 13 | +### virtualenv 没有打包动态链接库 |
| 14 | + |
| 15 | +virtualenv 和 python 3 的 venv 都有这问题。 |
| 16 | + |
| 17 | +https://github.com/pypa/virtualenv/issues/1015 |
| 18 | +https://github.com/pypa/virtualenv/pull/1045 |
| 19 | + |
| 20 | +执行 `ldd /usr/local/bin/python` 看 python 依赖哪些动态链接库。 |
| 21 | + |
| 22 | +如果目标部署机器上没有对应的动态链接库,首先要把动态链接库拷贝到部署机任意位置(通常是 `/usr/local/lib/`)。然后在 LD_LIBRARY_PATH 加入目录路径即可。例如 `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib`。 |
| 23 | + |
| 24 | +### virtualenv 没有打包 /usr/local/lib/python3.5 |
| 25 | + |
| 26 | +这里 python3.5 只是个例子,跟 python 具体版本没关系。 |
| 27 | + |
| 28 | +``` |
| 29 | +$ python |
| 30 | +Could not find platform independent libraries <prefix> |
| 31 | +Could not find platform dependent libraries <exec_prefix> |
| 32 | +Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>] |
| 33 | +Fatal Python error: Py_Initialize: Unable to get the locale encoding |
| 34 | +ImportError: No module named 'encodings' |
| 35 | +
|
| 36 | +Current thread 0x00007f4dffee0740 (most recent call first): |
| 37 | +Aborted (core dumped) |
| 38 | +``` |
| 39 | + |
| 40 | +encodings 这种 python 标准库,都在 /usr/local/lib/python3.5 路径下。 |
| 41 | + |
| 42 | + |
| 43 | +### 制作完整的 venv 离线包 |
| 44 | + |
| 45 | +两种方式, |
| 46 | + |
| 47 | +1. 从官方 docker 镜像中制作 venv,安装 python 依赖包。 |
| 48 | +2. 自己编译 python,制作 venv,安装 python 依赖包。这种情况适用于 venv 拷贝到(跟镜像同一基线的)宿主机上。 |
| 49 | + |
| 50 | +#### 方案 1 |
| 51 | + |
| 52 | +```Dockerfile |
| 53 | +FROM python:3.8.2-slim |
| 54 | + |
| 55 | +WORKDIR /app |
| 56 | + |
| 57 | +SHELL ["/bin/bash", "-c"] |
| 58 | + |
| 59 | +RUN apt-get update |
| 60 | +RUN apt-get install -y build-essential |
| 61 | +RUN python -m venv --copies venv |
| 62 | +RUN mkdir -p venv/dll && \ |
| 63 | + cp /usr/local/lib/{libpython3.8m.so,libpython3.8m.so.1.0,libpython3.so} venv/dll/ && \ |
| 64 | + cp -rf /usr/local/lib/python3.8/* venv/lib/python3.8/ |
| 65 | + |
| 66 | +ADD requirements.txt . |
| 67 | + |
| 68 | +RUN source ./venv/bin/activate && \ |
| 69 | + pip install --upgrade pip && \ |
| 70 | + pip install --no-cache-dir -r ./requirements.txt |
| 71 | +RUN tar -czf ./venv.tgz -C ./venv . |
| 72 | + |
| 73 | +CMD [ "bash" ] |
| 74 | +``` |
| 75 | + |
| 76 | +#### 方案 2 |
| 77 | + |
| 78 | +```Dockerfile |
| 79 | +FROM centos:7 |
| 80 | + |
| 81 | +WORKDIR /app |
| 82 | + |
| 83 | +SHELL ["/bin/bash", "-c"] |
| 84 | + |
| 85 | +# See https://github.com/pyenv/pyenv/wiki/Common-build-problems |
| 86 | +RUN yum install -y @development \ |
| 87 | + zlib-devel bzip2 bzip2-devel readline-devel \ |
| 88 | + sqlite sqlite-devel openssl-devel xz xz-devel libffi-devel findutils |
| 89 | + |
| 90 | +RUN curl https://pyenv.run | bash |
| 91 | +RUN export PATH="/root/.pyenv/bin:$PATH" &&\ |
| 92 | + eval "$(pyenv init -)" &&\ |
| 93 | + eval "$(pyenv virtualenv-init -)" &&\ |
| 94 | + CFLAGS=-I/usr/include/openssl LDFLAGS=-L/usr/lib64 pyenv install -v 3.8.2 |
| 95 | + |
| 96 | +RUN export PATH="/root/.pyenv/bin:$PATH" &&\ |
| 97 | + eval "$(pyenv init -)" &&\ |
| 98 | + eval "$(pyenv virtualenv-init -)" &&\ |
| 99 | + pyenv shell 3.8.2 &&\ |
| 100 | + python -m venv --copies venv |
| 101 | + |
| 102 | +RUN mkdir -p venv/dll && \ |
| 103 | + cp /root/.pyenv/versions/3.8.2/lib/{libpython3.8m.so,libpython3.8m.so.1.0,libpython3.so} venv/dll/ && \ |
| 104 | + cp -rf /root/.pyenv/versions/3.8.2/lib/python3.8/* venv/lib/python3.8/ |
| 105 | + |
| 106 | +RUN source ./venv/bin/activate && \ |
| 107 | + pip install --upgrade pip |
| 108 | + |
| 109 | +ADD requirements.txt . |
| 110 | +RUN source ./venv/bin/activate && \ |
| 111 | + pip install -r ./requirements.txt |
| 112 | + |
| 113 | +RUN tar -czf ./venv.tgz -C ./venv . |
| 114 | + |
| 115 | +CMD [ "bash" ] |
| 116 | +``` |
| 117 | + |
| 118 | +#### docker cp 导出 venv 包 |
| 119 | + |
| 120 | +```sh |
| 121 | +main() { |
| 122 | + local image=$1 |
| 123 | + local venv_file=$2 |
| 124 | + |
| 125 | + local cid |
| 126 | + cid=$(docker create "$image") |
| 127 | + docker cp "$cid":/app/venv.tgz "$venv_file" |
| 128 | + docker rm "$cid" |
| 129 | + |
| 130 | + # tar -xzf "$venv_file" -C "$output" |
| 131 | +} |
| 132 | +``` |
0 commit comments