VS Code, python, контейнеры — как обуздать эту триаду

image

Это небольшой туториал о настройке VS Code для работы с python. Здесь вы не увидите каких-то божественных откровений — тут будет просто мой опыт о том, как сделать свою работу/хобби немного комфортнее и почему я пришел именно к такой конфигурации.

Мой путь к разработке начался через администрирование, и, как и любой админ, я сталкивался с необходимостью писать автоматизацию. Bash/python/powershell/go — это все типичные инструменты инженера. Но в большинстве своем мы пишем автоматизацию в vim/nano/notepad++. И на все рассказы про IDE я лишь пожимал плечами — «а мне то это зачем?». Но однажды появился проект на Python, где я стал писать код уже «в промышленных масштабах»… Результат предсказуем — я пересел на VS Code.
Почему он? Да все просто:


  • Быстрый
  • Удобный
  • Бесплатный
  • Куча плагинов

Я осознал прелесть линтера (линтер (linter) — это программа, которая автоматизирует «причёсывание» кода по определённым правилам), подсказки синтаксиса, и прочие прелести современных IDE.
Но разбираться в VS Code «все еще было некогда». И в один прекрасный момент за эту лень я поплатился сполна — у меня закрылся VScode с ошибкой и при запуске у меня открылось пустое окно. Это был шок. Привычка писать в пустых файлах, кое-как настроенные параметры запуска отладки, настройки linter-а и подсказок по синтаксису — все это в полной мере дало о себе знать. И в итоге было принято решение разобраться что тут к чему и как мне сохранить свои настройки.
В итоге мое изучение VS Code разделилось на три этапа:


  1. Единые настройки на все проекты.
    С этого я начал, но очень быстро понял, что мне необходимо делать отдельные настройки для разных проектов.
  2. Отдельные настройки под каждый проект.
    Почти идеальный вариант, если бы не проблемы со сборкой некоторых специфических библиотек под MacOS.
  3. Разработка в контейнерах.
    Очень интересный вариант разработки, лично мне он показался очень удобным.

Из коробки VS Code можно назвать «весьма продвинутым блокнотом». В общем то так бы все и осталось, если бы не система плагинов — с их помощью можно превратить VS Code практически во что угодно.
Теперь немного теории, чтобы мы одинаково понимали используемые термины и у нас был единый контекст. Почему это в моем понимании важно? Да потому что я мучался с этим достаточно долго, пока не собрал свою порцию шишек и граблей.
Понятия:


  1. Workspace
    В VS Code работа очень многое крутиться вокруг такого понятия как Workspace. В заложенной логике Workspace — это папка с вашим проектом, область применение настроек и параметров запуска отладки.
    Системные папки в Workspace и их назначение:
  2. .vscode
    Точка в начале — обязательна. В этой папке vscode ищет настройки окружения и запуска отладки для данного Workspace.
  3. .devcontainer
    Точка в начале — обязательна. В этой папке vscode ищет настройки контейнеров и Dockerfile для сборки для данного Workspace.

Область видимости настроек:


  1. User
    Настройки сохраняются для конкретного пользователя
  2. Workspace
    Настройки сохраняются для конкретной области

Файлы и их назначение:


  1. %name%.code-workspace
    Настройки для данного Workspace. Может содержать настройки плагинов, путей к интерпретатору и тому подобное. Удобно, можно передавать его другим.
  2. launch.json
    Настройка логики и параметров запуска отладки проекта. Может содержать несколько вариантов настройки для одного и того же проекта.
  3. settings.json
    Может содержать настройки плагинов, путей к интерпретатору и тому подобное. Переопределяет настройки из %name%.code-workspace.
  4. devcontainer.json
    Файл содержащие настройки процесса сборки контейнера и его содержимого


Что нужно для старта?

В целом все просто — надо поставить сам python, поставить нужные расширения и сделать настройки. Кажется, что все банально, но как обычно «дьявол кроется в деталях».


Настройка Python

Для того, чтобы начать разрабатывать на питоне с помощью VS Code надо сделать 3 вещи:


  1. Установить сами python (думаю с этим вы сами справитесь).
  2. Поставить набор плагинов для разработки (делается в самом VS Code, занимает минимум времени).
  3. Настроить различные дополнительные модули для более комфортной и качественной работы. Это:
    • linter (я использую flake8).
    • language server (настраивается в файле settings.json, я использую Pylance) (Вот тут неплохая статья описывающая что это и зачем это). Тут как раз обычно и скрыта вся магия.
    • параметры запуска отладки (файл launch.json). Вторая часть магии.

