Подтвердить что ты не робот

Как подключить PyCharm к интерпретатору python, расположенному внутри контейнера Docker?

Я начинаю с Docker, но я не знаю, как настроить PyCharm на использование интерпретатора python, расположенного в контейнере.

Было легко настроить с помощью Vagrant, но там явно не было официального способ сделать это с помощью Docker.

Должен ли я подготовить специальное изображение Docker с открытым портом ssh? Как это сделать проще?

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: PyCharm 2017.1 имеет решение этой проблемы, см. эту запись в блоге

Вот как я решил проблему. Мои обстоятельства таковы, что мне поручили вмешательство в определенную область веб-приложения, которое использовало docker-compose для создания набора из четырех контейнеров. Docker-compose - это вид мета-докера, который управляет несколькими контейнерами-докерами из одной команды. Я не хотел портить их существующую настройку, так как от этого зависит очень много вещей. Но так как я работал над одной конкретной частью на одном из изображений, я решил, что я расширю один из контейнеров с помощью ssh, чтобы я мог отлаживать из PyCharm. Кроме того, я хотел, чтобы приложение запускалось как обычно при запуске, и только принудительно завершив его работу и подключившись к нему из PyCharm, я получил бы отлаживаемый компонент. Вот что я сделал на своем Mac, который использует boot2docker (на VirtualBox) для правильной настройки докера.

Сначала мне нужно расширить целевой контейнер, который называется 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 '[email protected]\s*required\s*[email protected] optional [email protected]' -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. Да, все говорят, что 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 с известным портом, доступным в виртуальной машине, напомним, что я использую boot2docker, который работает на VirtualBox, но необходимо сопоставить его с тем, где PyCharm может добраться до него. В VirtualBox откройте виртуальную машину boot2docker и выберите Adapter 1. Иногда комбо "Attached to:" отменяет выбор, так что следите за этим. В моем случае он должен был выбрать NAT.

Нажмите "Переадресация портов" и сопоставьте внутренний порт с портом на локальном хосте, я решил использовать тот же номер порта. Это должно быть что-то вроде:

  • Имя: ssh_mapped;
  • Протокол: TCP;
  • IP-адрес хоста: 127.0.0.1;
  • Порт хоста: 7722;
  • Гостевой IP :;
  • Гостевой порт: 7722

Примечание: будьте осторожны, чтобы не изменить настройку boot2docker ssh, иначе вы не сможете правильно запустить виртуальную машину.

Итак, на данный момент у нас есть контейнер, который расширяет мой целевой контейнер. Он запускает ssh на порту 22 и отображает его на 7722, поскольку другие контейнеры могут захотеть использовать 22, и он виден в среде VirtualBox. VirtualBox сопоставляет 7722 с 7722 локальный хост, и вы можете войти в контейнер с помощью ssh:

ssh [email protected] -p 7722

После этого появится запрос на ввод пароля 'sou4nuts', и вы сможете найти что-то конкретное для вашего контейнера, чтобы убедиться, что он правильный и все работает нормально. Я бы не связывался с 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 думает, что в других местах это не совсем удобно. Да, это немного мешает, пока JetBrains не использует решение Docker.

Сначала перейдите в Project X/Project Structure и создайте корень контента локального сопоставления, в моем случае это означает /Users/me/source/myproject

Позже вернитесь и добавьте .pycharm_helpers к исключенному набору, мы не хотим, чтобы это заканчивалось управлением исходным кодом или приводило к путанице PyCharm.

Перейдите на вкладку "Сборка, выполнение, развертывание", выберите "Развертывание" и создайте новое развертывание типа SFTP. Хост - localhost, порт 7722, корневой путь - /opt/applications/myproject, имя пользователя - root, пароль - soup4nuts, и я проверил опцию сохранения пароля. Я назвал свое развертывание "dockercompose", чтобы позже его можно было найти.

На вкладке "Сопоставления развертывания" я установил для локального пути /Users/me/source/myproject, а для развертывания и веб-пути - один символ "/", но поскольку мой код не соответствует URL-адресу, и я не использую его для отладки, он является заполнителем в настройка веб-пути. Я не знаю, как вы могли бы установить свои.

На вкладке Project X/Project Interpreter создайте новый удаленный интерпретатор Python. Вы можете выбрать конфигурацию развертывания и выбрать конфигурацию dockercompose, которую мы создали выше. URL хоста должен быть заполнен как ssh://[email protected]:7722, а путь интерпретатора Python, скорее всего, будет /usr/bin/python. Нам нужно установить путь помощников PyCharm, так как по умолчанию он не сохранится при повторном контейнере. На самом деле я зашел в локальный каталог своего проекта и создал каталог .pycharm_helpers в корневом каталоге, затем установил путь здесь как /opt/applications/myproject/.pycharm_helpers, и когда я нажал кнопку OK, он скопировал файлы "вверх" в каталог. Я не знаю, создаст ли он это автоматически или нет.

