Опыт использования VSCode Remote-Containers

Alexandr Vishniakov
Mad Devs — блог об IT
8 min readJun 14, 2019

Не так давно, в VSCode-insiders (для разработчиков или любителей получать и тестить все новое) билде появилось расширение Remote Development, которое включает в себя удобную разработку в докере, по SSH, WSL. И относительно недавно это расширение стало доступно в VSCode без приставки insiders.

Remote — SSH — Работайте с исходным кодом в любом месте, открывая папки на удаленной машине / ВМ с использованием SSH. Поддерживает подключение к x86_64 Linux SSH серверам сейчас, и все больше платформ находятся на подходе.

Remote — Containers — Работайте с изолированной цепочкой инструментов или приложением на основе контейнера, открывая любую папку внутри (или вмонтированную) в контейнер.

Remote — WSL — Получите опыт разработки на базе Linux, не выходя из Windows, открыв любую папку в подсистеме Windows для Linux.

Но речь в этой статье пойдет о Remote — Containers. Я опробовал это расширение на практике (пока оно было доступно в VSCode-insiders) и очень остался доволен.

Преимущества разработки с использованием Remote — Containers

  1. Вы и ваша команда перестают мучаться и адаптировать различные скрипты поднятия проекта, для разных операционных систем.
  2. У вас и вашей команды теперь отныне одна и единственная среда разработки в докере.
  3. Все необходимые переменные окружения, вы можете уже сразу указать в Dockerfile или docker-compose.yml
  4. А еще в довесок поднять дополнительные контейнеры сервисов, которые необходимы для разработки (будь то redis, mysql или nginx, или еще какой сервис, все зависит от вашей фантазии)
  5. “Все это очень похоже на простое поднятие окружения из dev контейнеров или dev docker-compose.yml” — но это не совсем так и какие же отличия есть, пойдет сказ ниже.

Чем отличается Remote-Containers от обычного docker-compose up

0. Вы не можете проигнорить девелоперовский контейнер, вы просто не сможете разрабатывать. Это останавливающая сила, для тех, кто привык “разворачивать систему локально” игнорируя дев докеры.

  1. У вас есть один главный контейнер, в котором вы разрабатываете и при этом нет команд для запуска какого либо сервиса внутри, лишь команда, что поддерживает контейнер открытым (к примеру, sleep infinity). это ваше рабочее окружение и внутрь контейнера, добавлена папка, с вашим проектом, так что все изменения, внесенные локально или в докере — синхронизируются (собственно используются VOLUME настройки в докере, но уже автоматически).
  2. Для того, чтобы протестировать ваш сервис, вам самим нужно будет запустить его (или несколько сервисов, в разных терминалах в VSCode), как вы это делаете локально, но намного проще! Этот подход позволяет экспериментировать и не переживать по поводу изменения команды запуска, прописанную в конфигурации.
  3. Терминал VSCode, после запуска в режиме “Reopen in Container”,
Вот такое окно, будет отображено, если ваш проект содержит папку .devcontainer

будет смотреть внутрь контейнера, доступа к локальному терминалу в VSCode (в вашей ОС), у вас не будет. Так что, сколько бы вы ни запустили терминалов, внутри VSCode, все они будут запускаться удаленно — т.е. в контейнере. Таким образом, вы ничего не натворите плохого локально, ваша система не будет замусорена.

4. При этом, у вас есть возможность автоматически запустить сервисы Redis, Mysql или PostgreSQL и это сделает VSCode в содружестве с Docker Desktop или просто Docker демоном вашей ОС.

5. Git как VCS прокидывается автоматически в контейнер и коммитить, пушить или обновляться, из репозитория, не составит труда.

6. Создается рабочая папка с проектом и именно эта папка будет рутовой в терминале VSCode.

7. Гибкая настройка команд, выполняемых после старта контейнера.

8. Все это возможно благодаря автоматическому деплою vscode-server внутрь контейнера.

9. Настройка расширений, которые нужно поставить в докер.