Плагины, необходимых для работы с python-ом:


  • Python Extension Pack (id — donjayamanne.python-extension-pack)
    В этот плагин входит все, что нужно для разработки на python
  • Dev Containers (id — ms-vscode-remote.remote-containers)
    Этот плагин нужен для работы в контейнерах


Настройка удаленной разработки

Об этом я бы хотел тоже упомянуть, так как это очень удобная история. Есть такой набор плагинов от компании Microsoft — Remote Development (id — ms-vscode-remote.vscode-remote-extensionpack). Туда входят:


  • Remote — Tunnels
    Назначение этого плагина не знаю, не разбирался
  • Dev Containers
    Этот плагин позволяем нам разрабатывать и/или отлаживать код в контейнерах. Обязателен для установки, если хотите работать в контейнерах.
  • Remote — SSH
    Этот плагин предназначен для удаленной разработки с подключением к удаленному хосту по ssh. Причем вы можете не только редактировать файлы или запускать команды, но и заниматься полноценной разработкой с отладкой и всем прочим. Проблема с сохранением файлов, на которых нет прав, может решить плагин sudo (Save as Root in Remote — SSH, id yy0931.save-as-root).
  • WSL
    Этот плагин очень поможет пользователям Windows — с его помощью можно разрабатывать в среде полноценного Linux, подключаясь к нему через WSL.


Лирическое отступление. 'Емае… Что ж я сделал то…' © реклама из 90-тых.

Все было очень просто, пока репозиторий был один. Кое-как я настроил какие-то совсем базовые вещи и на этом успокоился. Проблемы этого подхода всплыли тогда, когда репозиториев стало три и в одном из них использовался не python, а Go. Ну и конечно же по классике — я не использовал venv =)
Вот небольшой список тех проблем, которые я испытывал постоянно:


  • Периодически отваливались импорты в python. Лечилось это переустановкой пакета и перезапуском приложения. (Да-да, это все еще было терпимо, так как происходило не часто)
  • Запуск проектов был не самым простым делом, но я как настоящий самурай написал bash-скрипты для запуска. (Чего только не сделаешь, лишь бы не читать доки)
  • Когда появился Go — на нем просто не работала отладка… В итоге отладкой я занимался в виртуалке…
    Ну и добил меня случай, который я описал выше — я профукал настройки Workspace по дефолту.
    И вот, мой дорогой читатель, сижу я перед ноутом, смотрю в пустую страницу VS Code и понимаю, что час настал…

Как я уже говорил, Workspace в VS Code это по сути свое область видимости настроек. Осознав это, я с ужасом понял, что мою идеологию «одно окно — много проектов» можно похоронить. Но остатки надежды говорили, что я не один такой и возможно решение есть среди тысяч плагинов, которые есть для VS Code. Но все оказалось даже лучше, начиная с версии 1.18 этот функционал доступен из коробки. И тут у меня начал вырисовываться примерный план приведения в порядок моего рабочего места разработчика. Он был в целом прост:


  1. Сделать отдельную корневую папку для всех проектов.
  2. Каждый проект лежит в отдельной директории.
  3. Для каждого из проектов я сделаю свои отдельные настройки.
  4. Все общие настройки буду хранить в корневой общей папке.

Сказано — сделано. В итоге у меня появился такая структура каталогов:

Development
├───.vscode
│   └───my_dev_env.code-workspace
├───First project
│   ├───!env
│   │   ├───prod.evn
│   │   └───dev.env
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
├───Second project
│   ├───!env
│   │   ├───prod.evn
│   │   └───dev.env
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
└───Third project
    ├───!env
    │   ├───prod.evn
    │   └───dev.env
    ├───.vscode
    │   ├───launch.json
    │   └───settings.json
    └───app
        ├───file111.txt
        ├───file112.txt
        └───...

