feat: Docker Compose — app, PostgreSQL 17, опциональный Caddy

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
shop
2026-05-17 09:41:03 +03:00
parent 8dae5d37fc
commit a4541cf266
7 changed files with 200 additions and 16 deletions
+12
View File
@@ -0,0 +1,12 @@
node_modules
npm-debug.log
data
.env
.env.*
!.env.example
.git
.gitignore
README.md
*.md
.dockerignore
docker-compose*.yml
+12
View File
@@ -0,0 +1,12 @@
# Скопируйте: cp .env.docker.example .env
# Используется docker compose (переменные подставляются в compose)
POSTGRES_USER=shop
POSTGRES_PASSWORD=shop
POSTGRES_DB=shop
APP_PORT=3000
SESSION_SECRET=change-me-to-a-long-random-string
TRUST_PROXY=0
# С профилем proxy (Caddy): TRUST_PROXY=1
+22
View File
@@ -0,0 +1,22 @@
FROM node:20-alpine
WORKDIR /app
RUN apk add --no-cache tini curl
COPY package.json ./
RUN npm install --omit=dev && npm cache clean --force
COPY src ./src
COPY postgres ./postgres
ENV NODE_ENV=production
ENV HOST=0.0.0.0
ENV PORT=3000
EXPOSE 3000
USER node
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "src/server.js"]
+55 -9
View File
@@ -11,21 +11,64 @@
## Требования
- Node.js 18+
- PostgreSQL 17
- npm
- Node.js 18+ и PostgreSQL 17 — **или** Docker / Docker Compose
---
## PostgreSQL 17
## Docker Compose (рекомендуется для теста)
### Docker (разработка / тест)
Полный стек: **PostgreSQL 17** + **приложение Node.js**.
```bash
docker compose up -d
# БД: postgresql://shop:shop@127.0.0.1:5432/shop
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
@@ -301,7 +344,7 @@ journalctl -u shop -n 50 --no-pager
## Локальная разработка
```bash
docker compose up -d
docker compose -f docker-compose.dev.yml up -d
cp .env.example .env
npm install
npm run dev
@@ -318,9 +361,12 @@ npm run dev
## Структура
```
Dockerfile
docker-compose.yml
docker-compose.dev.yml
postgres/init/01_schema.sql
docker-compose.yml — PostgreSQL 17 локально
caddy/Caddyfile.example
caddy/Caddyfile.docker.example
deploy/shop.service
scripts/
setup-postgres-ubuntu.sh
+19
View File
@@ -0,0 +1,19 @@
# Для docker compose --profile proxy
# Скопируйте и отредактируйте домен перед запуском:
# cp caddy/Caddyfile.docker.example caddy/Caddyfile.docker
# Укажите volume в compose на свой файл
{
email admin@example.com
}
:80 {
encode gzip zstd
reverse_proxy app:3000
}
# С доменом и HTTPS (раскомментируйте, закомментируйте :80):
# shop.example.com {
# encode gzip zstd
# reverse_proxy app:3000
# }
# }
+22
View File
@@ -0,0 +1,22 @@
# Локальная разработка: только PostgreSQL, приложение на хосте (npm run dev)
services:
postgres:
image: postgres:17-alpine
container_name: shop-postgres-dev
ports:
- '5432:5432'
environment:
POSTGRES_USER: shop
POSTGRES_PASSWORD: shop
POSTGRES_DB: shop
volumes:
- shop_pg_dev:/var/lib/postgresql/data
- ./postgres/init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U shop -d shop']
interval: 3s
timeout: 3s
retries: 5
volumes:
shop_pg_dev:
+58 -7
View File
@@ -1,22 +1,73 @@
services:
postgres:
image: postgres:17
image: postgres:17-alpine
container_name: shop-postgres
restart: unless-stopped
environment:
POSTGRES_USER: shop
POSTGRES_PASSWORD: shop
POSTGRES_DB: shop
ports:
- '5432:5432'
POSTGRES_USER: ${POSTGRES_USER:-shop}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-shop}
POSTGRES_DB: ${POSTGRES_DB:-shop}
volumes:
- shop_pg_data:/var/lib/postgresql/data
- ./postgres/init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U shop -d shop']
test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB']
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
networks:
- shop
app:
build: .
container_name: shop-app
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3000
TRUST_PROXY: ${TRUST_PROXY:-0}
SESSION_SECRET: ${SESSION_SECRET:-change-me-in-docker-compose-env}
DATABASE_URL: postgresql://${POSTGRES_USER:-shop}:${POSTGRES_PASSWORD:-shop}@postgres:5432/${POSTGRES_DB:-shop}
ports:
- '${APP_PORT:-3000}:3000'
healthcheck:
test: ['CMD', 'curl', '-f', 'http://127.0.0.1:3000/health']
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
networks:
- shop
caddy:
image: caddy:2-alpine
container_name: shop-caddy
profiles:
- proxy
restart: unless-stopped
depends_on:
app:
condition: service_healthy
ports:
- '80:80'
- '443:443'
volumes:
- ./caddy/Caddyfile.docker.example:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- shop
networks:
shop:
driver: bridge
volumes:
shop_pg_data:
caddy_data:
caddy_config: