Docker — настройка локальной среды разработки JS и Python
Современные системы сложно разрабатывать локально, поскольку они обычно включают в себя различные сервисы. Процесс настройки локальной среды разработки вызвал обеспокоенность у некоторых разработчиков. Одной из основных проблем, с которой сталкиваются разработчики, является проблема «это работает на моем компьютере», которая возникает, когда они разрабатывают приложение, которое хорошо работает на их локальном компьютере, но совсем не работает при его развертывании в других средах. Эти ситуации затрудняют сотрудничество или эффективное развертывание.
Этот пост для вас, если вы столкнулись с вышеуказанной проблемой в процессе разработки. В этом руководстве мы будем использовать Docker для настройки локальной среды разработки. К тому времени, как вы закончите читать этот пост, вы будете знать, как создать и настроить локальную среду разработки для Node.js и Python.
Установите следующее:
- Docker
- docker-compose
- git
- Базовые знания по настройке проекта NodeJS и Python.
Пример архитектурного проекта
Предположим, у нас есть набор сервисов со следующей архитектурой.
Как мы видим из схемы, мы имеем:
Node — служба NodeJS, работающая на порту 5000.
Py — служба Python, работающая на порту 8000.
Настройка
Мы установим базовую настройку служб Python и Node.js, как описано выше. Чтобы продолжить, клонируйте репозиторий, используя следующие команды.
git clone https://github.com/jagkt/local_dev_env.git
cd local_dev_env
Теперь у вас должна быть следующая структура проекта для начала:
.
├── node
│ ├── index.js
│ └── package.json
└── py
│ ├── Dockerfile
│ ├── requirements.txt
│ └── main.py
├── LICENSE
├── Makefile
├── README.md
└── docker-compose.yml
Чтобы развернуть службы, запустите приведенный ниже сценарий из каталога проекта:
make up
make run_con #check the services are up and running
Вы можете получить доступ к приложениям py и node из браузера
py: http://localhost:8000
node: http://localhost:5000
Теперь давайте углубимся в детали настройки проекта.
Создайте образ Docker для среды Python
Здесь мы создадим образ Docker для среды Python с нуля на основе официального образа Python и создадим в нем приложение FastAPI. Сначала давайте создадим требования к пакету.
Создайте каталог с именем «py», внутри него создайте файл require.txt
и скопируйте приведенные ниже зависимости, чтобы запустить в нем приложение FastAPI.
fastapi
uvicorn[standard]
Затем создайте файл main.py
с приведенным ниже кодом приложения FastAPI:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def home():
return {"message": "Hello from py_app!"}
@app.get("/hello/{user}")
async def greetings(user):
return {"Hello": user}
Контейнеризация нашей среды Python
Сначала мы должны создать файл Dockerfile с инструкциями, необходимыми для создания образа, чтобы сгенерировать образ Docker. После этого сборщик Docker обрабатывает Dockerfile и создает образ Docker. Затем запускается служба Python и создается контейнер с помощью простой команды запуска Docker.
Dockerfile
Чтобы запустить наш код Python в контейнере, нужно упаковать его как образ Docker, а затем запустить на его основе контейнер. Этапы описаны ниже.
Теперь в том же каталоге проекта создайте файл Dockerfile
со следующим кодом:
# # Pull the official docker image
FROM python:3.11.1-slim
# # set work directory
WORKDIR /home/py/app
# # set env variables
ENV PYTHONDONTWRITEBYTECODE 1 \
PYTHONUNBUFFERED 1 \
PIP_NO_CACHE_DIR=1
# # install dependencies
COPY ./requirements.txt .
RUN pip install --upgrade -r requirements.txt
# copy project
COPY . /home/py/app
Давайте углубимся в код Dockerfile.
FROM: указывает тонкую версию базового образа Python 3.11 для создания образа Docker.
WORKDIR: эта команда устанавливает активный каталог (/home/py/app), в котором выполняются все следующие команды.
Переменные ENV установлены для оптимизации поведения pip во время установки пакетов (в файле require.txt
) в контейнере Docker.
-- PYTHONUNBUFFERED=1 -- Разрешить немедленное появление операторов и сообщений журнала
-- PIP_DISABLE_PIP_VERSION_CHECK=1 -- отключить проверку версии pip, чтобы уменьшить время выполнения и спам в журналах.
-- PIP_NO_CACHE_DIR=1 – отключение кеша для уменьшения размера образа докера.
COPY: копирует файл requirements.txt
с хоста в WORKDIR контейнера.
RUN: вызывает установку приложений-контейнеров или зависимостей пакетов в файле require.txt
.
COPY: копирует исходные коды приложения с хоста в WORKDIR
.
Теперь давайте создадим образ контейнера, запустим контейнер и протестируем приложение Python.
Чтобы создать образ контейнера, перейдите в каталог py и выполните следующую команду:
docker build -t python-application:0.1.0 .
Проверьте свое изображение
docker image ls
Затем приступаем к созданию контейнера. Чтобы получить доступ к вашему приложению с вашего хост-компьютера, вам необходимо выполнить «переадресацию портов» для перенаправления или прокси-трафика с определенного порта на хост-компьютере на порт внутри вашего контейнера.
docker run -p 4000:4000 python-application:0.1.0
Проверьте свой контейнер
docker container ls
Наконец, получите доступ к своему приложению, запустив команду Curl, протестировав его в браузере или запустив Postman
.
curl http://127.0.0.1:4000
curl http://127.0.0.1:4000/hello/James
Создайте среду узла
Сначала создайте новый каталог с именем node в каталоге local_dev_env
и создайте в нем файл index.js
с приведенным ниже кодом.
const express = require("express");
const app = express();
const PORT = process.env.PORT || 5000;
app.get("/", (req, res) => {
res.send("Hello from node_app");
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Кроме того, создайте новый файл package.json
с приведенным ниже кодом в каталоге узла.
{
"name": "node",
"version": "1.0.0",
"description": "A sample nodejs application",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "admin@admin.com",
"license": "MIT",
"engines": {
"node": ">=10.1.0"
},
"dependencies": {
"express": "^4.18.2"
}
}
Теперь, когда у нас есть базовый сценарий для запуска приложения Node, мы создадим базовый образ. На этот раз мы не будем использовать Dockerfile, как раньше со средой Python, а будем извлекать данные непосредственно из реестра Docker Hub.
Поскольку у нас есть многоконтейнерные сервисы, лучше всего организовывать наши сервисы из одного файла, а не создавать сервисы индивидуально из файла Dockerfile, что может оказаться сложной задачей, если нам нужно создать множество сервисов. Поэтому развертывание наших Node-контейнеров с помощью Docker Compose может быть очень удобным в таких ситуациях. Обратите внимание, что Docker Compose не заменяет Dockerfile. Скорее, последнее является частью процесса создания образов Docker, которые являются частью контейнеров.
Docker Compose позволяет нам использовать приложение Node вместе с другими сервисами (при условии, что у нас есть много сервисов, которые нам нужно развернуть). В нашем случае это будет рядом с нашим сервисом py.
Docker Compose
В каталоге «local_dev_env
» создайте файл «docker-compose.yml
» с приведенным ниже кодом:
version: '3'
services:
py_app:
build: ./py
container_name: py
command: uvicorn main:app --host 0.0.0.0 --reload
environment:
- FastAPI_ENV=development
- PORT=8000
ports:
- '8000:8000'
volumes:
- ./py:/home/py/app
node_app:
image: node:12.3-alpine
container_name: node
user: "node"
environment:
- NODE_ENV=development
- PORT=5000
command: sh -c "npm install && npm start"
ports:
- '5000:5000'
working_dir: /home/node/app
volumes:
- ./node:/home/node/app:cached
Как видно из файла компоновки, были определены две службы: py и node.
В нашем Dockerfile вы увидите некоторые параметры, которые мы не указали ранее. Например, служба py использует образ, созданный из Dockerfile в каталоге py, который мы создали выше, с помощью ключа сборки. ему присваивается имя контейнера «py» с ключом имя_контейнера, и при запуске он запускает веб-сервер FastAPI с ключом команды (uvicorn main:app --host 0.0.0.0 --reload)
.
Ключ томов монтирует каталог py в каталоге проекта (./py
) на хосте в каталог (/home/py/app) внутри контейнера, что позволяет вам изменять код на лету без необходимости пересборки образа. Ключ среды устанавливает переменные среды FastAPI_ENV и PORT
, которые указывают FastAPI работать в режиме разработки и прослушивать PORT 8000
.
Затем он привязывает контейнер и хост-компьютер к открытому порту 8000 с помощью ключа порта. В этом примере службы используется порт по умолчанию для веб-сервера FastAPI — 8000.
Подобно объявлению службы py, служба узлов использует большинство объявленных ключей, но вместо создания своего образа из файла Dockerfile она использует общедоступный образ узла 12.3 alpine
, полученный из реестра Docker Hub с ключом изображения. Пользовательский ключ позволяет запускать контейнер от имени непривилегированного пользователя. Это соответствует принципу наименьших привилегий. Ключwork_dir используется для установки рабочего каталога в контейнере /home/node/app
.
Теперь давайте создадим и запустим наши сервисы.
Чтобы запустить контейнеры сервисов (py и node), создайте приложение с помощью файла Compose
из каталога вашего проекта и запустите его.
docker-compose up -d
Чтобы убедиться, что образы всех служб созданы, выполните следующую команду. Образы py и node должны быть возвращены в CLI.
docker image ls
Чтобы убедиться, что все службы работают, выполните следующую команду. Это отобразит все существующие контейнеры в CLI.
docker container ls --all
Давайте попробуем еще одну вещь: выполним команду bash
из контейнера py
, чтобы просмотреть содержимое каталога (/home/py/app)
.
docker exec -it py bash
ls -l #list the directory in the py container
Makefile
Здесь мы сделали дополнительный шаг и создали Makefile
, который упрощает работу с инструментами, позволяя нам использовать ярлыки, а не вводить длинные команды. Команда может быть определена в Makefile
и использована с использованием синтаксиса команды make
.
Мы можем запускать все контейнеры, выполнять команды внутри контейнера, проверять журналы и замедлять работу контейнеров, как показано ниже.
make up
make py # execute shell script from our py container
make py_log #ouput logs from py container
make node_log #ouput logs from node container
make down #spin down our services including network created
Заключение
Надеюсь, теперь у вас есть четкое представление о том, как настроить локальную среду разработки из этого руководства. Подводя итоги, мы заметили следующее:
- Создание образов для Docker и запуск контейнера из Dockerfile.
- Разверните несколько контейнеров Docker с помощью docker-compose.
- Использование Makefile для упрощения выполнения сложных команд