python - 在 Docker 容器中找不到共享库 libpython3.5(但覆盖工作正常)
问题描述
我正在尝试在 Docker 容器中部署一个使用 CNTK 的 Python Web 服务(带有烧瓶)。我使用来自 Microsoft 的 Ubuntu-Base-Image,它应该包含所有必要且正确的程序和库来运行 CNTK。
该脚本在本地工作(在 Windows 上)以及当我运行容器并从 cmd-line 启动 bash 时
docker exec -it <container_id> bash
并从“容器内”启动脚本。
一个重要的补充是 python 脚本使用两个预编译模块,它们是用于 windows 的 *.pyd 文件和用于 Linux 的 *.so 文件。因此,对于 docker 映像,我将前者替换为后者,以便从容器内运行脚本。
当我在 Dockerfile 中使用 CMD 启动脚本时,问题就开始了。图像的创建显示没有问题。但是当我启动容器时
docker run -p 1234:80 app
我收到以下错误:
...
ImportError:libpython3.5m.so.1.0:无法打开共享对象文件:没有这样的文件或目录
图书馆好像不见了。但是(我重复一遍)当我从容器中运行的 bash 中运行脚本时(据我所知,它应该只有容器库),一切正常。我什至可以用
ldd $(which python)
该文件肯定在文件夹中。所以问题是为什么python在运行docker容器时找不到它的依赖。
当我尝试通过在环境变量中明确地给出库的路径时,它甚至变得更奇怪:
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/root/anaconda3/pkgs/python-3.5.2-0/lib/"
然后图书馆似乎找到了图书馆,但它不被接受为正确的:
ImportError:动态模块未定义初始化函数(initcython_bbox)
“cython_bbox”是要导入的 *.pyd / *.so 文件/库之一的名称。这显然是这类文件类型的典型错误。但我对他们没有任何经验。
我也不能(在我的个人开发中)能够从外部源编译我自己的文件或自己创建 docker 映像。我依赖从 Microsoft 获得的部件。但我愿意接受建议。
在导入基本映像后,我也已经尝试在 Dockerfile 中重新安装库
RUN apt-get install -y libpython3.5
但它引发了与我将路径放入环境变量时相同的错误。
我真的很想知道这里出了什么问题。为什么一切都在“容器内”顺利运行,但在使用 CMD 初始化容器时自动启动却不行?
有关其他信息,我添加了 Dockerfile:
# 使用官方 Python 运行时作为父镜像 FROM microsoft/cntk:2.5.1-cpu-python3.5
# 设置工作
目录到 /app WORKDIR /app
# 将当前目录内容复制到 /app ADD 的容器中。/应用程序
运行 apt-get update && apt-get install -y python-pip 运行 pip install --upgrade pip
# 安装 requirements.txt 中指定的任何需要的包 RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 让这个容器之外的世界可以使用 80 端口 EXPOSE 80
# 当容器启动 CMD 时运行 app.py ["python", "test.py"]
项目的其余部分是一个非常简单的 flask-webapp,当我注释掉实际 CNTK 项目的所有导入时,它运行没有问题。顺便说一下,它是带有 Faster-RCNN 的 CNTK 对象检测,可以在 cntk-git-repository 中找到。
编辑:
我发现了实际问题是什么,但我仍然没有办法解决它。问题是,当我使用“docker exec”启动 bash 时,它会在启动时运行一个脚本,该脚本会使用 python3.5 和所有整洁的库激活 anaconda 环境。但是当 CMD 刚刚启动 python 时,这是由标准的 Bourne shell“sh”完成的,它(正如我尝试过的)与 python2.7 一起运行。
所以我需要一种方法来使用 bash 启动我的容器(包括它的自动启动脚本),或者以另一种方式在启动时激活环境。
我查看了脚本,它基本上检查 bash 是否是当前 shell,设置一些环境变量并激活环境。
if [ -z "$BASH_VERSION" ]; then
echo Error: only Bash is supported.
elif [ "$(basename "$0" 2> /dev/null)" == "activate-cntk" ]; then
echo Error: this script is meant to be sourced. Run 'source activate-cntk'
else
export PATH="/cntk/cntk/bin:$PATH"
export LD_LIBRARY_PATH="/cntk/cntk/lib:/cntk/cntk/dependencies/lib:$LD_LIBRARY_PATH"
source "/root/anaconda3/bin/activate" "/root/anaconda3/envs/cntk-py35"
cat <<MESSAGE
************************************************************
CNTK is activated.
Please checkout tutorials and examples here:
/cntk/Tutorials
/cntk/Examples
To deactivate the environment run
source /root/anaconda3/bin/deactivate
************************************************************
MESSAGE
fi
我尝试了很多东西,比如将 sh 链接到 bash
RUN ln -fs /bin/bash /bin/sh
或使用 bash 作为 ENTRYPOINT。
解决方案
我找到了一个目前有效的解决方法。
首先,我在我的环境中手动将 python 链接到 python3:
RUN ln -fs /root/anaconda3/envs/cntk-py35/bin/python3.5 /usr/bin/python
然后我将环境库添加到 Library-Path:
ENV LD_LIBRARY_PATH "/cntk/cntk/lib:/cntk/cntk/dependencies/lib:$LD_LIBRARY_PATH"
并确保我将所有重要文件夹添加到 PATH:
ENV PATH "/cntk/cntk/bin:$PATH"
ENV PATH "/root/anaconda3/envs/cntk-py35/bin:$PATH"
然后我必须再次安装我的 python 包:
RUN pip install flask
最后可以开始我的脚本:
CMD ["python", "app.py"]
推荐阅读
- go - Golang Web 服务器的 Heroku 错误:Web 进程在启动后 60 秒内无法绑定到 $PORT
- javascript - Firebase:自定义声明要求我的用户注销并登录才能生效?
- xcode - "No such module 'Firebase'" // 找不到框架 FirebaseUI
- javascript - 使用 Puppeteer + Next.js 和 Express 进行网页抓取
- asp.net - 计时器回调中的 Asp.net 未处理异常崩溃 w3wp 并且未记录错误
- kotlin - 更改为不同的活动并再次返回后,回收站视图上的项目消失
- mysql - 数据库最高效的表系统
- jwt - System.InvalidOperationException:验证 Azure AD 令牌时出现 IDX20803
- python - 在每个数据框列中创建最频繁值的行
- scipy - 用于基于遗传算法的曲线拟合的 Python 库?