Skip to content
Back to skills

Docker

DSecurity

Docker для Node-проектов — эталонный multistage Dockerfile (node-slim, npm ci --omit=dev, non-root, HEALTHCHECK), оптимизация слоёв и размера, безопасность (.dockerignore, секреты не в слои), docker-compose для локальной разработки (healthcheck, volumes, env), критичное правило force-recreate vs restart, типовые ошибки (ECONNREFUSED между сервисами). Use when пишешь/ревьюишь Dockerfile или docker-compose, чинишь сборку/поднятие контейнеров или применяешь env-изменения.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 11, 2026
toolsgobashnodedockergit

Works with

  • cli

Security analysis

D52/100
  • mediumUses curl or wget to download content
  • highPerforms destructive filesystem operations
  • criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study

Pro shows the line behind each finding and how to fix it

Scanned September 11, 2026

npx -y skills add Vitammiin/agent-vorcl-flow --skill docker --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docker?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Docker
[![Security: D — Skills Directory](https://www.skillsdirectory.com/api/skills/vitammiin-docker-agent-vorcl-flow/badge)](https://www.skillsdirectory.com/skills/vitammiin-docker-agent-vorcl-flow)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: docker
description: Docker для Node-проектов — эталонный multistage Dockerfile (node-slim, npm ci --omit=dev, non-root, HEALTHCHECK), оптимизация слоёв и размера, безопасность (.dockerignore, секреты не в слои), docker-compose для локальной разработки (healthcheck, volumes, env), критичное правило force-recreate vs restart, типовые ошибки (ECONNREFUSED между сервисами). Use when пишешь/ревьюишь Dockerfile или docker-compose, чинишь сборку/поднятие контейнеров или применяешь env-изменения.
version: 1.0.0
---

# Навык: Docker для Node-проектов

Критерий готовности — не «Dockerfile написан», а **вывод команд**: `docker build` прошёл (размер образа показан), `docker compose ps` — все `healthy`.

## 1. Эталонный multistage Dockerfile (Node)
```dockerfile
# syntax=docker/dockerfile:1
FROM node:22-slim AS deps            # slim, версия пиненная — не latest
WORKDIR /app
COPY package*.json ./                # только манифесты — слой кэшируется,
RUN npm ci                          #   пока не меняются зависимости

FROM deps AS build
COPY . .                             # исходники — после deps: правка кода не сбрасывает кэш npm ci
RUN npm run build

FROM node:22-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev                # в финальном образе — только prod-зависимости
COPY --from=build /app/dist ./dist   # только артефакты, без исходников и devDeps
USER node                            # non-root: встроенный пользователь node
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD node -e "fetch('http://127.0.0.1:3000/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"
CMD ["node", "dist/index.js"]
```

## 2. Оптимизация слоёв и размера
| Приём | Эффект |
|---|---|
| `COPY package*.json` до `COPY . .` | кэш `npm ci` живёт, пока не меняются зависимости |
| `node:XX-slim` вместо полного | ~5x меньше базы; `alpine` — ещё меньше, но musl-риски у нативных модулей |
| `npm ci --omit=dev` в runner | devDeps не попадают в прод-образ |
| Multistage: в runner только артефакты | нет исходников, кэшей сборки, `.git` |
| Один `RUN` на связанные шаги (`apt-get update && install && rm -rf /var/lib/apt/lists/*`) | меньше слоёв, мусор не фиксируется в слое |
| `.dockerignore` | меньше build-контекст → быстрее и чище сборка |

Проверка размера: `docker image ls <tag>` — Node-приложение на slim обычно 150–300 MB; сильно больше — ищи devDeps/исходники в финальном слое (`docker history <tag>`).

## 3. Безопасность
- **Non-root:** `USER node` (или свой uid) в финальном stage; root в контейнере — root на хосте при побеге.
- **Секреты не в слои:** `COPY .env` и `ARG SECRET=...` запрещены — слои неудаляемы и читаются `docker history`. Секреты — runtime-`env` (compose `env_file`, оркестратор) или BuildKit `--mount=type=secret` для build-time.
- **`.dockerignore` — обязательные строки:** `node_modules`, `.git`, `.env*`, `dist`, `*.md`, `.github`, `Dockerfile*`, `docker-compose*`.
- Пин версий образов (`node:22-slim`, `postgres:16`), не `latest` — воспроизводимость и локалка ≈ прод.

## 4. HEALTHCHECK-паттерны
- HTTP-сервис: `node -e "fetch(...)"` (без curl в slim) или поставь `curl` и `CMD curl -f http://127.0.0.1:3000/health || exit 1`.
- В compose у баз: `pg_isready -U $POSTGRES_USER` (postgres), `mongosh --quiet --eval "db.adminCommand('ping')"` (mongo), `redis-cli ping` (redis).
- Приложение стартует после баз: `depends_on: { postgres: { condition: service_healthy } }` — `depends_on` без condition ждёт лишь старта контейнера, не готовности.

## 5. docker compose: env-правило (критично)
```bash
docker compose up -d --force-recreate   # ПОСЛЕ изменения env/.env — пересоздаёт контейнеры с новыми переменными
docker compose restart                  # НЕ перечитывает env — переменные останутся старыми!
```
После поднятия — дождись `healthy` у всех: `docker compose ps` (колонка STATUS); проверь `docker compose logs --tail 50` на `ECONNREFUSED` и циклы перезапуска (`Restarting (1)`). Изменился только код при `build:` — достаточно `docker compose up -d --build`.

## 6. Типовые ошибки
| Симптом | Первопричина |
|---|---|
| `ECONNREFUSED` между сервисами | в строке подключения `localhost` вместо **имени сервиса** compose (`postgres`, `redis`); localhost внутри контейнера — сам контейнер |
| env-переменная «не применилась» | сделан `restart` вместо `up -d --force-recreate` |
| Приложение падает на старте: БД недоступна | нет `depends_on` + `condition: service_healthy`, база ещё не готова |
| «No open ports detected» на хостинге | слушает `127.0.0.1`/хардкод-порт — надо `0.0.0.0:$PORT` |
| Образ раздут / секрет в образе | нет multistage/`.dockerignore`, `COPY . .` в финальный слой; смотри `docker history` |
| Данные БД пропали после `down` | `docker compose down -v` удалил volumes — `-v` только осознанно |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…