Deno and Docker
Using Deno with Docker Jump to heading
Deno provides official Docker files and images.
To use the official image, create a Dockerfile
in your project directory:
Dockerfile:
```dockerfile
FROM denoland/deno:latest
# Create working directory
WORKDIR /app
# Copy source
COPY . .
# Compile the main app
RUN deno cache main.ts
# Run the app
CMD ["deno", "run", "--allow-net", "main.ts"]
Best Practices Jump to heading
Use Multi-stage Builds Jump to heading
For smaller production images:
# Build stage
FROM denoland/deno:latest as builder
WORKDIR /app
COPY . .
RUN deno cache main.ts
# Production stage
FROM denoland/deno:latest
WORKDIR /app
COPY --from=builder /app .
CMD ["deno", "run", "--allow-net", "main.ts"]
Permission Flags Jump to heading
Specify required permissions explicitly:
CMD ["deno", "run", "--allow-net=api.example.com", "--allow-read=/data", "main.ts"]
Development Container Jump to heading
For development with hot-reload:
FROM denoland/deno:latest
WORKDIR /app
COPY . .
CMD ["deno", "run", "--watch", "--allow-net", "main.ts"]
Common Issues and Solutions Jump to heading
-
Permission Denied Errors
- Use
--allow-*
flags appropriately - Consider using
deno.json
permissions
- Use
-
Large Image Sizes
- Use multi-stage builds
- Include only necessary files
- Add proper
.dockerignore
-
Cache Invalidation
- Separate dependency caching
- Use proper layer ordering
Example .dockerignore Jump to heading
.git
.gitignore
Dockerfile
README.md
*.log
_build/
node_modules/
Available Docker Tags Jump to heading
Deno provides several official tags:
denoland/deno:latest
- Latest stable releasedenoland/deno:alpine
- Alpine-based smaller imagedenoland/deno:distroless
- Google's distroless-based imagedenoland/deno:ubuntu
- Ubuntu-based imagedenoland/deno:1.x
- Specific version tags
Environment Variables Jump to heading
Common environment variables for Deno in 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
Running Tests in Docker Jump to heading
FROM denoland/deno:latest
WORKDIR /app
COPY . .
# Run tests
CMD ["deno", "test", "--allow-none"]
Using Docker Compose Jump to heading
// filepath: docker-compose.yml
version: "3.8"
services:
deno-app:
build: .
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DENO_ENV=development
command: ["deno", "run", "--watch", "--allow-net", "main.ts"]
Health Checks Jump to heading
HEALTHCHECK --interval=30s --timeout=3s \
CMD deno eval "try { await fetch('http://localhost:8000/health'); } catch { exit(1); }"
Common Development Workflow Jump to heading
For local development:
- Build the image:
docker build -t my-deno-app .
- Run with volume mount:
docker run -it --rm \
-v ${PWD}:/app \
-p 8000:8000 \
my-deno-app
Security Considerations Jump to heading
- Run as non-root user:
# Create deno user
RUN addgroup --system deno && \
adduser --system --ingroup deno deno
# Switch to deno user
USER deno
# Continue with rest of Dockerfile
- Use minimal permissions:
CMD ["deno", "run", "--allow-net=api.example.com", "--allow-read=/app", "main.ts"]
- Consider using
--deny-*
flags for additional security
Working with Workspaces in Docker Jump to heading
When working with Deno workspaces (monorepos) in Docker, there are two main approaches:
1. Full Workspace Containerization Jump to heading
Include the entire workspace when you need all dependencies:
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. Minimal Workspace Containerization Jump to heading
For smaller images, include only required workspace members:
- Create a build context structure:
project-root/
├── docker/
│ └── project-a/
│ ├── Dockerfile
│ ├── .dockerignore
│ └── build-context.sh
├── deno.json
├── project-a/
└── project-b/
- Create a
.dockerignore
:
// filepath: docker/project-a/.dockerignore
*
!deno.json
!project-a/**
!project-b/** # Only if needed
- Create a build context script:
// filepath: docker/project-a/build-context.sh
#!/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
- Create a minimal Dockerfile:
// filepath: docker/project-a/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"]
- Build the container:
cd docker/project-a
./build-context.sh
docker build -t project-a -f Dockerfile tmp-build-context
rm -rf tmp-build-context
Best Practices Jump to heading
- Always include the root
deno.json
file - Maintain the same directory structure as development
- Document workspace dependencies clearly
- Use build scripts to manage context
- Include only required workspace members
- Update
.dockerignore
when dependencies change