Как начать разработку с использованием Remote-Containers?

1. Для начала нужно создать папку с проектом

2. Установить расширение Remote Development от Microsoft

3. Нажать на (Ctrl) Command + Shift + P для вызова меню команд VSCode

4. Набрать текст Remote-Containers: для того, чтобы отфильтровать все доступные команды.

4. Выбрать пункт Remote-Containers: Create Container Configuration File

5. Появится следующий список c уже готовыми конфигурациями:

Вот такой список появится после выбора пункта Remote-Containers: Create Container Configuration File

6. Если вы разрабатываете на python, то набрав слово python, вы увидите список готовых конфигураций:

Готовые конфигурации для Python

Как видите, тут есть возможность создания как расширенной настройки с двумя сервисами Python 3 & PostgreSQL, так и простой конфигурации с Python 2 или Python 3 на борту. Точно также и с node.js и любой другой платформой или языком программирования.

Готовые конфигурации для Node.js

7. Если в списке, не нашлось подходящего для вас, не беда, можно самому подкорректировать базовую конфигурацию для себя

Базова конфигурация с Debian и git на борту

8. Далее в зависимости от того, какую конфигурацию вы выбрали, у вас будет одна из ниже перечисленных картин в дереве исходного кода в VSCode.

Это конфигурация с Python 3 + percona-server

Или же

Конфигурация с одним сервисом

Как видно из изображений выше, если появляются два сервиса, то создается docker-compose.yml. Если всего один сервис, то будет создан Dockerfile.

9. Далее VSCode предложит запустить ваш проект в контейнере, следующим всплывающим окном

Нажав на “Reopen in Container” вы запустите процесс создания окружения в докере.

Или же, если по каким-либо причинам, вы закрыли окно, то не стоит переживать, можно воспользоваться комбинацией клавиш (Ctrl для Windows и Linux) Command + Shift + P и набрав Remote-Containers: Reopen Folder in Container…

Вы запустите аналогичный процесс.

Совет! Вы можете быстрее открыть только нужные пункты меню для Remote-Containers, нажав на зеленую кнопку с “><“, в левом нижнем углу VSCode.

10. Далее вы можете наблюдать за процессом поднятия окружения и как только все будет готово, терминал в VSCode будет присоединен к контейнеру.

Как только процесс скачивания образов и деплоя сервера VSCode в докер, будет закончен, у вас появится следующая картина.

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

Содержимое папки .devcontainer

Давайте обратим свой взор внутрь этой папки, в которой сосредоточены настройки для Remote-Containers.

devcontainer.json

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

Это контейнер для нескольких сервисов, Python + Percona и еще один сервис
А вот это уже файл для одного контейнера

В случае с несколькими сервисами, основное внимание стоит уделить свойствам:

  • service —название основного сервиса в docker-compose.yml. Что будет указано, туда и будет подключена VSCode.
  • extensions — тоже, что и для одиночного контейнера (описание ниже)
  • shutdownAction — очень важный пункт. В данном случае указана команда stopCompose — что эквивалентно команде docker-compose down, когда вы закрываете VSCode или выбираете команду Remote-Containers: Reopen Folder Locally
Выход из среды контейнера при помощи команды Remote-Containers: Reopen Folder Locally
  • postCreateCommand — тоже, что и для одиночного контейнера (описание ниже)

В случае с одним сервисом, внимание стоит уделить свойствам:

  • appPort — позволит прокинуть порт из докер контейнера VSCode в вашу ОС (разумеется на этом порту вы получите отклик если вручную запустите сервис в терминале VSCode)
  • extensions — очень важный параметр, так как расширения установленные локально, в VSCode не будут автоматом поставлены в докер вместе с серверной частью VSCode. Названия расширений отображаются при клике на расширении в меню расширений VSCode. Именно это название стоит копировать и вставлять в список расширений, необходимых для разработки. Очень удобно! Другому разарботчику, не нужно думать или знать, какие расширения нужно поставить, чтобы комфортно разрабатывать.
  • postCreateCommand — эта команда важна для запуска действий после создания контейнера, к примеру установки зависимостей (что часто забывают делать разработчики) перед стартом разработки. Или установки каких либо специфических библиотек.

