A lightweight, secure Deno runtime image built on Alpine Linux with S6 overlay, comprehensive permissions management, and developer-friendly utilities.
This image is available on multiple registries:
tundrasoft/denoghcr.io/tundrasoft/deno# Pull from Docker Hub (recommended)
docker pull tundrasoft/deno:latest
# Pull from GitHub Container Registry
docker pull ghcr.io/tundrasoft/deno:latest
# Run a simple Deno application
docker run -d \
-p 8080:8080 \
-e FILE=https://deno.land/std/examples/chat/server.ts \
-e ALLOW_NET=1 \
--name deno-app \
tundrasoft/deno:latest
# Run with custom timezone and permissions
docker run -d \
-e TZ=Asia/Kolkata \
-e ALLOW_NET=1 \
-e ALLOW_READ=1 \
-v $(pwd):/app \
--name my-deno-app \
tundrasoft/deno:latest
| Version | Tags |
|---|---|
| latest | Latest stable release |
| edge | Edge/development version |
| 2.9 | 2.9.6, 2.9.5, 2.9.4, 2.9.3, 2.9.2, 2.9.1, 2.9.0 |
| 2.8 | 2.8.3, 2.8.2, 2.8.1, 2.8.0 |
| 2.7 | 2.7.14, 2.7.13, 2.7.12, 2.7.11, 2.7.10, 2.7.9, 2.7.8, 2.7.7, 2.7.6, 2.7.5, 2.7.4, 2.7.3, 2.7.2, 2.7.1 |
| 2.6 | 2.6.7, 2.6.6, 2.6.5, 2.6.4, 2.6.3, 2.6.2, 2.6.1, 2.6.0 |
| 2.5 | 2.5.6, 2.5.5, 2.5.4, 2.5.3, 2.5.2, 2.5.1, 2.5.0 |
| 2.4 | 2.4.5, 2.4.4, 2.4.3, 2.4.2, 2.4.1, 2.4.0 |
| 2.3 | 2.3.7, 2.3.6, 2.3.5 |
tundra user (UID/GID: 1000)Use as a base image in your Dockerfile:
# From Docker Hub
FROM tundrasoft/deno:latest
# Your Deno application setup here
COPY . /app
# From GitHub Container Registry
FROM ghcr.io/tundrasoft/deno:latest
# Your Deno application setup here
COPY . /app
For specific versions:
FROM tundrasoft/deno:2.5.6
# or with specific Alpine version
FROM tundrasoft/deno:alpine-3.22-2.5.6
Run a remote script:
docker run -p 8080:8080 \
-e FILE=https://deno.land/std/examples/chat/server.ts \
-e ALLOW_NET=1 \
tundrasoft/deno:latest
Run with Deno tasks:
docker run -v $(pwd):/app \
-e TASK=start \
-e ALLOW_ALL=1 \
tundrasoft/deno:latest
Run with environment variables and permissions:
docker run -d \
-e FILE=/app/server.ts \
-e ALLOW_NET=1 \
-e ALLOW_READ=/app,/etc/config \
-e ALLOW_WRITE=/tmp \
-e PUID=1001 \
-e PGID=1001 \
-e TZ=America/New_York \
-v $(pwd):/app \
tundrasoft/deno:latest
| Variable | Description | Default |
|---|---|---|
DENO_DIR | Directory where cached items are stored | /deno-dir |
TASK | Run a task from deno.json (ignores permission flags) | N/A |
FILE | The file to run with permission flags | N/A |
PUID | User ID for the tundra user | 1000 |
PGID | Group ID for the tundra group | 1000 |
TZ | Timezone (e.g., Asia/Kolkata, America/New_York) | UTC |
DENO_LOG | Deno logging level (e.g., debug, info) | N/A |
DENO_NO_LOCK | Disable lock file generation (1 to disable) | N/A |
DEBUG | Enable debug mode with verbose output (1 to enable) | N/A |
WATCH | Enable watch mode for file changes (1 to enable) | N/A |
S6_CMD_WAIT_FOR_SERVICES_MAXTIME | Max time (ms) to wait for services to start (0 = infinite) | 0 |
S6_KILL_FINISH_MAXTIME | Grace period (ms) for graceful shutdown | 5000 |
These environment variables control Deno's runtime permissions (used only with FILE mode):
| Variable | Description | Default |
|---|---|---|
ALLOW_ALL | Enable all permissions (-A or --allow-all) | N/A |
ALLOW_HRTIME | Allow high-resolution time measurement | N/A |
ALLOW_SYS | Allow system information access | N/A |
ALLOW_ENV | Allow environment variable access | N/A |
ALLOW_NET | Network access (1 for all, or specify domains) | 1 |
ALLOW_READ | File system read access (1 for all, or specify paths) | N/A |
ALLOW_WRITE | File system write access (1 for all, or specify paths) | N/A |
ALLOW_RUN | Command execution (1 for all, or CSV of commands) | N/A |
UNSTABLE | Enable unstable APIs (specific features: ffi,cron,etc) | 0 |
📚 Reference: Deno Permissions Documentation
| Path | Description |
|---|---|
/app | Application root directory (recommended to mount as volume) |
/crons | Directory for cron job files (automatically loaded) |
/deno-dir | Deno cache directory (for persisting dependencies) |
Pre-warm the Deno cache during image build to eliminate cold-start dependency downloads:
Simple file caching:
FROM tundrasoft/deno:latest
COPY . /app
# Pre-warm cache during build
RUN deno cache /app/main.ts
ENV FILE=/app/main.ts
ENV ALLOW_NET=1
With dependencies file:
FROM tundrasoft/deno:latest
COPY deps.ts /app/
COPY main.ts /app/
# Cache all dependencies first (better layer caching)
RUN deno cache /app/deps.ts
# Then cache the main app
RUN deno cache /app/main.ts
ENV FILE=/app/main.ts
ENV ALLOW_NET=1
With deno.json tasks:
FROM tundrasoft/deno:latest
COPY . /app
# Cache dependencies defined in deno.json
RUN deno cache --reload /app/deno.json
ENV TASK=start
ENV ALLOW_ALL=1
Multi-stage optimized build:
FROM tundrasoft/deno:latest AS cache
COPY deno.lock deps.ts /app/
RUN deno cache --reload /app/deps.ts
FROM tundrasoft/deno:latest
# Copy pre-cached dependencies
COPY --from=cache /deno-dir /deno-dir
COPY . /app
RUN deno cache /app/main.ts
ENV FILE=/app/main.ts
ENV ALLOW_NET=1
Development mode combines DEBUG, WATCH, and DENO_LOG for optimal developer experience:
Development setup:
docker run -it \
-e DEBUG=1 \
-e WATCH=1 \
-e DENO_LOG=debug \
-e FILE=/app/main.ts \
-e ALLOW_ALL=1 \
-v $(pwd):/app \
-p 8080:8080 \
tundrasoft/deno:latest
What this enables:
DEBUG=1: Verbose startup output with argument inspectionWATCH=1: File watching with auto-restart on changesDENO_LOG=debug: Detailed Deno runtime loggingWith Deno tasks:
docker run -it \
-e DEBUG=1 \
-e WATCH=1 \
-e TASK=dev \
-v $(pwd):/app \
-p 8080:8080 \
tundrasoft/deno:latest
Lock file disabled (useful for read-only containers):
docker run -d \
-e DENO_NO_LOCK=1 \
-e FILE=/app/server.ts \
-e ALLOW_NET=1 \
-v /app:ro \
tundrasoft/deno:latest
This image uses S6 Overlay for advanced process supervision and service management. S6 is a lightweight init system that provides reliable service supervision, dependency management, and graceful shutdown handling.
The Deno service runs your application via the S6 system, ensuring:
Control S6 service supervision timeouts:
# Custom startup timeout (30 seconds max wait)
docker run -d \
-e S6_CMD_WAIT_FOR_SERVICES_MAXTIME=30000 \
-e FILE=/app/server.ts \
tundrasoft/deno:latest
# Extended graceful shutdown (10 seconds)
docker run -d \
-e S6_KILL_FINISH_MAXTIME=10000 \
-e FILE=/app/server.ts \
tundrasoft/deno:latest
# Infinite startup wait (for slow-starting apps)
docker run -d \
-e S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
-e FILE=/app/server.ts \
tundrasoft/deno:latest
S6 provides dependency management through trigger points:
| Trigger | Description |
|---|---|
os-ready | Container booted, basic setup complete |
config-start | Start configuration changes |
config-ready | Configuration complete |
service-start | Application services begin |
service-ready | All services initialized |
You can extend the Deno image with additional services:
FROM tundrasoft/deno:latest
# Install additional tools
RUN apk add --no-cache redis
# Create Redis service
RUN mkdir -p /etc/s6-overlay/s6-rc.d/redis/dependencies.d
RUN echo "longrun" > /etc/s6-overlay/s6-rc.d/redis/type
RUN cat > /etc/s6-overlay/s6-rc.d/redis/run << 'EOF'
#!/command/with-contenv sh
exec 2>&1
exec redis-server --bind 127.0.0.1
EOF
RUN chmod +x /etc/s6-overlay/s6-rc.d/redis/run
RUN touch /etc/s6-overlay/s6-rc.d/redis/dependencies.d/service-start
RUN touch /etc/s6-overlay/s6-rc.d/user/contents.d/redis
This image provides dynamic cron job loading with environment variable substitution support:
/crons directory$VARIABLE_NAME syntaxFile: /crons/daily-cleanup
# Run cleanup at 3 AM daily
0 3 * * * find /tmp -type f -mtime +7 -delete
Run container:
docker run -d \
-v /host/crons:/crons:ro \
tundrasoft/deno:latest
File: /crons/health-check
# Check application health every 5 minutes
*/5 * * * * curl -f http://localhost:8080/health || exit 1
Run container:
docker run -d \
-p 8080:8080 \
-e FILE=/app/server.ts \
-e ALLOW_NET=1 \
-v /host/crons:/crons:ro \
-v $(pwd):/app \
tundrasoft/deno:latest
File: /crons/maintenance-jobs
# Database backup
$BACKUP_TIME /usr/local/bin/backup.sh >> /var/log/cron-backup.log 2>&1
# Log rotation
$LOG_ROTATE_TIME logrotate /etc/logrotate.conf
# Cleanup caches
$CLEANUP_TIME rm -rf /tmp/deno-cache-*
Run container with environment substitution:
docker run -d \
-e BACKUP_TIME='0 2 * * *' \
-e LOG_ROTATE_TIME='0 0 * * *' \
-e CLEANUP_TIME='0 4 * * 0' \
-v /host/crons:/crons:ro \
tundrasoft/deno:latest
docker build \
--build-arg ALPINE_VERSION=latest \
--build-arg DENO_VERSION=2.5.6 \
-t my-deno-image .
| Argument | Description | Example |
|---|---|---|
ALPINE_VERSION | Alpine Linux version (base image) | latest, 3.22, 3.21 |
DENO_VERSION | Deno runtime version | 2.5.6, 2.4.5, 2.3.7 |
This repository implements comprehensive security scanning:
Deno provides fine-grained permissions for runtime security:
# Minimal permissions (read-only access)
docker run -e FILE=/app/script.ts \
-e ALLOW_READ=/app \
tundrasoft/deno:latest
# Network with specific domain whitelist
docker run -e FILE=/app/fetch.ts \
-e ALLOW_NET=api.example.com,cdn.jsdelivr.net \
tundrasoft/deno:latest
# Restricted execution (no command execution)
docker run -e FILE=/app/processor.ts \
-e ALLOW_READ=/app \
-e ALLOW_WRITE=/tmp \
tundrasoft/deno:latest
For security issues, please use GitHub's private vulnerability reporting.
Container Runtime Security:
# Run with read-only root filesystem
docker run --read-only --tmpfs /tmp --tmpfs /run tundrasoft/deno:latest
# Use specific user and drop capabilities
docker run --user 1000:1000 --cap-drop=ALL tundrasoft/deno:latest
# Limit resources
docker run --memory=512m --cpus=1 --pids-limit=100 tundrasoft/deno:latest
# Restrict network access to specific domains
docker run -e ALLOW_NET=api.example.com,cdn.jsdelivr.net tundrasoft/deno:latest
File System Security:
# Mount application files as read-only
docker run -v $(pwd):/app:ro tundrasoft/deno:latest
# Use specific read/write permissions
docker run -e ALLOW_READ=/app,/etc/ssl -e ALLOW_WRITE=/tmp tundrasoft/deno:latest
# Mount secrets securely
docker run -v /host/secrets:/secrets:ro,Z -e ALLOW_READ=/secrets tundrasoft/deno:latest
Production Deployment:
# Always use specific version tags
docker run tundrasoft/deno:2.1.4 # Not 'latest'
# Use custom networks
docker network create --driver bridge secure-app-net
docker run --network secure-app-net tundrasoft/deno:2.1.4
# Enable logging
docker run --log-driver=json-file --log-opt max-size=10m tundrasoft/deno:2.1.4
For security issues, please use GitHub's private vulnerability reporting.
| Stage | Description | Services |
|---|---|---|
| Boot | Initialize system and user | os-ready → service-ready |
| Config | Load configuration | config-start → config-ready |
| Main | Run application/cron | deno or crond |
| Shutdown | Clean termination | S6 async handlers |
/deno-dir/ - Deno cache directory (mounted volume)
/app/ - Application code
/etc/s6-overlay/ - S6 service definitions
/etc/crontabs/ - Cron jobs (if using cron)
/etc/timezone - TZ configuration
/run/s6/ - S6 runtime (temporary)
version: '3.8'
services:
app:
image: tundrasoft/deno:latest
environment:
- FILE=/app/src/main.ts
- ALLOW_NET=api.example.com
- ALLOW_READ=/app
- ALLOW_WRITE=/tmp
volumes:
- ./src:/app
- deno-cache:/deno-dir
ports:
- "8000:8000"
healthcheck:
test: ["CMD", "/usr/bin/healthcheck.sh"]
interval: 30s
timeout: 10s
retries: 3
volumes:
deno-cache:
Symptoms: Files cannot be read/written, or network calls fail
Solutions:
# Grant read permission to specific path
docker run -e ALLOW_READ=/app \
-e FILE=/app/main.ts tundrasoft/deno:latest
# Grant read + write permissions
docker run -e ALLOW_READ=/app \
-e ALLOW_WRITE=/tmp \
-e FILE=/app/main.ts tundrasoft/deno:latest
# Grant network access to specific domain
docker run -e ALLOW_NET=api.example.com \
-e FILE=/app/main.ts tundrasoft/deno:latest
# Allow all permissions (development only)
docker run -e ALLOW_ALL=1 \
-e FILE=/app/main.ts tundrasoft/deno:latest
Symptoms: Container exits immediately or hangs
Debug steps:
# View logs to see startup errors
docker logs <container-id>
# Run with DEBUG mode for verbose output
docker run -it -e DEBUG=1 -e FILE=/app/main.ts tundrasoft/deno:latest
# Check healthcheck status
docker exec <container-id> /usr/bin/healthcheck.sh
# Verify file exists and is readable
docker exec <container-id> ls -la /app/main.ts
Symptoms: First run takes 30+ seconds to download dependencies
Root causes & solutions:
First-time module download:
# Persist cache using volume
docker run -v deno-cache:/deno-dir \
-e FILE=/app/main.ts tundrasoft/deno:latest
Pre-warm cache during build:
FROM tundrasoft/deno:latest
COPY . /app
RUN deno cache /app/main.ts
ENV FILE=/app/main.ts
Network timeouts:
# Increase S6 startup timeout (default 0 = infinite)
docker run -e S6_CMD_WAIT_FOR_SERVICES_MAXTIME=60000 \
-e FILE=/app/main.ts tundrasoft/deno:latest
Symptoms: "Cannot create lock file" or permission errors in read-only containers
Solution:
# Disable lock file for read-only deployments
docker run --read-only \
-e DENO_NO_LOCK=1 \
-e FILE=/app/main.ts tundrasoft/deno:latest
Symptoms: "Module not found" or "Failed to fetch" errors
Solutions:
# Use persistent cache volume
docker run -v deno-cache:/deno-dir \
-e FILE=/app/main.ts tundrasoft/deno:latest
# Pre-cache dependencies with deno cache
docker run -v deno-cache:/deno-dir \
-w /app \
tundrasoft/deno:latest \
deno cache https://deno.land/[email protected]/mod.ts
Symptoms: File changes don't trigger app restart with WATCH=1
Check:
# Verify watch mode is working
docker run -it -e WATCH=1 -e DEBUG=1 \
-e FILE=/app/main.ts \
-v $(pwd):/app \
tundrasoft/deno:latest
# Look for file change messages in logs
git checkout -b feature/amazing-featuregit commit -m 'Add amazing feature'git push origin feature/amazing-featureSee CHANGELOG.md for release notes and CHANGELOG-GUIDE.md for contribution guidelines.
Built with ❤️ by TundraSoft
Content type
Image
Digest
sha256:e898c1e69…
Size
50.5 MB
Last updated
4 days ago
docker pull tundrasoft/deno