Deno и Docker
Docker — распространённый способ упаковывать и доставлять приложение Deno: вы один раз создаёте воспроизводимый образ и запускаете его одинаково везде. Deno публикует официальные базовые образы, поэтому Dockerfile обычно получается коротким. На этой странице рассказывается, как написать такой Dockerfile, уменьшить размер образа с помощью многоэтапных сборок, а также настроить Compose, рабочую область, безопасность и проверки работоспособности для эксплуатации в production.
Использование Deno с Docker
Deno предоставляет официальные файлы Docker и образы.
Чтобы использовать официальный образ, создайте Dockerfile в каталоге проекта:
FROM denoland/deno:latest
WORKDIR /app
# Copy manifests first so the dependency install layer caches across
# source-only edits
COPY deno.json deno.lock package.json* ./
RUN deno ci --prod --skip-types
# Then copy the rest of the source
COPY . .
CMD ["deno", "run", "--allow-net", "main.ts"]
deno ci выполняет воспроизводимую установку из deno.lock. --prod пропускает devDependencies, а --skip-types удаляет пакеты @types/*. Оба способа уменьшают размер итогового образа, не влияя на поведение во время выполнения.
Рекомендации
Используйте многоэтапные сборки
Чтобы уменьшить размер production-образов:
# Build stage
FROM denoland/deno:latest AS builder
# Point Deno's cache at a known location so it can be copied to the next stage
ENV DENO_DIR=/deno-dir
WORKDIR /app
# Copy manifests first so the dependency install layer caches across
# source-only edits
COPY deno.json deno.lock package.json* ./
RUN deno ci --prod --skip-types
# Then copy the rest of the source
COPY . .
# Production stage
FROM denoland/deno:latest
ENV DENO_DIR=/deno-dir
WORKDIR /app
COPY --from=builder /app .
# Copy the populated Deno cache so the runtime stage has the dependencies
COPY --from=builder /deno-dir /deno-dir
CMD ["deno", "run", "--allow-net", "main.ts"]
Если не копировать $DENO_DIR, deno ci записывает данные только в глобальный кэш Deno на этапе сборки. Эти файлы не попадут в COPY --from=builder /app ., поэтому при первом запуске контейнер повторно загрузит зависимости.
Флаги разрешений
Явно указывайте необходимые разрешения:
CMD ["deno", "run", "--allow-net=api.example.com", "--allow-read=/data", "main.ts"]
Контейнер для разработки
Для разработки с горячей перезагрузкой:
FROM denoland/deno:latest
WORKDIR /app
COPY . .
CMD ["deno", "run", "--watch", "--allow-net", "main.ts"]
Распространённые проблемы и решения
-
Ошибки отказа в доступе
- Правильно используйте флаги
--allow-* - Рассмотрите возможность использования разрешений
deno.json
- Правильно используйте флаги
-
Большой размер образов
- Используйте многоэтапные сборки
- Включайте только необходимые файлы
- Добавьте правильный
.dockerignore
-
Инвалидация кэша
- Разделяйте кэширование зависимостей
- Правильно упорядочивайте слои
Пример .dockerignore
.git
.gitignore
Dockerfile
README.md
*.log
_build/
node_modules/
Доступные теги Docker
Deno предоставляет несколько официальных тегов:
-
denoland/deno:latest— последний стабильный выпуск -
denoland/deno:alpine— уменьшенный образ на основе Alpine -
denoland/deno:distroless— образ Google на основе distroless -
denoland/deno:ubuntu— образ на основе Ubuntu -
denoland/deno:2.x— закрепление за конкретной веткой выпусков (укажите нужную версию)
Переменные окружения
Распространённые переменные окружения для Deno в Docker:
ENV DENO_DIR=/deno-dir/
ENV DENO_INSTALL_ROOT=/usr/local
ENV PATH=${DENO_INSTALL_ROOT}/bin:${PATH}
# Optional environment variables
ENV DENO_NO_UPDATE_CHECK=1
ENV DENO_NO_PROMPT=1
Запуск тестов в Docker
FROM denoland/deno:latest
WORKDIR /app
COPY . .
# Run tests
CMD ["deno", "test", "--allow-none"]
Использование Docker Compose
Простой файл Compose для разработки с горячей перезагрузкой:
services:
deno-app:
build: .
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DENO_ENV=development
command: ["deno", "run", "--watch", "--allow-net", "main.ts"]
Более реалистичная конфигурация с базой данных:
services:
app:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgres://deno:${POSTGRES_PASSWORD}@db:5432/app
depends_on:
db:
condition: service_healthy
restart: unless-stopped
command:
[
"deno",
"run",
"--allow-net=db:5432",
"--allow-env=DATABASE_URL",
"main.ts",
]
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: deno
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U deno"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
volumes:
pgdata:
Храните секреты, например POSTGRES_PASSWORD, в файле .env рядом с docker-compose.yml. Compose загрузит его автоматически. Не добавляйте его в систему контроля версий.
Запустите службы с помощью docker compose up или в фоновом режиме с помощью docker compose up -d.
Проверки работоспособности
HEALTHCHECK --interval=30s --timeout=3s \
CMD deno eval "try { await fetch('http://localhost:8000/health'); } catch { Deno.exit(1); }"
Типичный процесс разработки
Для локальной разработки:
- Соберите образ:
docker build -t my-deno-app . - Запустите контейнер с монтированием тома:
docker run -it --rm \
-v ${PWD}:/app \
-p 8000:8000 \
my-deno-app
Вопросы безопасности
- Запускайте от имени пользователя без прав root:
# Create deno user
RUN addgroup --system deno && \
adduser --system --ingroup deno deno
# Switch to deno user
USER deno
# Continue with rest of Dockerfile
- Используйте минимальный набор разрешений:
CMD ["deno", "run", "--allow-net=api.example.com", "--allow-read=/app", "main.ts"]
- Для дополнительной безопасности рассмотрите использование флагов
--deny-*
Работа с рабочими областями в Docker
При работе с рабочими областями Deno (монорепозиториями) в Docker есть два основных подхода:
1. Контейнеризация всей рабочей области
Включите всю рабочую область, если нужны все зависимости:
FROM denoland/deno:latest
WORKDIR /app
# Copy entire workspace
COPY deno.json .
COPY project-a/ ./project-a/
COPY project-b/ ./project-b/
WORKDIR /app/project-a
CMD ["deno", "run", "-A", "mod.ts"]
2. Минимальная контейнеризация рабочей области
Чтобы уменьшить размер образа, включите только необходимые компоненты рабочей области:
- Создайте структуру контекста сборки:
project-root/
├── docker/
│ └── project-a/
│ ├── Dockerfile
│ ├── .dockerignore
│ └── build-context.sh
├── deno.json
├── project-a/
└── project-b/
- Создайте
.dockerignore:
*
!deno.json
!project-a/**
!project-b/** # Only if needed
- Создайте скрипт для контекста сборки:
#!/bin/bash
# Create temporary build context
BUILD_DIR="./tmp-build-context"
mkdir -p $BUILD_DIR
# Copy workspace configuration
cp ../../deno.json $BUILD_DIR/
# Copy main project
cp -r ../../project-a $BUILD_DIR/
# Copy only required dependencies
if grep -q "\"@scope/project-b\"" "../../project-a/mod.ts"; then
cp -r ../../project-b $BUILD_DIR/
fi
- Создайте минимальный Dockerfile:
FROM denoland/deno:latest
WORKDIR /app
# Copy only necessary files
COPY deno.json .
COPY project-a/ ./project-a/
# Copy dependencies only if required
COPY project-b/ ./project-b/
WORKDIR /app/project-a
CMD ["deno", "run", "-A", "mod.ts"]
- Соберите контейнер:
cd docker/project-a
./build-context.sh
docker build -t project-a -f Dockerfile tmp-build-context
rm -rf tmp-build-context
Рекомендации
- Всегда включайте корневой файл
deno.json - Сохраняйте ту же структуру каталогов, что и при разработке
- Чётко документируйте зависимости рабочей области
- Используйте скрипты сборки для управления контекстом
- Включайте только необходимые компоненты рабочей области
- Обновляйте
.dockerignoreпри изменении зависимостей
Последнее обновление:
© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/reference/docker