Начнем по порядку:


  • Development/.vscode/my_dev_env.code-workspace.
    тут лежат пути к папкам и общие настройки для всех Workspace. В этом файле мы определяем общие настройки на все проекты. Переопределить их можно с помощью локального файла с настройками — settings.json, он будет описан ниже. Пример файла (описание всех свойств даны в самом файле):

    {
    // Список папок, которые должны попасть в вашу multi-root.
    // Пути можно использовать абсолютные, поэтому можно собирать
    // воедино папки из разных мест
    "folders": [
        {
            "path": "/Development/First project"
        },
        {
            "path": "/Development/Second project"
        },
        {
            "path": "/Development/Third project"
        }
    ],
    // Общие настройки. Они являются дефолтными для всех включенных директорий,
    // но могут переопределяться на уровне конкретной корневой папки проекта.
    // Тут собраны те, что использую я
    "settings":  {
        "git.autofetch": true,
    // Включить или выключить периодический поиск изменений в удаленном
    // репозитории. В случае, если включено в VS Code в разделе работы 
    // с git будет показывать сколько неполученных коммитов есть
    // в удаленном репозитории.
        "python.languageServer": "Pylance",
    // Выбор language server. У Python их несколько, с последнего времени
    // по дефолту используется Pylance. На мой взгляд лучше оставить его,
    // так как его делает Microsoft и он активно развивается.
        "python.defaultInterpreterPath": "/opt/homebrew/bin/python3.10",
    // Дефолтный путь для Питона
        "python.analysis.diagnosticMode": "openFilesOnly",
    // Выбор области, где производится анализ файлов на ошибки.
    // Я выбрал вариант "только открытые файлы" чтобы меньше логало
        "python.analysis.autoImportCompletions": true,
    // Включает автоматическое добавление импорта модуля, если его нет,
    // но в коде найдены на него ссылки
        "python.analysis.typeCheckingMode": "off",
    // Очень полезная, но очень суровая опция - включает проверку
    // соответствия типов для языкового движка Pylance. По сути попытка
    // сделать из Python типизированный язык. Доступные значения:
    //  off: анализ проверки типа не проводится; производится диагностика
    //       неразрешенных импортов/переменных
    //  basic: Правила, не связанные с проверкой типов (все правила в off)
    //         + базовые правила проверки типов
    //  strict: все правила проверки типов с наивысшей серьезностью ошибки
    //          (включая все правила в категориях off и basic)
    "python.analysis.inlayHints.variableTypes": true,
    // Анализирует ваши переменные и предлагает для них подходящие типы.
    // Так же позволяет двойным кликом добавить тип
    "python.analysis.inlayHints.functionReturnTypes": true,
    // Анализирует ваши функции и классы и предлагает подходящие типы
    // выходных данных. Так же дает подсказки, какой выходной тип вы получите
        "python.terminal.activateEnvironment": true,
    // Если в проекте найдено виртуальное окружение, то в терминале оно
    // будет автоматически активироваться при переходе в этот проект
        "python.linting.enabled": true,
    // Включает линтер для питона
        "python.linting.flake8Enabled": true,
    // Выбор каким линтером пользоваться.  Я выбрал flake8.
        "python.linting.flake8Args": [
            "--max-line-length=250",
    // "--ignore=E402,F841,F401,E302,E305",
        ],
    // Настройки flake8. Я лично выставил себе только увеличение максимальной
    // длинны строки - по дефолту 80, этого мало для меня
        "[python]": { 
    // Настройка автоматического форматирования. Удобно тем, что при сохранении
    // автоматически приводит форматирование к правильному по мнению форматора виду
            "editor.defaultFormatter":"ms-python.python",
    // Выбор форматера
            "editor.formatOnSave": true,
    // Включает форматирование при сохранении
            "editor.codeActionsOnSave": {
                    "source.organizeImports": true
    // Форматирует импорты. Могут быть проблемы, если импорты зависят друг от друга
            },
        "files.exclude": {
    // Крайне полезная на мой взгляд функция - задается список файлов, которые
    // исключаются из показа в дереве каталогов. Отлично подходит для скрытия всяких
    // ненужных системных каталогов
      "**/.git": true,
            "**/__pycache__": true,
            "**/.DS_Store": true,
        "**/Thumbs.db": true
    },
        "files.watcherExclude": {
    // еще одна крайне любопытная опция - за изменениями файлов из
    // этого списка VS Code не следит
            "**/.git/objects/**": true,
            "**/.git/subtree-cache/**": true,
            "**/node_modules/*/**": true,
            "**/.hg/store/**": true,
            "**/__pycache__/**": true,
            "**/.venv-*/**": true
        },
    "files.enableTrash": false,
    // Включение/выключение корзины. Если False то файлы удаляются сразу же
    "cSpell.language": "en,ru",
    // Крайне полезный плагин и настройки - проверка орфографии.
    // Настоятельно рекомендую к установке
    "cSpell.words": [
    // Тут список слов, которые мы добавили в исключения
            "Clickhouse",
            "fastapi",
            "jsonify",
            "loguru"
        ]
    }
    }

  • Далее идет папка .vscode внутри папки проекта. Тут мы видим два файла — settings.json и launch.json.
    Файл settings.json нужен для того, чтобы переопределить параметры из одноименной секции файла workspace (my_dev_env.code-workspace). Вот пример файла

    {
    "python.defaultInterpreterPath": "${workspaceFolder}/.venv-first-project/bin/python3.10",
    // Переопределяем путь к Python. Тут есть два интересных момента:
    //    1. используется переменная ${workspaceFolder} - она обозначает
    //       корневую папку проекта
    //    2. Путь указывает сразу же в каталог с виртуальным окружением
    "python.envFile": "${workspaceFolder}/!env/dev.env",
    // Крайне полезная директива - она позволяет задать переменные окружения,
    // которые будут использоваться при запуске Python. Очень помогает при отладке
    // при pytest, которым нужны переменные из окружения для работы
    }

    Файл launch.json нужен для настройки запуска отладки приложения. Оооо… Насколько же моя жизнь стала проще, когда я открыл для себя этот файл…

    {
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
    // Важно - можно делать сколько угодно наборов настроек отладки
    {
      "name": "First project - Dev",
    // Наименование набора настроек для запуска и отладки. Выводится в
    // выпадающем списке при запуске отладки. Мне нравится сюда вписывать проект
    // и окружение, в котором будет запущена отладка
      "type": "python",
    // указание какой язык используется - нужно для запуска нужного
    // набора параметров отладки
      "request": "launch",
    // Указывает режим, в котором следует начать отладку.
    //   - launch - если вы запускаете код локально
    //   - attach - если вы используете удаленную отладку
    // (но эта история более сложная, поэтому тут я ее не буду описывать)
      "program": "${file}",
    // Путь к исполняемому файлу. По умолчанию ${file} обозначает файл,
    // который выбран сейчас в активном окне. Если прописать туда какой-то
    // конкретный файл, то запускается будет всегда он, вне зависимости
    // от того, какое окно у вас сейчас выбрано.
      "console": "integratedTerminal",
    // Указатель того, куда выводить stdout и stderr.
    // По умолчанию - встроенный терминал.
    // Менять в моем понимании надо только если ты четко понимаешь что делаешь )
      "python": "${workspaceFolder}/.venv/bin/python3.10",
    // путь к интерпретатору, с помощью которого запускаться проект
      "cwd": "${workspaceFolder}",
    // Указывает каталог, из которого запускается для отладчика,
    // который является базовой папкой для любых относительных путей,
    // используемых в коде. Если опущено, по умолчанию используется ${workspaceFolder}.
      "jinja": true,
    // Активирует специфические параметры окружения для отладки шаблонов jinja
      "envFile": "${workspaceFolder}/!env/dev.env",
    // указывает на файл со списком переменных окружения.
    // Есть нюанс - на данный момент не поддерживает многострочные переменные,
    // то есть если вам нужно в окружение добавить большой json - придется
    // сначала перевести его в компактный вид (в одну строку)
      "justMyCode": true,
    // Ограничивает отладку вашим кодом. В случае, если стоит False то отладчик будет
    // показывать шаги и в стандартных библиотеках.
      "presentation": {
    // Настройки видимости этой настройки отладки в списке всех отладок
        "hidden": false,
    // Если True то эта отладка не будет видна в списках
        "group": "api",
    // Имя группы, нужно для логической группировки отладок
        "order": 1
    // Порядковый номер в группе
      },
      "autoReload": {
    // Перезапуск отладки в случае сохранения файла с новым кодом.
    // Если отладка идет в рамках активного файла - перезапустится только он.
        "enable": true
      }
    },
    // Пример настройки для запуска проекта написанного на FastApi
    {
      "name": "FastAPI",
      "type": "python",
      "request": "launch",
      "module": "uvicorn",
    // В отличие от предыдущего раза, где запускается файл из текущего активного окна,
    // тут запускается вполне конкретный модуль
      "console": "integratedTerminal",
      "envFile": "${workspaceFolder}/!env/stage.env",
    // Заведя несколько файлов с переменными окружения можно легко переключаться
    // на отладку в разных окружениях
      "python": "${workspaceFolder}/.venv/bin/python3.10",
      "cwd": "${workspaceFolder}",
      "args": [
    // параметры запуска - специфичны для FastApi
        "app.main:app",
    // в моем случае:
    //   первое app- это пака в корне файла проекта
    //   main - это название файла,
    //   второе app - это имя экземпляра класса FastAPI
    //   (выглядит как app = FastAPI())
        "--host",
        "0.0.0.0"
    // , "--workers", "5" // количество воркеров запускаемых по умолчанию.
    // Нужно для высоконагруженного продакшена
      ],
      "jinja": true,
      "justMyCode": true,
      "presentation": {
        "hidden": false,
        "group": "api",
        "order": 5
      }
    }
    ]
    }

