如何将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 .
这增加了它,所以我可以从docker
或docker-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):
-
创build一个名为
python_myproject.sh
的文件,python_myproject.sh
包含以下内容:#!/bin/bash docker exec -i myproject_container /path/to/containers/python2.7
请注意,文件的名称必须以
python
开头,否则PyCharm会投诉。 -
在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可以通过
ifconfig
find,对我来说是:
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(例如,通过Debug
button,从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
您可以在容器中安装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
点击+
- select
Docker machine
单选button,并在下拉bleh
突出显示bleh
的泊坞窗机器 - select
Apply
- 从
PyCharm
/Preferences
/Project:bleh
/Project Interpreter
- 点击
Project Interpreter
字段最右侧的齿轮图标,然后selectAdd Remote
- select
Docker
单选button - 在“
Server
字段中,为此项目select以前创build的泊坞窗机器 - select包含你想要的Python解释器的
bleh_api
(例如bleh_api
) -
Python interpreter path
不需要改变 - 点击
OK
第4步: configuration远程debugging器
- 从
Run
/Edit Configurations
select+
添加configuration - select
Python
- 通过
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容器select(例如
第五步:晒太阳还是多打一些吧
这些是让我到一个工作的docker和PyCharm设置的步骤。
我不假装在这些步骤中都是正确的。 我会很乐意更新您find的任何错误/改进。
我还没有尝试过,但我会尝试创build一个调用docker exec ...
的Bash脚本,就像@ Anto的答案一样 。
然后,安装BashSupport扩展 。 现在创build一个新的运行configuration ,将脚本作为Bash脚本运行。