我从Docker开始,但我不知道如何配置PyCharm以使用位于容器中的python解释器。
It was easy to setup with Vagrant,但还有apparently no official way to do it with Docker。
我应该使用暴露的ssh端口准备特殊的Docker镜像吗?如何更容易地做到这一点?
答案 0 :(得分:11)
更新:PyCharm 2017.1有针对此问题的解决方案,请参阅此blog entry
以下是我解决问题的方法。我的情况是,我被指派对使用docker-compose创建一组四个容器的Web应用程序的特定区域进行干预。 Docker-compose是一种meta docker,它通过一个命令管理多个docker容器。我不想破坏他们现有的设置,因为很多东西都依赖于它。但由于我正在处理其中一个图像中的一个特定部分,我决定使用ssh扩展其中一个容器,以便我可以从PyCharm进行调试。此外,我希望应用程序在启动时正常运行,并且只强制它退出然后从PyCharm连接到它我是否有可调试的组件。以下是我在mac上使用boot2docker(在VirtualBox上)正确设置docker的方法。
首先,我需要扩展名为jqworker
的目标容器。我将使用"supervisior"
来完成繁重的管理工作。
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来调试代码,而不是将其部署到字段,这是我们扩展现有容器而不是将其添加到部署结构的一个原因。我在本地运行它,以便我可以在上下文中调试代码。
这是supervisord.conf文件,请注意我使用supervisor-stdout包将输出定向到主管而不是记录数据,因为我更喜欢在一个地方看到它:
[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
我有一个包含上述两个文件的构建目录,从那里的终端我构建了Dockerfile
:
docker build -t fgkrqworker .
这会添加它,以便我可以从docker
或docker-compose
调用它。不要跳过尾随点!
由于应用程序使用docker-compose
运行一组容器,现有的WORKER
容器将替换为解决我的问题的容器。但首先我要表明,在我的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中可用的已知端口,回想一下我正在使用boot2docker
,它使用VirtualBox,但需要将其映射到PyCharm可以获取的位置。在VirtualBox中,打开boot2docker
VM并选择Adapter 1
。有时&#34;附加到:&#34; combo取消选择,所以请注意。在我的情况下,它应该选择NAT
。
点击&#34; Port Forwarding&#34;并将内部端口映射到localhost上的端口,我选择使用相同的端口号。应该是这样的,名字:ssh_mapped
;议定书:TCP
;主机IP:127.0.0.1
;主机端口:7722
;访客IP:;访客端口:7722
。注意:注意不要更改boot2docker`ssh&#39;设置或您最终无法正确启动VM。
所以,此时我们有一个扩展我的目标容器的容器。它在端口22上运行ssh并将其映射到7722,因为其他容器可能想要使用22,并且在VirtualBox环境中可见。 VirtualBox将7722到7722映射到localhost,您可以使用以下命令ssh进入容器:
ssh root@localhost -p 7722
然后会提示输入密码,&#39; soup4nuts&#39;并且您应该能够找到特定于容器的东西,以验证它是正确的,并且一切正常。如果我在除了本地机器之外的任何地方部署它,我不会乱用root,所以要警告。 这仅适用于本地调试,您应该在现场网站上三思而后行三次或三次。
此时,如果您使用过PyCharm的远程调试,您可能会想到剩下的部分。但这是我如何设置它:
首先,回想一下我有docker-compose.yml
映射项目目录:
? /Users/me/source/myproject:/opt/applications/myproject
我的容器/opt/applications/myproject
实际上是/Users/me/source/myproject
在我的本地硬盘上。所以,这是我项目的根源。我的PyCharm将此目录视为项目根目录,我希望PyCharm在此处编写.pycharm_helpers
,以便它在会话之间保持不变。我在mac方面管理源代码,但是PyCharm认为它在其他地方是一个unixy盒子。是的,在JetBrains采用Docker解决方案之前,这是一个很大的问题。
首先,转到Project X / Project Structure并创建本地映射的Content Root,在我的情况下,这意味着/Users/me/source/myproject
稍后,返回并将.pycharm_helpers
添加到排除的集合中,我们不希望这最终导致源代码管理或混淆PyCharm。
转到构建,执行,部署选项卡,选择部署并创建新的SFTP部署类型。主机是localhost,端口为7722,根路径为/opt/applications/myproject
,用户名为root
,密码为soup4nuts
,我选中了保存密码的选项。我命名我的部署&#39; dockercompose&#39;这样我以后就能把它拿出来。
在“部署映射”选项卡上,我将本地路径设置为/Users/me/source/myproject
,并将部署和Web路径设置为单个&#39; /&#39;但由于我的代码与URL不对应而且我不使用它进行调试,因此它是Web Path设置中的占位符。我不知道你怎么设置你的。
在Project X / Project Interpreter选项卡上,创建一个新的Remote Python Interpreter。您可以选择“部署配置”并选择“#dockercompose”&#39;我们上面创建的配置。主机URL应填写为&#39; ssh:// root @ localhost:7722&#39;并且Python解释器路径可能是/usr/bin/python
。我们需要设置PyCharm Helpers Path,因为默认情况下,容器无法重做。我实际上去了我的项目本地目录并在根目录中创建了一个.pycharm_helpers
目录,然后将路径设置为/opt/applications/myproject/.pycharm_helpers
,当我点击确定按钮时,它复制了文件&#34; up&#34 ;到目录。我不知道它是否会自动创建它。
不要忘记项目根选项卡上可能会排除.pycharm_helpers
目录。
此时您可以转到Build,Execution,Deployment选项卡,然后在Console / Python控制台下,选择我们上面创建的远程解释器并将工作目录设置为/opt/applications/myproject
,然后运行Python控制台如果你愿意,可以放在容器里。
现在您需要创建一个运行配置,以便您可以远程调试您的python代码。创建一个新的Python配置并将脚本设置为用于在容器中启动python代码的脚本。从上面的主管设置来看,我的是:
/opt/applications/myproject/worker.py -A args
所以我将脚本设置为/opt/applications/myproject/worker.py
,参数设置为-A args
。
选择我们上面创建的远程解释器,并根据需要选择工作目录,对我来说是/opt/applications/myproject
,对我来说是完成这项工作的。
现在我想输入我的容器并停止worker.py脚本,以便启动调试版本。当然,如果您愿意,可以忽略默认运行脚本,只使用容器进行调试。
我可以打开一个ssh会话来停止脚本,但是docker提供了一个有用的命令,可以通过将它传递给环境来为我做这项工作。
$> docker exec -i -t supervisorctl stop worker
由于我的流程被命名为&#39; worker&#39;。请注意,您可以通过将stop
命令替换为start
来重新启动。
现在,在PyCharm中,使用上面创建的运行配置启动调试会话。它应该连接并启动,并在窗口中为您提供控制台输出。由于我们杀死了监督最初开始的那个,它已不再连接。
这是裤子操作的一个席位,所以可能会有错误和错误的假设我没有注意到。特别是,PyCharm设置需要几次迭代,因此顺序可能不正确,如果失败则再试一次。这是很多东西,很容易跳过一些关键的东西。
答案 1 :(得分:3)
现在还没有,但很快就会出现问题,因为
从PyCharm 4.1 EAP(4月初)开始,将在PyCharm中引入Docker支持
答案 2 :(得分:2)
为了避免任何SSH开销(这对Docker来说非常合理),docker exec
似乎绝对是可行的方法。
不幸的是,到目前为止,我无法让它工作。如果有人可以填补空白,那就太棒了。这是我做的(使用PyCharm 4.0.4和Docker 1.4.1):
创建一个名为python_myproject.sh
的文件,其中包含以下内容:
#!/bin/bash
docker exec -i myproject_container /path/to/containers/python2.7
请注意,文件的名称必须以python
开头,否则PyCharm会抱怨。
在PyCharm的设置中,在Project Interpreter
下,添加一个新的本地解释器。为其指定python_myproject.sh
文件的路径。
这就是我被困住的地方。经过相当长的加载时间(throbber说“设置库文件”)后,会出现一个名为“Invalid Python SDK”的窗口并说:
无法设置python SDK
at /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
答案 3 :(得分:2)
如果您真的需要,我认为在您的容器中包含SSH并不是很糟糕。是的,自引入docker exec
以来,它在其他用例中并不重要,但由于Intellij / PyCharm仅通过SSH支持远程解释器,所以没关系。
您可以使用phusion/baseimage
作为一个良好的起点,使用SSH和您需要的任何版本的Python构建自己的容器(默认情况下是PY3)。
理论上,继续使用Vagrant进行此任务也是理想的,因为它允许您创建一个可在Windows / OS X计算机(通过使用boot2docker)和Linux(本机Docker)上工作的工作流。 / p>
实际上我无法在OS X上运行,因为你必须通过双层NAT才能进入SSH服务,看起来不可能为Vagrant boot2docker添加额外的接口盒子(Vagrant 1.7.2)。
答案 4 :(得分:2)
如果您只需调试在docker容器中启动的代码,则可以使用pycharm的python debug server功能。至于我,它比通过SSH访问远程解释器更麻烦。这个解决方案的缺点是,对于自动完成和所有这些东西,你应该有容器解释器的本地副本,并将其标记为项目的解释器(适用于自动完成,但我不确定是否可以从中调试代码在这种情况下的第三方库)或使pycharm可以看到容器的解释器文件(根本没有测试)。另请注意,Python调试服务器为feature of Professional edition。
通过Python调试服务器进行调试应该做什么:
1)确保将项目目录添加到容器中。它看起来像Dockerfile中的这一行:
ADD . /path/in/container
2)将pycharm-debug.egg
(Python的pycharm-debug-py3k.egg
)从主机上安装了pycharm的目录复制到容器中的目录,该容器位于容器的PYTHONPATH中。
开发人员主机上pycharm-debug.egg的路径可能是:
/Applications/PyCharm.app/Contents/pycharm-debug.egg
/opt/pycharm/pycharm-debug.egg
3)创建运行/调试配置,以便在docs的To configure a remote debug server
部分所述的主机上启动Python调试服务器。端口是您选择的任何主机端口,但IP是可从容器访问主机的地址。它可能是:
ifconfig
找到IP,对我来说就是: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
另外,不要忘记在开发人员主机的项目路径和容器的项目路径之间指定路径映射。
This blog post also could be helpful for current step
4)启动此创建的配置(例如,通过Debug
按钮,直接从Run
一个)
5)创建python脚本,它将启动你的项目,并为调试初始化添加以下代码作为此脚本的第一行。 (确保pycharm-debug.egg
在PYTHONPATH中,或者此代码不能import pydevd
):
import pydevd pydevd.settrace('172.17.42.1', suspend=False, port=8765, stdoutToServer=True, stderrToServer=True)
6)最后,您可以通过创建的脚本在容器中设置断点并从主机启动应用程序。例如:
docker-compose run 'container_name' python 'script_name' 'args'
一开始,您的启动脚本将连接到在主机上运行的Python调试服务器,并在断点处停止。调试器功能将照常提供。
答案 5 :(得分:1)
特定于PyCharm专业版2017.2的步骤(但它们可能与PyCharm CE一起使用)
我采取了几个步骤让我的设置正常工作
对您(或可能正在阅读此内容的任何人)项目结构的一些假设:
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
。 api
服务,如后面docker-compose.yml
文件中所示 注意我们还会假设您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
包含这些内容
bleh
专门为docker-machine create bleh
项目
PyCharm
Preferences
/ Build, Execution, Deployment
/ Docker
/ +
点击Docker machine
bleh
单选按钮并在下拉菜单中突出显示Apply
的泊坞机PyCharm
Preferences
/ Project:bleh
/ Project Interpreter
/ Project Interpreter
Add Remote
字段最右侧的齿轮图标,然后选择Docker
Server
单选按钮bleh_api
字段,为此项目选择以前创建的泊坞机Python interpreter path
)OK
所需Run
Edit Configurations
/ +
选择Python
添加配置Script
/usr/bin/bleh/__main__.py
字段,在将要运行的docker容器上使用脚本文件的位置(在此示例中,它是Script parameters
,因为我们给出了目标脚本的绝对位置)Dockerfile
字段,提供CLI参数(如果有)(模仿CMD
的最后--cfg=/etc/bleh/config.ini
命令,Python Interpreter
)Working directory
字段,选择您之前建立的远程python解释器Script
字段,选择Docker容器中/usr/bin/bleh
所在的目录(例如Path mappings
)...
字段,点击/Users/myfunkyusername/Projects/bleh/api/src
并选择本地(例如/usr/bin/bleh
)和远程(例如Docker container settings
),如上所述...
字段,点击bleh_api:latest
Dockerfile
)0.0.0.0
中的内容(例如8080/8080,并使用tcp
协议公开8080
,现在我没有' t显示了您的应用结构是什么,但我们假设您是理智的,并且在您的应用中也指定/usr/bin/bleh
作为您提供数据的端口。/Users/myfunkyusername/Projects/bleh/api/src
/ Network mode
<name_of_project_directory>_<name_of_network_from_compose_file>
(thanks Piotr)设置为bleh_default
(例如docker network ls
,您可以在正确的docker-machine
内与$(document).ready
确认)这些是让我进入工作码头和PyCharm设置的步骤。
我并不假装在每个步骤中都是正确的。我很乐意更新您找到的任何错误/改进。
答案 6 :(得分:0)
使用Docker 1.3,使用exec
命令构建Python解释器的路径:
sudo docker exec container_name /usr/bin/python
请参阅https://docs.docker.com/reference/commandline/cli/#exec,http://forum.jetbrains.com/thread/PyCharm-2224
您可以在容器中安装SSH,然后公开端口,但这不是预期如何使用容器,因为您会膨胀它们。
答案 7 :(得分:0)
我还没试过这个,但我会尝试创建一个调用docker exec ...
的Bash脚本,就像@Anto's answer一样。
然后,安装BashSupport extension。现在create a new run configuration将您的脚本作为Bash脚本运行。
答案 8 :(得分:0)
你可以通过在容器中安装pycharm并从那里运行它来获得一点疯狂。你必须通过“docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY =:0.0 pycharm-image”来做到这一点,但它应该可以正常工作。但请记住,所有pycharm和你的源代码也都在那个容器中。因此,请尽早保存,提交和推送。
答案 9 :(得分:0)
使用PyCharm 5,他们增加了对docker的支持。您必须在docker-machine中配置docker。
如果您还没有使用docker-machine,则可以使用通用机器引擎连接到现有计算机,如果您不在VM中运行,则可以将ssh连接到vagrant VM或localhost。不幸的是,我没有找到绕ssh到localhost的方法。
我还没有找到一种方法将卷装入他们使用的docker镜像中,与我的开发树共享文件,但这可能是可能的。