В итоге, через 3 часа мучений все мои проекты были снабжены нужными им параметрами для запуска отладки, сделаны для всех свои виртуальные окружения и вообще наступила благодать. Но ненадолго…

И вот, казалось бы, наступило счастье, благодать, бабочки порхают и в мире больше не осталось проблем… Но радость была не долгой — мне пришлось работать с MSSQL, а с драйвер упорно не хотел становиться ко мне на машину. И тут я понял, что это следующий пинок — разобраться с возможностью разработки в контейнерах.
История с разработкой в контейнерах прямо внутри VS Code витала в моей голове уже очень давно, но как обычно, волшебного пинка не было. И вот он настал…
На самом деле у VS Code есть два режима поддержки контейнеров:


  • полноценная разработка в контейнерах (будет рассматриваться в статье)
  • отладка в контейнерах (мне показалась эта история более громоздкой, поэтому не ковырял)

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


  • В гостевой операционной системе открывается интерфейс.
  • Запускается контейнер, в который устанавливаются расширения и специальный сервер, который позволяет интерфейсной части взаимодействовать с контейнером по сети.
  • В контейнер монтируется выбранная папка, то есть любые изменения файлов внутри контейнера происходят с файлами, лежащими на файловой системе вашей операционной системы.
  • Все процессы, связанные работой с кодом, форматированием и отладкой запускаются внутри контейнера.