Вот пример, с указанным портом для проброса в локальную ОС и списком необходимых расширений для VSCode

Dockerfile (в случае единственного контейнера)

Это стандартный докер, только без CMD или ENTRYPOINT команд в конце. Все что нужно сделает VSCode.

В нем производится установка необходимых зависимостей, установка глобальных пакетов (часто это подводный камень для команды разработчиков, часто бывает что ни в README ни в другом источнике, не указываются эти важные пакеты. В package.json их не добавить, увы).

Конечно, можно и так:

"scripts": {
"preinstall": "npm i -g name_of_global_module"
}

но все же это не так очевидно.

Вот тут https://github.com/npm/npm/issues/2949 народу просто очевидно сказали — “добро пожаловать в эру докера”, мол незачем вам впихивать в package.json то, что выходит за его границы ответственности. В принципе с этим я тоже согласен.

docker-compose.yml (в случае конфигурации с несколькими контейнерами)

Тут, как говорится, можно разойтись с душой, на что гораздо ваше воображение.

Вот пример моего композа, подправленного после создания шаблонной конфигурации, в результате разработки.

Посмотрите как удобно работать другому разработчику, ведь все необходимые переменные окружения настроены уже нужным для разработки образом. Не нужно где то описывать что и откуда нужно взять. Поднимается рабочее окружение посредством VSCode и вы уже сразу готовы писать код и тестить его вручную (или если напишите тесты, то и тестить при помощи запуска тестов).

Рядом с docker-compose.yml можно добавлять свои Doсkerfile, как в данном случае сделал я, добавив контейнер с фейковым slack сервисом.

Ну и конечно же мокая внешние зависимости, вы можете сделать интеграционное и e2e тестирование, для ваших продуктов, намного проще. И мелькание реальных настроек в исходном коде для разработчки, уходит в небытие, так как нечего теперь скрывать и прятать.

Пример докер файла для Python проекта с несколькими сервисами:

В папке также может присутствовать файл requirements.txt.temp или package.json.tmp. Но эти файлы нужны для того, чтобы если в проекте в друг по каким то причинам не окажется такового, то контейнер будет все равно запущен. В противном случае, команда COPY бы оборвалась и контейнер бы не поднялся.

Вот эта команда COPY .devcontainer/requirements.txt.temp requirements.txt* /workspace/ работает отлично с requirements.txt.temp, это некий такой хак, если requirements.txt будет отсутствовать, то COPY команда скопирует файл requirements.txt.temp и создание окружения разработчика будет продолжено.

Недостатки

  • Нет функционала удобного копирования файлов из локальной системы в VSCode удаленно, приходится либо производить копирование через локальный терминал, либо пользоваться командами, открытия папки локально. Благо повторное открытие в докере выполняется быстро. Так что пока это не особо надоедает и не так часто это приходится делать.
  • Нет возможности открыть локальный терминал, что будет смотреть в вашу систему, пока вы находитесь в режиме удаленной разработки. А было бы круто, если бы рядом с “+” кнопкой, в окне терминала, была возможность выбрать, какой вид терминала открыть, локальный или удаленный. C другой стороны я понимаю почему так не сделали, во избежание конфуза и проделывания тех действий, что по невнимательности пользователя, могут произвестись на реальной системе. Но тут можно найти компромис, как-то дать понять пользователю, что вот это локальный терминал и в нем ты будешь производить действия в реальной системе.

Эпилог

На этом все! Спасибо за то, что дочитали до конца статьи. Выбор как всегда за вами. И да прибудет с вами сила )))!

--

--

Alexandr Vishniakov
Mad Devs — блог об IT

«Переписывание с нуля гарантирует лишь одно — ноль!» — Мартин Фаулер