【发布时间】:2018-05-22 14:18:12
【问题描述】:
我正在尝试在 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 工作目录 /app
# 将当前目录内容复制到容器/app 添加 。 /应用程序
运行 apt-get update && apt-get install -y python-pip RUN pip install --升级点
# 安装 requirements.txt 中指定的任何需要的包 运行 pip install --trusted-host pypi.python.org -r requirements.txt
# 让这个容器外的世界可以使用 80 端口 曝光 80
# 容器启动时运行 app.py CMD ["python", "test.py"]
项目的其余部分是一个非常简单的 flask-webapp,当我注释掉实际 CNTK 项目的所有导入时,它运行没有问题。顺便说一下,它是CNTK Object Detection with Faster-RCNN,因为它可以在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 linux docker anaconda cntk