如何将PyCharm连接到位于Docker容器内的python解释器?

我从Docker开始,但是我不知道如何configurationPyCharm来使用位于容器中的python解释器。

使用Vagrant很容易 ,但是Docker显然还没有正式的方法 。

我应该准备特殊的Docker镜像与暴露的SSH端口? 如何更轻松地做到这一点?

更新:PyCharm 2017.1有这个问题的解决scheme,请参阅此博客条目

这是我如何解决这个问题。 我的情况是,我被分配到一个Web应用程序的特定区域进行干预,该应用程序使用docker-compose创build了一组四个容器。 Docker-compose是一种通过一个命令pipe理多个docker容器的元docker。 我不想破坏现有的设置,因为有很多事情依赖于它。 但是由于我在其中一个图像的某个特定部分工作,我决定用ssh扩展其中一个容器,以便从PyCharm中进行debugging。 而且,我希望应用程序在启动时正常运行,只需强制退出,然后从PyCharm连接到应用程序,我将拥有一个可debugging组件。 这是我在我的Mac上使用boot2docker(在VirtualBox上)来正确设置docker的。

首先,我需要扩展名为jqworker的目标容器。 我打算用"supervisior"来做pipe理工作的繁重工作。

 FROM jqworker # Get supervisor to control multiple processes, sshd to allow connections. # And supervisor-stdout allows us to send the output to the main docker output. RUN apt-get update && apt-get install -y supervisor openssh-server python-pip \ && pip install supervisor-stdout \ && mkdir -p /var/run/sshd \ && mkdir -p /var/log/supervisor \ && mkdir -p /etc/supervisor/conf.d COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf # Fix up SSH, probably should rip this out in real deploy situations. RUN echo 'root:soup4nuts' | chpasswd RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile # Expose SSH on 22, but this gets mapped to some other address. EXPOSE 22 # Replace old entrypoint with supervisiord, starts both sshd and worker.py ENTRYPOINT ["/usr/bin/supervisord"] 

Supervisor允许我从一个命令运行多个任务,在这种情况下是原始命令和SSHD。 是的,大家都说Docker中的SSHD是邪恶的,容器应该是这样的,而且等等,但是编程就是解决问题,不符合任意忽略上下文的意思。 我们需要SSH来debugging代码,而不是将其部署到该字段,这是我们扩展现有容器而不是将其添加到部署结构的一个原因。 我在本地运行它,以便我可以在上下文中debugging代码。

这里是supervisord.conf文件,请注意,我使用supervisor-stdout软件包将输出导向到supervisor,而不是logging数据,因为我更愿意在一个地方看到它们:

 [supervisord] nodaemon=true [program:sshd] command=/usr/sbin/sshd -D [program:worker] command=python /opt/applications/myproject/worker.py -A args directory=/opt/applications/myproject stdout_events_enabled=true stderr_events_enabled=true [eventlistener:stdout] command = supervisor_stdout buffer_size = 100 events = PROCESS_LOG result_handler = supervisor_stdout:event_handler 

我有一个包含上述两个文件的构build目录,并从那里的terminal,我build立了Dockerfile

 docker build -t fgkrqworker . 

这增加了它,所以我可以从dockerdocker-compose 。 不要跳过尾随点!

由于应用程序使用docker-compose来运行一组容器,现有的WORKER容器将被replace为解决我的问题的容器。 但首先我想要显示的是,在我docker-compose.yml另一部分中,我定义了一个从容器映射到本地硬盘的映射,这是映射的卷的数量之一:

 volumes: &VOLUMES ? /Users/me/source/myproject:/opt/applications/myproject 

然后是我的容器的实际定义,它引用了上面的VOLUMES

 jqworker: &WORKER image: fgkrqworker privileged: true stdin_open: true detach: true tty: true volumes: <<: *VOLUMES ports: - "7722:22" 

这将SSH端口映射到VM中可用的已知端口,请回想一下,我使用的是基于VirtualBox的boot2docker ,但需要将其映射到PyCharm可以获取的位置。 在VirtualBox中,打开boot2docker VM并selectAdapter 1 。 有时候“附加到:”组合没有select自己,所以要注意。 在我的情况下,它应该selectNAT

