在Docker容器中找不到共享库libpython3.5(但重写工作正常)

在Docker容器中找不到共享库libpython3.5(但重写工作正常),python,linux,docker,anaconda,cntk,Python,Linux,Docker,Anaconda,Cntk,我正在尝试部署一个带有flask的Python Web服务,该服务在Docker容器中使用CNTK。我使用了一个来自微软的Ubuntu基础映像,该映像应该包含运行CNTK所需的所有必要且正确的程序和库 该脚本可以在Windows上本地运行,也可以在我运行容器并使用命令行从cmd启动bash时运行 docker exec -it <container_id> bash 我得到以下错误: 。。。 ImportError:libpython3.5m.so.1.0:无法打开共享对象文件:没

我正在尝试部署一个带有flask的Python Web服务,该服务在Docker容器中使用CNTK。我使用了一个来自微软的Ubuntu基础映像,该映像应该包含运行CNTK所需的所有必要且正确的程序和库

该脚本可以在Windows上本地运行,也可以在我运行容器并使用命令行从cmd启动bash时运行

docker exec -it <container_id> bash
我得到以下错误:

。。。 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运行时作为父映像 来自microsoft/cntk:2.5.1-cpu-python3.5

设定工作时间

目录到/app WORKDIR/app

将当前目录内容复制到位于/app的容器中 加上/应用程序

运行apt-get-update&&apt-get-install-y python-pip-RUN-pip-install -升级pip

安装requirements.txt中指定的任何所需软件包 运行pip安装-可信主机pypi.python.org-r requirements.txt

使端口80在此容器外的世界可用 暴露80

在容器启动时运行app.py CMD[python,test.py]

该项目的其余部分是一个非常简单的flask webapp,当我注释掉实际CNTK项目的所有导入时,它运行起来没有问题。顺便说一句,它是最新版本,可以在cntk git存储库中找到

编辑:

我发现了真正的问题是什么,但我仍然没有办法解决它。问题是,当我用docker exec启动bash时,它会在启动时运行一个脚本,用python3.5和所有整洁的库激活anaconda环境。但是当CMD刚刚启动python时,这是由标准的bourneshellsh完成的,正如我尝试使用python2.7运行的那样

因此,我需要一种方法,要么用bash启动容器,包括它的autostart脚本,要么在启动时以另一种方式激活环境

我查阅了脚本,它基本上检查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

或者使用bash作为入口点。

我找到了一个暂时有效的解决方法

首先,我在我的环境中手动将python链接到python3:

RUN ln -fs /root/anaconda3/envs/cntk-py35/bin/python3.5 /usr/bin/python
然后,我将环境库添加到库路径:

ENV LD_LIBRARY_PATH "/cntk/cntk/lib:/cntk/cntk/dependencies/lib:$LD_LIBRARY_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"]
我也发现这和我做的差不多。他们还需要启动他们的环境。意识到我需要学习如何编写更好的Dockerfiles。我认为这是正确的方法,即使用shell脚本作为入口点

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

请仅对实际答案使用“发布答案”按钮。您应该修改原始问题以添加其他信息。这是答案吗?或者你问题的其他信息?这是我问题的真实答案。它显示了一种在容器开始时激活某个conda环境的方法,对于像我这样的新手来说,这本身就很有趣,因为我曾想过这样做,但在互联网上却找不到它。由于缺少安装在该环境中的库,因此
卢特莉解决了我一直遇到的问题。其实我更喜欢这个答案。这似乎是正确的方法,并且不依赖于在正确的方向上手动弯曲环境变量。很抱歉造成误解。另外:这两篇文章都是对这个问题的不同、完整的回答。
ENTRYPOINT ["/app/run.sh"]
#!/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