简体   繁体   English

Docker 卷绑定中断 python 脚本 CLI entry_point

[英]Docker volume bind breaks python script CLI entry_point

Alright so I have a fairly basic python click CLI application that when ran with a bound volume in a container (live dev on files) appears to break the entry_point I have in setup.py好的,所以我有一个相当基本的 python click CLI 应用程序,当它在容器中使用绑定卷运行时(文件上的实时开发)似乎打破了我在setup.pyentry_point

Running either of the following commands运行以下任一命令

$ docker run -it -v $(pwd):/opt/app gdax
$ docker run -it --mount src=$(pwd),target=/opt/app,type=bind gdax

I get the following我得到以下

Traceback (most recent call last):
  File "/usr/local/bin/gdax", line 6, in <module>
    from pkg_resources import load_entry_point
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 3144, in <module>
    @_call_aside
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 3128, in _call_aside
    f(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 3157, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 666, in _build_master
    ws.require(__requires__)
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 984, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 870, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'gdax-cli' distribution was not found and is required by the application

Dockerfile文件

FROM python:3.6

RUN mkdir /opt/app
COPY . /opt/app


WORKDIR /opt/app

RUN pip install --editable .

CMD ["gdax", "--help"]

setup.py设置文件

from setuptools import setup


setup(
    name='gdax-cli',
    version='0.1',
    py_modules=['app'],
    install_requires=[
        'click==6.7',
        'gdax==1.0.6'
    ],
    entry_points='''
        [console_scripts]
        gdax=app:cli
    ''',
)

/usr/local/bin/gdax <- on container /usr/local/bin/gdax <- 在容器上

#!/usr/local/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'gdax-cli','console_scripts','gdax'
__requires__ = 'gdax-cli'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('gdax-cli', 'console_scripts', 'gdax')()
    )

If I don't bind the volume I can execute the script just fine but I lose the ability to edit the files on the host machine.如果我不绑定卷,我可以很好地执行脚本,但我无法在主机上编辑文件。 I'm fairly confident this has something to do with how binding "overwrites" the files and will break /usr/local/bin/gdax ability to load the files which is placed there by setuptools .我相当有信心这与绑定如何“覆盖”文件有关,并且会破坏/usr/local/bin/gdax加载由setuptools放置在那里的文件的能力。 Is there anyway to circumvent this (outside of calling python app.py in the container)?有没有办法绕过这个(在容器中调用python app.py之外)?

For anybody interested in calling the Python entry_points console scripts via docker-compose run during development.对于任何有兴趣在开发过程中通过entry_points docker-compose run调用 Python entry_points控制台脚本的人。 Copying the .egg-info folder into the mounted host directory from the running container one time works for me.一次将.egg-info文件夹从正在运行的容器复制到挂载的主机目录对我.egg-info

Copy the .egg-info directory to host from running container..egg-info目录从正在运行的容器复制到主机。 Turn mounting off beforehand so the .egg-info directory is not overriden.预先关闭挂载,这样.egg-info目录就不会被覆盖。

sudo docker cp <container id>:/path/to/package/in/container/package.egg-info /path/to/mounted/package/on/host/package.egg-info

Re-enable mounting, the needed .egg-info folder is now present so the installed entry_points should work and you can run commands like:重新启用挂载,所需的.egg-info文件夹现在存在,因此安装的 entry_points 应该可以工作,您可以运行如下命令:

sudo docker-compose run <service name> <entry_point console script name> [OPT] [ARG]

For this to work, the Python package needed to be installed in development mode in the image, like with RUN pip install -e /path/to/package/ , because otherwise the .egg-info file will not be in the symlinked source code directory, I guess.为此,需要在映像中以开发模式安装 Python 包,例如RUN pip install -e /path/to/package/ ,否则.egg-info文件将不会出现在符号链接的源代码中目录,我猜。

Of course, the alternative, like @Adam mentions, is to always call the CLI scripts directly like:当然,替代方案,如@Adam 提到的,总是直接调用CLI脚本,如:

sudo docker-compose run <service name> python /path/to/package/cli.py [OPT] [ARG]

When installing pip as editable in the current directory, the <package>.egg-info directory needs to be present for python to find the installed package.在当前目录中将 pip 安装为可编辑时,需要存在<package>.egg-info目录,python 才能找到已安装的包。

One can “whitelist” directories from being overwritten by a docker-compose.yml mount point, like so:可以将目录“列入白名单”,以免被docker-compose.yml挂载点覆盖,如下所示:

services:
  myapp:
    image: mafrosis/myapp:dev
    build:
      context: .
    volumes:
      - ./:/app
      - /app/.git
      - /app/myapp.egg-info

In this example, both the .git and myapp.egg-info directories will be present when the container starts.在这个例子中,当容器启动时.gitmyapp.egg-info目录都会出现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM