Docker: заметки веб-разработчика. Итерация третья

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.


Привет, друзья! Продолжаю делиться с вами заметками о 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 						
Источник: https://habr.com/ru/company/timeweb/blog/650969/


Интересные статьи

Интересные статьи

Хочу поделиться опытом автоматизации экспорта заказов из Aliexpress в несколько CRM. Приведенные примеры написаны на PHP, но библиотеки для работы с Aliexpress есть и для...
Мы снова в эфире и продолжаем цикл заметок Дата Сайентиста и сегодня представляю мой абсолютно субъективный чек-лист по выбору модели машинного обучения. Это топ-10 свойств задач...
В 1С-Битрикс: Управление сайтом (как и в Битрикс24) десятки, если не сотни настраиваемых типов данных (или сущностей): инфоблоки, пользователи, заказы, склады, форумы, блоги и т.д. Стр...
В предыдущих сериях мы взглянули на дробные числа с несколько необычных ракурсов. В этой серии, после введения и некоторой теоретической базы, попробуем собрать всё в удобном виде и получить поль...
Одной из «киллер-фич» 12й версии Битрикса была объявлена возможность отдавать статические файлы из CDN, тем самым увеличивая скорость работы сайта. Попробуем оценить практический выигрыш от использова...