Не забывайте, что каталог .pycharm_helpers, вероятно, следует исключить на вкладке корней проекта.

На этом этапе вы можете перейти на вкладку Build, Execution, Deployment и в Console/Python Console выбрать удаленный интерпретатор, который мы создали выше, и установить рабочий каталог на /opt/applications/myproject, и вы можете запустить вашу Python Console в контейнере, если вы как.

Теперь вам нужно создать конфигурацию запуска, чтобы вы могли удаленно отлаживать код 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

Поскольку мой процесс называется "работник". Обратите внимание, что вы можете перезапустить, заменив команду stop на start.

Теперь в PyCharm запустите сеанс отладки с конфигурацией запуска, созданной выше. Он должен подключиться и запустить все, и вы получите консольный вывод в окне. Поскольку мы убили того, кого изначально начал Supervision, он больше не подключен.

Это было место операции штанов, поэтому могут быть ошибки и неправильные предположения, которые я не заметил. В частности, для установки PyCharm потребовалось несколько итераций, поэтому порядок может быть неправильным, попробуйте повторить его снова, если он потерпит неудачу. Это много вещей и легко пропустить что-то критическое.

Ответ 3

Чтобы избежать каких-либо накладных расходов 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" и говорит:

Невозможно настроить SDK python
в/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

Ответ 4

Я не думаю, что так сложно включать SSH в ваш контейнер, если вам это действительно нужно. Да, это не важно в других случаях использования с момента введения docker exec, но поскольку Intellij/PyCharm поддерживает только удаленный интерпретатор через SSH, это нормально.

Вы можете использовать phusion/baseimage в качестве хорошей отправной точки для создания собственного контейнера с SSH и любой версии Python, которая вам нужна (она поставляется по умолчанию с PY3).

Теоретически, было бы идеальным продолжать использовать Vagrant для этой задачи, так как это позволяет вам создать рабочий процесс, который будет работать как на машинах Windows/OS X (с помощью boot2docker), так и на Linux (родной Docker).

Практически я не смог заставить его работать с OS X из-за двойного слоя NAT, который вы должны пройти, чтобы войти в службу SSH, и похоже, что невозможно добавить дополнительный интерфейс к брандмауэру boot2docker (Vagrant 1.7.2).

Ответ 5

Если вам нужно отлаживать код, который запускается внутри контейнера докеров, вы можете использовать pycharm сервер отладки python функция. Что касается меня, это менее проблематично, чем доступ к удаленному интерпретатору через SSH. Недостатком этого решения является то, что для автозаполнения и всего этого типа вы должны иметь локальную копию интерпретатора контейнера и отмечать его как интерпретатор проекта (работает для автозаполнения, но я не уверен, что можно отлаживать код из сторонние библиотеки в таком случае) или сделать файлы контейнера-интерпретатора видимыми для pycharm (не тестируются вообще). Также обратите внимание, что сервер отладки Python является функцией Professional edition.

Что вы должны сделать для отладки через сервер отладки Python:

1) убедитесь, что каталог с вашим проектом добавлен в контейнер. Это может выглядеть так: Dockerfile:

ADD . /path/in/container

2) скопируйте pycharm-debug.egg (pycharm-debug-py3k.egg для Python3) из каталога, где pycharm установлен на вашем хосте в каталог в контейнере, который находится в контейнере PYTHONPATH. Путь к pycharm-debug.egg на хосте разработчика может быть:

  • для Mac: /Applications/PyCharm.app/Contents/pycharm-debug.egg
  • для Linux: /opt/pycharm/pycharm-debug.egg

3) создать конфигурацию запуска/отладки для запуска сервера отладки Python на хосте, как описано в разделе To configure a remote debug server docs. Порт - любой хост-порт по вашему выбору, но IP-адрес, на котором хост доступен из контейнера. Это может быть:

  • Если контейнер запускается через boot2docker, вероятно, IP-адрес 192.168.99.1 - адрес хоста в сети только для хоста с помощью машины vbox
  • Если хост Linux, IP можно найти через ifconfig, для меня это:
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

Кроме того, не забудьте указать сопоставления пути между пути проекта на хосте разработчика и пути к проекту в контейнере.

Это сообщение также может быть полезно для текущего шага

4) запустите эту созданную конфигурацию (например, с помощью кнопки Debug, прямо от Run one)

5) создайте python script, который запустит ваш проект и добавит следующий код для инициализации отладки в качестве первых строк этого script. (убедитесь, что pycharm-debug.egg находится в PYTHONPATH, или этот код не может import pydevd):

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

6) Наконец, вы можете установить точки останова и запустить приложение с хоста в контейнере через созданный script. Например:

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

При запуске ваш запуск script будет подключен к серверу отладки Python, который запущен на хосте, и остановится на контрольных точках. Функции Debugger будут доступны как обычно.

Ответ 6

Шаги, специфичные для PyCharm Professional Edition 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.
  • Примечание. Очевидно, что это все случайное отношение к наименованию и местоположению, внесите корректировки, специфичные для вашей системы/проекта.
  • Примечание. Мы также предположим, что вы хотите отлаживать службу 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
    

Шаг 2: Создание докерной машины

Создайте докер-машину специально для проекта bleh

docker-machine create bleh

Шаг 3: подключить удаленный интерпретатор

  • Из PyCharm/Preferences/Build, Execution, Deployment/Docker нажмите +
  • Выберите переключатель Docker machine и выделите док-станцию ​​bleh в выпадающем меню
  • Выберите Apply
  • Из PyCharm/Preferences/Project:bleh/Project Interpreter
  • Щелкните значок шестеренки в правом углу поля Project Interpreter и выберите Add Remote
  • Выберите переключатель Docker
  • В поле Server выберите ранее созданный докер-машину для этого проекта
  • Выберите изображение докеры, которое содержит нужный интерпретатор python для этого проекта (например, bleh_api)
  • Не требуется изменение Python interpreter path
  • Нажмите OK

Шаг 4: настроить удаленный отладчик

  • От Run/Edit Configurations выберите +, чтобы добавить конфигурацию
  • Выберите Python
  • В поле Script используйте расположение файла script в контейнере докера, который будет запущен (в этом примере он /usr/bin/bleh/__main__.py, поскольку мы даем абсолютное местоположение нашей целевой script)
  • В поле Script parameters введите параметры CLI, если они есть (имитирует команду Dockerfile last CMD, которая --cfg=/etc/bleh/config.ini)
  • В поле Python Interpreter выберите ранее установленный удаленный интерпретатор python
  • В поле Working directory выберите каталог, в котором Script находится в контейнере Docker (например, /usr/bin/bleh)
  • В поле Path mappings нажмите ... и выберите локальный (например, /Users/myfunkyusername/Projects/bleh/api/src) и удаленный (например, /usr/bin/bleh), как указано выше
  • В поле Docker container settings нажмите ...
    • убедитесь, что выбран правильный контейнер докера (например, bleh_api:latest)
    • Добавьте контейнер/хост с привязкой к портам, который имитирует то, что у вас есть в Dockerfile (например, 8080/8080 и выставляйте 0.0.0.0 с помощью протокола tcp), теперь я не показывал, что такое структура вашего приложения, но допустим, что вы были здравомыслящими, и в вашем приложении также указывается 8080 как порт, в котором вы обслуживаете ваши данные.
    • Добавить объединить привязки контейнер/хост /usr/bin/bleh//Users/myfunkyusername/Projects/bleh/api/src
    • Network mode <<256 > (спасибо Piotr) установлен на <name_of_project_directory>_<name_of_network_from_compose_file> (например, bleh_default, вы можете подтвердить с помощью docker network ls из правильного docker-machine)

Шаг 5: Баск на солнце или Bash голова еще немного

Это шаги, которые привели меня к рабочему докеру и настройке PyCharm.

Я не претендую на правильность каждого из этих шагов. Я с радостью обновляю любые ошибки/улучшения, которые вы найдете.

Ответ 7

С 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 внутри контейнера, а затем открыть порт, но это не значит, что контейнеры должны использоваться, потому что вы будете раздувать их.

Ответ 9

Вы можете немного сойти с ума, установив Pycharm в контейнер и просто запустив его оттуда. Вы должны сделать это с помощью docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=:0.0 pycharm-image, но это должно работать просто отлично. Но помните, что весь Pycharm и ваш источник тоже будут в этом контейнере. Так что сохраняйте, фиксируйте и нажимайте рано и часто.

Ответ 10

С PyCharm 5 они добавили поддержку докера. У вас должен быть установлен ваш докер на докер-машине.

Если вы еще не используете докер-машину, вы можете подключиться к существующей машине, используя общий машинный движок и ssh, в виртуальную виртуальную машину или на локальный хост, если вы не работаете в виртуальной машине. К сожалению, я не нашел пути к ssh к localhost.

Я не нашел способ смонтировать тома в образ докеры, который они используют, для обмена файлами с моим деревом dev, но это возможно.