我正在尝试部署在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:动态模块没有定义init函数(initcython_bbox)
“cython_bbox”是要导入的* .pyd / * .so文件/库之一的名称。这显然是这类文件类型的典型错误。但我对他们没有任何经验。
我也不是(在我的个人开发中)能够从外部源编译我自己的文件或者自己创建docker镜像本身。我依赖于从微软获得的部分。但我愿意接受建议。
在使用
导入基本映像后,我还尝试在Dockerfile中重新安装库RUN apt-get install -y libpython3.5
但它引起的错误与将路径放在环境变量中的错误相同。
我真的很想知道这里出了什么问题。为什么一切都在“容器内部”顺利运行,而不是在使用CMD初始化容器时使用Autostart?
有关其他信息,我添加了Dockerfile:
#使用官方Python运行时作为父图像 FROM microsoft / cntk:2.5.1-cpu-python3.5
#设置工作
目录到/ app WORKDIR / app
#将当前目录内容复制到/ app的容器中 添加/应用
运行apt-get update&amp;&amp; apt-get install -y python-pip RUN pip install --upgrade pip
#安装requirements.txt中指定的任何所需包 运行pip install --trusted-host pypi.python.org -r requirements.txt
#使端口80可用于此容器外的世界 EXPOSE 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。
答案 0 :(得分:0)
我找到了一个现在有效的解决方法。
首先,我在我的环境中手动将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"]
答案 1 :(得分:0)
我也发现这个GIT Repository所做的事情与我做的差不多。他们还需要启动环境。意识到我需要学习如何编写更好的Dockerfile。我认为这是正确的方法,即使用shell脚本作为ENTRYPOINT
ENTRYPOINT ["/app/run.sh"]
这会激活环境,安装其他python软件包(这可能是一个问题)并启动实际的应用程序。
#!/bin/bash
source /root/anaconda3/bin/activate root
pip install easydict
pip install azure-ml-api-sdk==0.1.0a9
pip install sanic
python3 /app/app.py