Шаги, которые происходят при запуске разработки в контейнере:


  1. Мы выбираем папку, которую хотим открыть в контейнере.
  2. VS Code ищет в корне этой папки специальную директорию .devcontainer.
  3. В этой директории ищется специальный файл — devcontainer.json. Он содержит в себе информацию о том, как запустить нужный контейнер.
  4. В случае, если мы собираем контейнер сами, то запускается процесс сборки с помощью Dockerfile из этой же директории.
  5. В случае, если мы пользуемся уже собранным контейнером из заданного регестри, то скачивается указанный нами образ.
  6. После того, как контейнер запустился, стартует команда, описанная в разделе «initializeCommand» из файла devcontainer.json (если они заданы).
  7. Следующим шагом запускается установка расширений внутрь контейнера. Список расширений указывается в файле devcontainer.json.
  8. После установки расширений стартует команда, описанная в разделе «postCreateCommand» из файла devcontainer.json (если они заданы).

Вот так будет выглядеть наша структура каталогов для разработки в контейнерах:

Development
├───.vscode
│   └───my_dev_env.code-workspace
├───First project
│   ├───!env
│   │   ├───prod.evn
│   │   └───dev.env
│   ├───.devcontainer
│   │   ├───devcontainer.json
│   │   └───Dockerfile
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
├───Second project
│   ├───!env
│   │   ├───prod.evn
│   │   └───dev.env
│   ├───.devcontainer
│   │   ├───devcontainer.json
│   │   └───Dockerfile
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
└───Third project
    ├───!env
    │   ├───prod.evn
    │   └───dev.env
    ├───.devcontainer
    │   ├───devcontainer.json
    │   └───Dockerfile
    ├───.vscode
    │   ├───launch.json
    │   └───settings.json
    └───app
        ├───file111.txt
        ├───file112.txt
        └───...

Рассмотрим более подробно новые файлы.
devcontainer.json:

{
    "name": "docker-my_project",
// Это имя будет показываться в интерфейсе VS Code и обозначать в каком
// контейнере вы работаете
    "build": {
// Эта секция отвечает за то, как будет собираться ваш контейнер.
// Вариантов два - или собирать из Dockerfile при старте, или брать из
// какого-нибудь registry. Я пошел по первому варианту - он для меня проще
        "dockerfile": "Dockerfile",
// Это самый обычный Dockerfile для сборки образа
        "context": ".."
// Это очень важный параметр - он указывает в контексте какой директории
// собирается контейнер и относительно этой директории будут отрабатывать
// все пути в Dockerfile. В примере - это папка проекта First project.
// Соответственно, если у вас в Dockerfile написано "COPY app/requirements.txt ."
// то это значит, что при сборке каталог app будет искаться относительно папки
// First project. Эта возможность позволяет вам очень гибко собирать ваши образы.
    },
    "remoteUser": "root",
// Пользователь из-под кого запускается все в контейнере. Мне было лень
// заморачиваться и я оставил root.
// Есть еще две крайне любопытные команды - они позволяют вписать набор команд,
// выполняемых перед всеми действиями в контейнере (например, установка расширений)
// и сразу же после инициализации контейнера, перед передачей управления пользователю.
// Тут приведен пример, как можно это использовать - ставить зависимости
// или запускать сборки npm.
// "initializeCommand": "cp ../app/requirements.txt .",
// "postCreateCommand": "pip3 install -r /workspaces/alkir-infra-api/app/requirements.txt",
    "extensions": [
// тут мы задаем список расширений VS Code, которые хотим увидеть при разработке в контейнере.
// Тут приведен мой - замените на свой.
        "ms-python.python",
        "wholroyd.jinja",
        "formulahendry.code-runner",
        "streetsidesoftware.code-spell-checker",
        "VisualStudioExptTeam.vscodeintellicode",
        "VisualStudioExptTeam.intellicode-api-usage-examples",
        "humao.rest-client",
        "streetsidesoftware.code-spell-checker-russian",
        "adpyke.vscode-sql-formatter",
        "mtxr.sqltools",
        "ultram4rine.sqltools-clickhouse-driver",
        "DotJoshJohnson.xml",
        "redhat.vscode-yaml",
        "njpwerner.autodocstring"
    ],
    "customizations": {
// В этой секции вы переопределяете настройки по умолчанию.
// Логичнее всего скопировать сюда информацию из общего файла настроек.
        "vscode": {
            "settings": {
                "python.defaultInterpreterPath": "/usr/local/bin/python3.10",
                "python.linting.enabled": true,
                "sql-formatter.uppercase": true,
                "python.linting.flake8Enabled": true
            }
        }
    },
    "forwardPorts": [
// Список портов, которые будут проброшены из контейнера.
// Нужно для того, чтобы обращаться к своему приложению внутри контейнера по сети.
// Так как у меня проект FastAPI он по умолчанию открывает 8000 порт на прослушивание.
        8000
    ]
}

Пример Dockerfile для работы с Python

FROM python:3.10.8-buster as builder

COPY app/requirements.txt .

RUN set -ex \
 && apt-get update -yqq \
 && ACCEPT_EULA=Y apt-get install --no-install-recommends -yqq \
      unixodbc-dev \
      libpq-dev \
      g++ \
      git \
      rsync \
      freetds-dev \
      freetds-bin \
      tdsodbc \
 && pip3 install flake8 pylint autopep8 \
 && pip3 install -r requirements.txt

После того, как мы все настроили остается только запустить это все. Для этого надо нажать F1, и в появившейся строке ввода ввести «Open folder in container». После этого выбрать корневую папку проекта. После чего запустится сборка контейнера и папка откроется внутри контейнера.
И еще один момент. Как правильно, если вы хотите перезапустить контейнер или перестроить его у вас выпадает ошибка. Это, как правило, связано с тем, что контейнер не успевает удалиться. Попробуйте нажать retry и как правильно все срабатывает.

Так же, из неописанных возможностей (пока просто не разобрался), есть возможность стартовать зависимые контейнеры при запуске отладки. К примеру, вы разрабатывается фронт, и у вас в контейнерах стартуют бек с апи и субд для бека. Очень удобная штука.

Тут находится официальная документация — https://code.visualstudio.com/docs/
Открытая спецификация о разработке в контейнерах — https://containers.dev/
Поддерживаемые переменные в файлах настройки — https://code.visualstudio.com/docs/editor/variables-reference
Настройки python — https://code.visualstudio.com/docs/python/settings-reference
Перечень переменных в файле отладки — https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes

© Habrahabr.ru