在Docker Container中找不到共享库libpython3.5(但覆盖工作正常)

时间:2018-05-22 14:18:13

标签: python linux docker anaconda cntk

我正在尝试部署在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。

2 个答案:

答案 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