# Shop Интернет-магазин на **Node.js** и **PostgreSQL 17**. ## Возможности - Каталог товаров с категориями и поиском - Корзина и оформление заказа - Регистрация и вход пользователей - История заказов в личном кабинете ## Требования - Node.js 18+ и PostgreSQL 17 — **или** Docker / Docker Compose --- ## Docker Compose (рекомендуется для теста) Полный стек: **PostgreSQL 17** + **приложение Node.js**. ```bash cp .env.docker.example .env # Отредактируйте SESSION_SECRET в .env docker compose up -d --build docker compose ps curl -s http://127.0.0.1:3000/health ``` Сайт: **http://localhost:3000** | Команда | Описание | |---------|----------| | `docker compose up -d --build` | Сборка и запуск | | `docker compose logs -f app` | Логи приложения | | `docker compose down` | Остановка | | `docker compose down -v` | Остановка + удаление БД | ### Caddy в Docker (HTTPS, опционально) ```bash # В .env: TRUST_PROXY=1 # Отредактируйте caddy/Caddyfile.docker.example (домен) docker compose --profile proxy up -d --build ``` Порты: **80**, **443** (Caddy) → `app:3000`. ### Только PostgreSQL (разработка на хосте) ```bash docker compose -f docker-compose.dev.yml up -d cp .env.example .env # DATABASE_URL=postgresql://shop:shop@127.0.0.1:5432/shop npm install && npm run dev ``` ### Файлы | Файл | Назначение | |------|------------| | `Dockerfile` | Образ приложения | | `docker-compose.yml` | app + postgres (+ caddy с профилем `proxy`) | | `docker-compose.dev.yml` | только postgres для `npm run dev` | | `.env.docker.example` | переменные для compose | --- ## PostgreSQL 17 (без Docker) ### Ubuntu (сервер) ```bash apt update apt install -y postgresql-17 postgresql-client-17 systemctl enable postgresql systemctl start postgresql ``` Если пакета `postgresql-17` нет в репозитории Ubuntu, подключите [PGDG](https://www.postgresql.org/download/linux/ubuntu/): ```bash apt install -y curl ca-certificates install -d /usr/share/postgresql-common/pgdg curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(. /etc/os-release && echo ${VERSION_CODENAME}-pgdg) main" > /etc/apt/sources.list.d/pgdg.list' apt update apt install -y postgresql-17 postgresql-client-17 ``` Пользователь и база `shop`: ```bash cd /opt/shop bash scripts/setup-postgres-ubuntu.sh ``` Схема: `postgres/init/01_schema.sql` (применяется при старте приложения). Сессии — таблица `session` в PostgreSQL (создаётся автоматически). --- ## Быстрый развёртывание на Ubuntu ```bash # 1. Система + Node.js 20 apt update apt install -y git curl curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt install -y nodejs # 2. PostgreSQL 17 apt install -y postgresql-17 postgresql-client-17 # 3. Код cd /opt git clone shop cd shop # 4. БД bash scripts/setup-postgres-ubuntu.sh # 5. Окружение cp .env.example .env sed -i "s/change-me-to-a-long-random-string/$(openssl rand -hex 32)/" .env # Проверьте DATABASE_URL в .env # 6. Приложение npm install --omit=dev npm start ``` Проверка: ```bash curl -s http://127.0.0.1:3000/health # {"ok":true,"service":"shop","database":"postgresql"} ``` ### Переменные `.env` ```env PORT=3000 HOST=127.0.0.1 NODE_ENV=production TRUST_PROXY=1 SESSION_SECRET=длинный-секрет DATABASE_URL=postgresql://shop:shop@127.0.0.1:5432/shop ``` | Переменная | Описание | |------------|----------| | `DATABASE_URL` | Строка подключения PostgreSQL | | `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE` | Альтернатива `DATABASE_URL` | | `HOST` | `127.0.0.1` в production (доступ через Caddy) | --- ## Запуск как служба (systemd) ```bash cp /opt/shop/deploy/shop.service /etc/systemd/system/shop.service cd /opt/shop cp .env.example .env # при первой установке # Заполните SESSION_SECRET и DATABASE_URL npm install --omit=dev # Не делайте chown -R www-data на весь /opt/shop (ломает git pull) systemctl daemon-reload systemctl enable shop systemctl start shop journalctl -u shop -f ``` `EnvironmentFile=/opt/shop/.env` должен содержать `DATABASE_URL`. --- ## Проверка после установки ```bash systemctl restart shop sleep 1 curl -s http://127.0.0.1:3000/health ss -tlnp | grep 3000 journalctl -u shop -n 5 --no-pager # Магазин: http://127.0.0.1:3000 (PostgreSQL) ``` --- ## Обновление на сервере (git pull) ```bash cd /opt/shop git config --global --add safe.directory /opt/shop bash scripts/server-update.sh ``` Скрипт: `git pull` → `npm install` → проверка PostgreSQL → `restart shop` → `curl /health` → `reload caddy`. Вручную: ```bash cd /opt/shop git pull npm install --omit=dev systemctl restart shop curl -s http://127.0.0.1:3000/health systemctl reload caddy ``` --- ## Переход с SQLite на PostgreSQL 17 Если сервер уже работал на старой версии (файлы `data/*.db`): ```bash # 1. PostgreSQL apt install -y postgresql-17 postgresql-client-17 systemctl start postgresql # 2. Код cd /opt/shop git config --global --add safe.directory /opt/shop git pull # 3. База shop bash scripts/setup-postgres-ubuntu.sh # 4. .env — обязательно DATABASE_URL cp -n .env.example .env nano .env # DATABASE_URL=postgresql://shop:shop@127.0.0.1:5432/shop # HOST=127.0.0.1 # NODE_ENV=production # TRUST_PROXY=1 # 5. Зависимости и перезапуск npm install --omit=dev systemctl restart shop # 6. Проверка curl -s http://127.0.0.1:3000/health systemctl reload caddy ``` Каталог `data/` больше не используется. Демо-товары появятся при пустой таблице `products`. Аккаунты и заказы из SQLite не переносятся — нужна повторная регистрация или ручной импорт. Проверка PostgreSQL: ```bash psql "postgresql://shop:shop@127.0.0.1:5432/shop" -c '\dt' ``` --- ## Caddy — SSL и reverse proxy **Перед Caddy:** `curl http://127.0.0.1:3000/health` → OK. ```bash apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \ | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \ | tee /etc/apt/sources.list.d/caddy-stable.list apt update && apt install -y caddy cp /opt/shop/caddy/Caddyfile.example /etc/caddy/Caddyfile nano /etc/caddy/Caddyfile # ваш домен и email caddy validate --config /etc/caddy/Caddyfile systemctl enable caddy systemctl reload caddy ``` Пример `Caddyfile`: ```caddyfile { email admin@example.com } shop.example.com { encode gzip zstd reverse_proxy 127.0.0.1:3000 } ``` Порты **80/443** открыть; **5432** и **3000** наружу не публиковать. ### Ошибка `ECONNREFUSED 127.0.0.1:5432` Приложение обновилось на PostgreSQL, а сервер БД не запущен. **Быстрое исправление (одной командой):** ```bash cd /opt/shop git pull bash scripts/fix-db-connection.sh ``` **Вручную:** ```bash apt install -y postgresql-17 postgresql-client-17 systemctl enable --now postgresql pg_isready -h 127.0.0.1 -p 5432 cd /opt/shop bash scripts/setup-postgres-ubuntu.sh nano .env # DATABASE_URL=postgresql://shop:shop@127.0.0.1:5432/shop cp deploy/shop.service /etc/systemd/system/shop.service systemctl daemon-reload systemctl restart shop curl -s http://127.0.0.1:3000/health ``` ### HTTP 502 ```bash bash /opt/shop/scripts/diagnose-502.sh journalctl -u shop -n 50 --no-pager ``` | Причина | Решение | |--------|---------| | `ECONNREFUSED 127.0.0.1:5432` | PostgreSQL не запущен или не установлен — см. ниже | | PostgreSQL не запущен | `systemctl enable --now postgresql` | | Неверный `DATABASE_URL` | проверить `.env`, `psql` | | Node не слушает 3000 | `journalctl -u shop -f` | | Caddy без backend | сначала `curl /health`, потом `reload caddy` | --- ## Локальная разработка ```bash docker compose -f docker-compose.dev.yml up -d cp .env.example .env npm install npm run dev ``` ## Скрипты npm | Команда | Описание | |---------|----------| | `npm start` | Запуск сервера | | `npm run dev` | С автоперезагрузкой | | `npm run seed` | Демо-товары (если каталог пуст) | ## Структура ``` Dockerfile docker-compose.yml docker-compose.dev.yml postgres/init/01_schema.sql caddy/Caddyfile.example caddy/Caddyfile.docker.example deploy/shop.service scripts/ setup-postgres-ubuntu.sh fix-db-connection.sh diagnose-502.sh server-update.sh src/ ``` ## Репозиторий ```bash git clone shop cd shop ```