
Привет, друзья! Продолжаю делиться с вами заметками о Docker.
Заметки состоят из 4 частей: 2 теоретических и 2 практических. Если быть более конкретным:
- первая часть посвящена
Docker,Docker CLIиDockerfile; - во второй части рассказывается о
Docker Compose.
В этой части мы разработаем простое приложение, состоящее из трех сервисов и базы данных, а в заключительной — "контейнеризуем" его.
Репозиторий с кодом приложения.
Если вам это интересно, прошу под кат.
Подготовка и настройка проекта
Предполагается, что вы хотя бы вкратце ознакомились с содержанием предыдущих частей или изучали другие материалы, посвященные работе с Docker. Впрочем, в этой части Docker будет совсем чуть-чуть.
Также предполагается, что на вашей машине установлен Docker и Node.js.
Хорошо, если на вашей машине установлен Yarn и вы имеете опыт работы с React, Vue, Node.js, PostgreSQL и sh или bash (все это опционально).
Как я сказал, наше приложение будет состоять из трех сервисов:
- клиента на
React.js; - админки на
Vue.js; - сервера (API) на
Node.js.
В качестве базы данных мы будем использовать PostgreSQL, а для взаимодействия с ней — Prisma.
Функционал нашего приложения будет следующим:
- в админке задаются настройки для приветствия, темы и базового размера шрифта;
- эти настройки записываются в БД и применяются на клиенте;
- на клиенте реализована "тудушка";
- задачи записываются в БД;
- все это обслуживается сервером.
Создаем директорию для проекта, переходим в нее и создаем еще парочку директорий:
mkdir docker-test
cd !$ # docker-test
mkdir services sh uploadsВ директории services будут находиться наши сервисы, в директории sh — скрипты для терминала, директорию uploads мы использовать не будем, но обычно в ней хранятся различные файлы, загружаемые админом или пользователями.
Переходим в директорию services, создаем директорию для API, генерируем шаблон клиента с помощью Create React App и шаблон админки с помощью Vue CLI:
cd services
mkdir api
yarn create react-app client
# or
npx create-react-app client
yarn create vue-app admin
# or
npx vue create adminНачнем с API.
API
Переходим в директорию api, инициализируем Node.js-проект и устанавливаем зависимости:
cd api
yarn init -yp
# or
npm init -y
# производственные зависимости
yarn add express cors
# зависимости для разработки
yarn add -D nodemon prisma- express —
Node.js-фреймворкдля разработки веб-серверов; - cors — утилита для работы с CORS;
- nodemon — утилита для запуска сервера для разработки;
- prisma — ядро (core) ORM, которое мы будем использовать для взаимодействия с
postgres.
Инициализируем prisma:
npx prisma initЭто приводит к генерации директории prisma, а также файлов prisma/schema.prisma и .env.
Определяем генератор, источник данных и модели в файле prisma/schema.prisma:
// https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
// это нужно для контейнера
binaryTargets = ["native"]
}
datasource db {
provider = "postgresql"
// путь к БД извлекается из переменной среды окружения `DATABASE_URL`
url = env("DATABASE_URL")
}
// модель для настроек
model Settings {
id Int @id @default(autoincrement())
created_at DateTime @default(now())
updated_at DateTime @updatedAt
greetings String
theme String
base_font_size String
}
// модель для задачи
model Todo {
id Int @id @default(autoincrement())
created_at DateTime @default(now())
updated_at DateTime @updatedAt
text String
done Boolean
}Определяем путь к БД в файле .env:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/mydb?schema=publicЗдесь:
postgres— имя пользователя и пароль;localhost— хост, на котором запущен серверpostgres;5432— порт, на котором запущен серверpostgres;mydb— название БД.
Определяем команду для запуска контейнера postgres в файле sh/db (без расширения):
docker run --rm --name postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=mydb -dp 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgresОбратите внимание: если вы работаете на Mac, вам потребуется предоставить самому себе разрешение на выполнение кода из файла sh/db. Это можно сделать так:
# мы находимся в директории `sh`
chmod +x db
# or
sudo chmod +x dbНаходясь в корневой директории проекта, открываем терминал и выполняем команду:
sh/dbПроисходит загрузка образа postgres из Docker Hub и запуск контейнера под названием postgres.
Обратите внимание: иногда может возникнуть ошибка, связанная с тем, что порт 5432 занят другим процессом. В этом случае необходимо найти PID данного процесса и "убить" его. На Mac это делается так:
# получаем `PID` процесса, запущенного на порту `5432`
sudo lsof -i :5432
# предположим, что `PID` имеет значение `103`
# "убиваем" процесс
sudo kill 103Убедиться в запуске контейнера можно, выполнив команду docker ps:

Или запустив Docker Desktop:

Или в разделе Individual Containers расширения Docker для VSCode:

Выполняем миграцию:
# мы находимся в директории `api`
# migrate dev - миграция для разработки
# --name init - название миграции
npx prisma migrate dev --name initЭто приводит к генерации файла prisma/migrations/[Date]-init/migration.sql, подключению к БД, созданию в ней таблиц, установке и настройке @prisma/client.
Создаем файл prisma/seed.js с кодом для заполнения БД начальными данными:
import Prisma from '@prisma/client'
const { PrismaClient } = Prisma
// инициализируем клиента
const prisma = new PrismaClient()
// начальные настройки
const initialSettings = {
greetings: 'Welcome to Docker Test App',
theme: 'light',
base_font_size: '16px'
}
// начальные задачи
const initialTodos = [
{
text: 'Eat',
done: true
},
{
text: 'Code',
done: true
},
{
text: 'Sleep',
done: false
},
{
text: 'Repeat',
done: false
}
]
async function main() {
try {
// если таблица настроек является пустой
if (!(await prisma.settings.findFirst())) {
await prisma.settings.create({ data: initialSettings })
}
// если таблица задач является пустой
if (!(await (await prisma.todo.findMany()).length)) {
await prisma.todo.createMany({ data: initialTodos })
}
console.log('Database has been successfully seeded 