单击“端口转发”,将内部端口映射到本地主机上的端口,我select使用相同的端口号。 它应该是这样的:Name: ssh_mapped ; 议定书: TCP ; 主机IP: 127.0.0.1 ; 主机端口: 7722 ; 访客IP: 访客端口: 7722 。 注意:注意不要更改boot2docker的`ssh'设置,否则最终将无法正确启动虚拟机。

所以,在这一点上,我们有一个容器,扩展我的目标容器。 它在端口22上运行ssh并将其映射到7722,因为其他容器可能要使用22,并且在VirtualBox环境中可见。 VirtualBox将7722到7722映射到本地主机,你可以通过以下方式进入容器:

 ssh root@localhost -p 7722 

然后会提示input密码'soup4nuts',你应该能够find你的容器特定的东西,以确认它是正确的,一切正常。 如果我在本地机器的任何地方部署,我都不会惹根,所以要警告。 这只适用于本地debugging,您应该在现场进行三次或三次的思考

在这一点上,如果你已经使用了PyCharm的远程debugging,那么你可以把剩下的部分弄清楚。 但是这里是我如何设置:

首先回想一下,我有docker-compose.yml映射项目目录:

 ? /Users/me/source/myproject:/opt/applications/myproject 

在我的容器/opt/applications/myproject实际上是我的本地硬盘上的/Users/me/source/myproject 。 所以,这是我的项目的根源。 我的PyCharm将这个目录视为项目根目录,我希望PyCharm在这里写入.pycharm_helpers ,以便在会话之间持续存在。 我正在pipe理Mac的源代码,但是PyCharm认为这是其他地方的unixy框。 是的,直到JetBrains合并了一个Docker解决scheme之前,这是一个混乱。

首先,进入Project X / Project Structure并创build一个本地映射的Content Root,在我的情况下这意味着/Users/me/source/myproject

稍后,回来并将.pycharm_helpers添加到排除的集合,我们不希望这在源代码pipe理中结束或混淆PyCharm。

转到构build,执行,部署选项卡,select部署,并创build一个新的SFTPtypes的部署。 主机是localhost,端口7722,根path是/opt/applications/myproject ,用户名是root ,密码是soup4nuts ,我检查了保存密码的选项。 我将我的部署命名为“dockercompose”,以便稍后可以挑选出来。

在“部署映射”选项卡上,我将本地path设置为/Users/me/source/myproject ,将部署和webpath设置为单个“/”,但由于我的代码不对应于某个URL,因此我不使用它进行debugging它是Webpath设置中的占位符。 我不知道你怎么设定你的。

在Project X / Project解释器选项卡上,创build一个新的远程Python解释器。 您可以select“部署configuration”并select我们上面创build的“dockercompose”configuration。 主机URL应填写为“ssh:// root @ localhost:7722”,Python解释器path可能是/usr/bin/python 。 我们需要设置PyCharm助手path作为默认将不能幸免于容器重做。 其实我去了我的项目本地目录,并在根目录中创build一个.pycharm_helpers目录,然后将path设置为/opt/applications/myproject/.pycharm_helpers ,当我点击OKbutton时,它将文件“up”复制到目录。 我不知道它是否会自动创build它。

不要忘记.pycharm_helpers目录可能应该被排除在项目的根目录上。

此时,您可以进入构build,执行,部署选项卡,并在控制台/ Python控制台下,select我们上面创build的远程解释器,并将工作目录设置为/opt/applications/myproject并且可以在容器,如果你喜欢。

现在您需要创build一个运行configuration,以便您可以远程debugging您的Python代码。 创build一个新的Pythonconfiguration,并将脚本设置为用于启动容器中的Python代码的脚本。 我的,从主pipe设置,上面是:

 /opt/applications/myproject/worker.py -A args 

因此,我将脚本设置为/opt/applications/myproject/worker.py ,将参数设置为-A args

select我们上面创build的远程解释器,根据需要/opt/applications/myproject工作目录,对于我来说,它是/opt/applications/myproject ,对我来说就是做这个工作。

现在我想进入我的容器并停止worker.py脚本,以便启动一个debugging版本。 当然,如果你喜欢,你可以忽略默认运行脚本,只使用容器进行debugging。

我可以打开一个ssh会话来停止脚本,但是docker提供了一个有用的命令,将它传递到环境中,为我完成这项工作。

 $> docker exec -i -t supervisorctl stop worker 

因为我的过程被命名为“工人”。 请注意,您可以通过将start命令replace为stop命令来重新start

现在,在PyCharm中,用上面创build的运行configuration启动debugging会话。 它应该连接并启动,并在窗口中给你控制台输出。 既然我们杀了监督最初开始的那个,就不再连接了。

这是一个裤子操作的座位,所以可能会有错误和不正确的假设,我没有注意到。 特别是,PyCharm设置需要一些迭代,所以顺序可能不正确,如果失败,尝试再次尝试。 这是很多东西,很容易跳过一些关键的东西。

现在还不在这里,但是不久之后,这不应该成为一个问题

从PyCharm 4.1 EAP(4月初)开始在PyCharm中引入Docker支持,

来源: http : //blog.jetbrains.com/pycharm/2015/03/feature-spotlight-python-remote-development-with-pycharm/#comment-187772

为了避免任何SSH开销(这对于Docker来说是非常合理的), docker exec肯定是要走的路。
不幸的是,我目前无法实现这一目标。 如果有人能填补空白,那将是非常好的。 这是我做的(使用PyCharm 4.0.4和Docker 1.4.1):

  1. 创build一个名为python_myproject.sh的文件, python_myproject.sh包含以下内容:

     #!/bin/bash docker exec -i myproject_container /path/to/containers/python2.7 

    请注意,文件的名称必须以python开头,否则PyCharm会投诉。

  2. 在PyCharm的设置下,在Project Interpreter ,添加一个新的本地解释器。 给它的path到你的python_myproject.sh文件。


这是我卡住的地方。 经过相当长的加载时间(跳动者说“设置库文件”),出现一个标题为“无效的Python SDK”的窗口,并说:

无法设置python SDK
在/path/to/python_myproject.sh。
SDK似乎无效。

~/.PyCharm40/system/log/.idea

 2015-02-19 17:33:30,569 [ 166966] WARN - ution.process.OSProcessHandler - Cannot kill process tree. Trying to destroy process using Java API. Cmdline: 2015-02-19 17:34:30,628 [ 227025] WARN - ution.process.OSProcessHandler - Cannot kill process tree. Trying to destroy process using Java API. Cmdline: 2015-02-19 17:34:30,653 [ 227050] INFO - rains.python.sdk.PythonSdkType - Timed out 

如果您只需要debugging在docker容器中启动的代码,则可以使用pycharm的pythondebugging服务器function。 对于我来说,通过SSH访问远程解释器并不麻烦。 这个解决scheme的缺点是,对于自动完成和所有这些东西,你应该有容器的解释器的本地副本,并将其标记为项目的解释器(适用于自动完成,但我不确定是否有可能debugging代码在这种情况下第三方库)或使容器的解释器文件可见pycharm(根本没有testing)。 另请注意,Pythondebugging服务器是专业版的function 。

你应该通过Pythondebugging服务器进行debugging:

1)确保您的项目的目录被添加到容器中。 它可能看起来像Dockerfile中的这一行:

ADD . /path/in/container

2)从主机上安装pycharm的目录复制pycharm-debug.egg (用于Python3的pycharm-debug-py3k.egg )到容器中位于容器的PYTHONPATH中的目录。 开发者主机上pycharm-debug.egg的path可能是:

  • 对于Mac: /Applications/PyCharm.app/Contents/pycharm-debug.egg
  • 对于Linux: /opt/pycharm/pycharm-debug.egg

3)创build运行/debuggingconfiguration,以启动主机上的Pythondebugging服务器,如To configure a remote debug server 文档 To configure a remote debug server部分所述。 端口是您select的任何主机的端口,但是IP是可从容器访问主机的地址。 它可能是:

  • 如果容器通过boot2docker运行,IP很可能是192.168.99.1 – 主机的地址在主机只有networking与vbox机器
  • 如果主机是Linux,IP可以通过ifconfigfind,对我来说是:
 docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99 inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 

另外,不要忘记在开发者主机的项目path和容器的项目path之间指定path映射。

这个博客文章也可能对当前步骤有所帮助

4)启动这个创build的configuration(例如,通过Debugbutton,从Run一个)

5)创buildpython脚本,它将启动您的项目,并添加下面的代码作为debugging初始化作为脚本的第一行。 (确保pycharm-debug.egg在PYTHONPATH中,或者这个代码不能import pydevd ):

  import pydevd pydevd.settrace('172.17.42.1', suspend=False, port=8765, stdoutToServer=True, stderrToServer=True) 

6)最后,你可以通过创build的脚本在容器中设置断点并从主机启动你的应用程序。 例如:

docker-compose run 'container_name' python 'script_name' 'args'

开始时,启动脚本将连接到正在主机上运行的Pythondebugging服务器,并在断点处停止。 debugging器function将照常使用。

如果你真的需要的话,在你的容器中joinSSH并不是那么糟糕。 是的,自引入docker docker exec以来,在其他用例中并不重要,但由于Intellij / PyCharm只支持通过SSH进行远程解释,所以没关系。

您可以使用phusion/baseimage作为一个很好的起点,使用SSH和您需要的任何版本的Python(它默认使用PY3)来构build自己的容器。

从理论上讲,最好还是继续使用Vagrant来完成这个任务,因为它允许你创build一个可以在Windows / OS X机器上(通过使用boot2docker)和Linux(本地Docker)工作的工作stream程。

实际上,我无法使它在OS X上工作,因为为了进入SSH服务,您必须传递双NAT层,而且看起来不可能为Vagrant boot2docker框添加额外的接口(stream氓1.7.2)。

使用Docker 1.3,使用exec命令来构buildPython解释器的path:

 sudo docker exec container_name /usr/bin/python 

请参阅https://docs.docker.com/reference/commandline/cli/#exec,http://forum.jetbrains.com/thread/PyCharm-2224

您可以在容器中安装SSH,然后公开该端口,但这不是容器如何使用的原因,因为您将会膨胀它们。

通过在容器中安装pycharm并从那里运行,你可能会有点疯狂。 你必须通过“docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY =:0.0 pycharm-image”来做到这一点,但它应该工作得很好。 但请记住,所有的pycharm和你的源也将在该容器中。 所以保存,提交,并推动和经常。

用PyCharm 5他们增加了对docker的支持。 您必须在docker-machine中configurationdocker。

如果您还没有使用docker-machine,则可以使用通用机器引擎连接到现有机器,如果不在VM中运行,则可以将ssh连接到vagrant VM或localhost。 不幸的是,我没有find解决scheme的SSH本地。

我还没有find一种方法将卷装载到他们使用的docker映像中,与我的开发树共享文件,但也可以。

特定于PyCharm专业版2017.2的步骤(但是它们可以与PyCharm CE一起使用)

这里有几个步骤让我的设置工作

步骤1:环境

您(或任何可能正在阅读的)项目的结构的一些假设:

 bleh ├── README.md ├── api │  ├── Dockerfile <---- this is the one we want to debug │  ├── config.example.ini │  └── src │  ├── __init__.py <---- this is a pycharm project │  ├── __main__.py <---- this is a pycharm project │  └── ... ├── proxy │  ├── Dockerfile │  ├── config.example.ini │  └── src │  ├── ... │  └── ... ├── webserver │  ├── Dockerfile │  ├── config.example.ini │  └── src │  ├── ... │  └── ... ├── frontend │  ├── Dockerfile │  ├── config.example.ini │  └── src │  ├── ... │  └── ... ├── db │  ├── Dockerfile │  ├── ... │  └── migrations │  ├── ... │  └── ... └── docker-compose.yml 
  • 注意我只使用bleh作为我的项目名称作为示例。
  • 注意我们也将假设这个项目的绝对位置是/Users/myfunkyusername/Projects/bleh
  • 注意 :就命名和位置而言,显然这是随机的,请针对您的系统/项目进行调整
  • 注意我们也假设你想要在docker-compose.yml文件中稍后显示的,debuggingapi服务
  • 注意我们也将假定你的api的内容是唯一的Dockerfile

     FROM python ADD config.example.ini /etc/bleh/config.ini RUN chmod +x /usr/bin/bleh COPY ./src /usr/bin/bleh WORKDIR /usr/bin/bleh RUN pip install -r requirements.txt CMD ["sh", "-c", "python -m bleh --cfg=/etc/bleh/config.ini"] 
  • 注意我们假设你唯一docker-compose.yml包含这些内容

     version: '2' services: api: build: context: ./api depends_on: - db expose: - "8080" networks: - default frontend: build: context: ./frontend ports: - "80:7000" networks: - default webserver: build: context: ./webserver depends_on: - frontend networks: - default proxy: build: context: ./proxy ports: - "80:80" - "443:443" depends_on: - webserver - api networks: - default db: build: context: ./db expose: - "3306" networks: - default networks: default: driver: bridge 

第2步:创buildDocker-Machine

创buildbleh -machine专门为bleh项目

 docker-machine create bleh 

第3步: 连接远程解释器

  • PyCharm / Preferences / Build, Execution, Deployment / Docker点击+
  • selectDocker machine单选button,并在下拉bleh突出显示bleh的泊坞窗机器
  • selectApply
  • PyCharm / Preferences / Project:bleh / Project Interpreter
  • 点击Project Interpreter字段最右侧的齿轮图标,然后selectAdd Remote
  • selectDocker单选button
  • 在“ Server字段中,为此项目select以前创build的泊坞窗机器
  • select包含你想要的Python解释器的bleh_api (例如bleh_api
  • Python interpreter path不需要改变
  • 点击OK

第4步: configuration远程debugging器

  • Run / Edit Configurationsselect+添加configuration
  • selectPython
  • 通过Script字段,可以在将要运行的Docker容器上使用脚本文件的位置(在本例中,它是/usr/bin/bleh/__main__.py因为我们给出了目标脚本的绝对位置)
  • 使用Script parameters字段,提供CLI参数(如果有的话)(模仿Dockerfile的最后一个CMD命令,即--cfg=/etc/bleh/config.ini
  • 使用Python Interpreter字段,select您以前build立的远程Python解释器
  • 使用Working directory字段,selectScript在Docker容器内的目录(例如/usr/bin/bleh
  • Path mappings字段中,单击...并select本地(例如/Users/myfunkyusername/Projects/bleh/api/src )和远程(例如/usr/bin/bleh )如上
  • 使用Docker container settings字段,单击...
    • 确保你有正确的docker容器select(例如bleh_api:latest
    • 添加端口绑定容器/主机,模仿Dockerfile (例如Dockerfile并使用tcp协议公开到0.0.0.0现在我还没有显示你的应用程序结构是什么,但是让我们假设你是理智的,在您的应用程序中也指定8080作为您的数据服务的端口
    • 添加卷绑定container / host /usr/bin/bleh / /Users/myfunkyusername/Projects/bleh/api/src
    • 确保Network mode ( 感谢Piotr )设置为<name_of_project_directory>_<name_of_network_from_compose_file> (例如bleh_default ,您可以在正确的docker-machine使用bleh_default docker network ls进行确认)

第五步:晒太阳还是多打一些吧

这些是让我到一个工作的docker和PyCharm设置的步骤。

我不假装在这些步骤中都是正确的。 我会很乐意更新您find的任何错误/改进。

我还没有尝试过,但我会尝试创build一个调用docker exec ...的Bash脚本,就像@ Anto的答案一样 。

然后,安装BashSupport扩展 。 现在创build一个新的运行configuration ,将脚本作为Bash脚本运行。