Предполагается, что АПИ у вас уже написано (для C# и python создание образа рассмотрим на следующих занятиях)
Нам нужна не простая рыба, а АПИ работающее с БД (чтобы задействовать контейнер test_mysql из прошлой лекции). Я накидал простенькое АПИ на основе прошлогодней инструкции.
Код лежит в каталоге docker/api. Весь я его здесь описывать не буду, сосредоточусь только на важных моментах:
В файле .sequelizerc не забудьте указать порт, если он не стандартный
module.exports = {
'url': 'mysql://root:toor@127.0.0.1:3308/mydb'
}
Данные в базу накатываем командой npx sequelize-cli db:seed:all
Если всё сделано правильно, то АПИ должен работать и возвращать список жанров:
Так как у нас для разработки и боевого режима одна и та жже база данных, то перед запуском контейнера нужо отменить миграцию командой:
npx sequelize-cli db:seed:undo
При создании образа мы будем копировать в него наш проект, при этом мы должны помнить про безопасность и не хранить в образе пароли, плюс не нужно копировать каталог node_modules, так как в образе проект будет собираться заново.
Для игнорирования файлов нужно добавить в каталог с проектом файл .dockerignore, в который добавить файл .sequelizerc и каталог node_modules (формат у файла такой же как у .gitignore)
.sequelizerc
node_modules
В Dockerfile можно прописать только одну команду (CMD) для запуска приложения, а нам перед запуском нужно запустить миграцию. Для таких случаев в Dockerfile можно прописать не отдельную команду, а скрипт. Для этого служит команда ENTRYPOINT
Создадим в каталоге проекта файл entrypoint.sh:
#!/bin/sh
# накатываем начальные данные
npx sequelize-cli db:seed:all
# запускаем сервер
exec node index.js
Теперь пишем Dockerfile:
# создаем образ на основе Node.js версии 20 на основе минималистичного linux-образа alpine
FROM node:20-alpine
# устанавливаем рабочую директорию
WORKDIR /app
# копируем package.json и package-lock.json
COPY package*.json ./
# устанавливаем зависимости (как раз тут будет заполнен каталог node_modules)
RUN npm install
# копируем остальные файлы проекта
COPY . .
# открываем порт 3000
EXPOSE 3000
# запускаем сервер Express.js - вместо простого запуска будем использовать ENTRYPOINT
# CMD ["node", "index.js"]
# даем права на выполнение скрипту
RUN chmod 777 ./entrypoint.sh
# точка входа
ENTRYPOINT [ "./entrypoint.sh" ]
Собираем образ
docker build -t test-api .
До этого мы про сети не упоминали. Контейнеры, как вы знаете, работают в изолированном окружении, в том числе и в собственной сети, даже если мы явно никакую сеть не указывали.
По-умолчанию используется режим сети bridge, когда для контейнера создается своя сеть (глубоко в тему сетей мы не полезем, упомяну только, что для разработки можно исользовать режим сети host, когда контейнер работает в сети хоста).
Мы можем посмотреть текущий режим сети в Docker Desktop
Нас, естественно, не устраивает, что у каждого контейнера своя сеть. Нам нужно запускать оба наших контейнера в одной сети, чтобы АПИ видело базу.
Для создания сети нужно выполнить команду
docker network create test-network
docker network create: консольная команда для создания сетиtest-network: название создаваемой сетиДля начала этого достаточно. При желании можно указать тип создаваемой сети и её параметры
Апи мы запустим с использованием созданной сети, а как быть с базой?
Можно перезапустить контейнер с указанием сети, а можно подключить уже запущенный контейнер к новой сети командой:
docker network connect test-network test_mysql
Теперь, когда все готово, запускаем контейнер с АПИ
docker run --name test_api --network=test-network -d -p 3000:3000 -e NODE_ENV=production -e DATABASE_URL="mysql://root:toor@test_mysql/mydb" test-api
Тут у нас появились новые опции:
--network=test-network: при запуске контейнера присоединиться к существующей сети-e NODE_ENV=production: переменная среды окружения для Node.js, которая указывает приложению, что используется боевой режим (мы его используем для настройки доступа к базе данных)-e DATABASE_URL="mysql://root:toor@test_mysql/mydb": задаём строку подключения к базе данных. Обратите внимание, в качестве хоста указывается имя контейнера, т.е. нам не надо знать адрес контейнера с базой, в докере имя хоста можно использовать вместо IP-адреса. Ну и смена порта не нужна, так как внутри контейнера используется стандартный порт MySQL (3306)Если все сделали правильно, то контейнер с АПИ запустится, подключится к базе данных по внутренней сети и будет доступен по адресу localhost:3000
Можно посмотреть логи работы в Docker Desktop
В репозитории опубликовать весь проект АПИ (не забываем про .gitignore), в readme.md написать команды для сборки образа и запуска контейнера и скриншот Docker Desktop с запущенным контейнером.