Настройка мультиконтейнерной среды в Visual Studio Code
Представьте, что вы хотите разработать приложение, которое будет состоять из внешнего интерфейса, API и БД. Вы можете сделать это в том же контейнере Docker, но это ограничит вашу будущую возможность масштабирования, т. е. добавление дополнительных API или нескольких серверов БД в случае увеличения нагрузки.
Решением этой проблемы является разработка каждой из этих служб в отдельном контейнере. Visual Studio Code (VS Code) дает нам возможность не только запускать несколько наших сервисов, но также легко подключаться к каждому из них и использовать VS Code как наш инструмент разработки в различных контейнерах.
Давайте посмотрим, как это может быть реализовано. Взяв эту статью за основу, мы можем расширить те же концепции и построить нашу мультиконтейнерную среду.
Предполагая, что наша архитектура состоит из следующих трех сервисов:
- Фронтенд на основе PyWebIO
- Средний уровень, API на основе fastApi
- Бэкэнд, экземпляр Redis
Структура папок в моей папке разработки, названная в данном случае multicontainersetup
, будет выглядеть следующим образом:
C:\DEV\MULTICONTAINERSETUP ├───api ├───frontend └───redis
Чтобы VS Code распознал другую папку как «Remote-Folder», то есть папку, которую следует открыть в контейнере Docker, нам нужно создать папку .devcontainer
в каждой подпапке. Взяв за основу файлы, описанные в ранее упомянутой статье, мы можем затем настроить конфигурацию каждой папки по мере необходимости.
Поскольку интерфейс и API будут разрабатываться на Python, мы можем использовать один и тот же Dockerfile
для них обоих.
Этот Dockerfile необходимо скопировать в папку .devcontainer
папки Frontend
и API
.
Файл devcontainer.json
необходимо изменить, чтобы использовать файл Docker Compose, чтобы VS Code мог одновременно запускать несколько контейнеров Docker. Прежде чем я опишу файлы devcontainer.json
, давайте быстро взглянем на файл docker-compose.yml
.
Файл docker-compose.yml
должен быть помещен в корневую папку нашего проекта, в данном случае multicontainersetup
.
Каждая служба, за исключением службы redis
, о которой я объясню позже, будет следовать одному и тому же шаблону, для frontend
в части службы в файле docker-compose.yml
конфигурация будет выглядеть следующим образом:
frontend: image: frontend tty: true build: context: ./frontend/.devcontainer dockerfile: ./Dockerfile volumes: - .:/workspace:cached depends_on: - api - redisserver ports: - "8000:8000" networks: - myNetwork
Более пристальный взгляд показывает, что мы описываем службу с именем frontend
, первой строкой кода выше, и что она построена на основе Dockerfile
в нашей папке frontend/.devcontainer
:
context: ./frontend/.devcontainer dockerfile: ./Dockerfile
Мы также делаем этот контейнер зависимым от нашей службы api
и службы redisserver
, так что оба контейнера будут запущены, как только мы запустим контейнер frontend
. Я также открываю порт «8000», чтобы я мог получить доступ к frontend
с моего хост-компьютера, как только я его разработаю.
ports: - "8000:8000"
Используя тот же формат, api
service будет выглядеть так:
api: image: api tty: true build: context: ./api/.devcontainer dockerfile: ./Dockerfile volumes: - .:/workspace:cached networks: - myNetwork
Обратите внимание, что я подключил обе службы к сети с именем myNetwork
.
Поскольку я планирую использовать API только в этой сети Docker, я не открываю никаких портов для хост-компьютера.
Часть конфигурации сети в файле docker-compose.yml
выглядит так и будет в самом конце конфигурации.
networks: myNetwork: driver: bridge
Теперь перейдем к redisserver
service, который будет нашим бэкендом. Поскольку мы не планируем вести разработку внутри этого контейнера, мы можем настроить этот контейнер без папки .devcontainer
и файлов Dockerfile
и devcontainer.json
.
Не буду вдаваться в подробности конфигурации для контейнера redis, у меня работает следующая конфигурация :)
redissever: image: redisserver tty: true build: context: ./redis/ dockerfile: ./Dockerfile volumes: - .:/workspace:cached - ./redis/redis-data:/data ports: - "6379:6379" command: # Save if 100 keys are added in every 10 seconds - "--save 10 100" networks: - myNetwork
Это полный файл docker-compose.yml, который я использую.
Файлы devcontainer.json
для двух служб очень похожи, но относятся к их соответствующему образу в файле docker-compose.ym
l.
Следующая часть должна быть настроена для каждого контейнера; это конкретная часть для frontend
service:
"name": "frontend", "dockerComposeFile": "../../docker-compose.yml", "workspaceFolder": "/workspace/frontend", "service": "frontend",
Нам нужно определить имя, файл docker-compose.yml
, который VS Code будет использовать для создания нашей среды, папку, в которой будет храниться наш код workspaceFolder
, и имя службы, на которую мы ссылаемся, в файле Docker Compose.
Два полных файла с конфигурациями для линтера Python:
Чтобы завершить настройку, нам нужно создать файлы requirements.txt
для каждой службы. Один для внешнего интерфейса имеет следующий контент, так как мой внешний интерфейс будет основан на PyWebIO:
pylint pycodestyle black requests pywebio
И контент для службы API будет следующим:
pylint pycodestyle black fastapi uvicorn[standard] redis
API будет создан с использованием fastapi
и uvicorn
будет использоваться для размещения API. Я также устанавливаю модуль redis
Python для доступа к базе данных Redis.
Полная структура папок, включая файлы, должна быть такой
C:\DEV\MULTICONTAINERSETUP │ docker-compose.yml │ ├───api │ └───.devcontainer │ devcontainer.json │ Dockerfile │ requirements.txt │ ├───frontend │ └───.devcontainer │ devcontainer.json │ Dockerfile │ requirements.txt │ └───redis
Используя CTRL+SHIFT+P или F1 для доступа к палитре команд VS Code, мы выбираем следующую команду
Remote-containers: Open Folder in Container
В следующем окне мы выбираем либо папку API, либо папку внешнего интерфейса, и vs code запустит три контейнера, если все прошло нормально, нам будет представлен терминал внутри контейнера, и все три контейнера будут запущены.