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:
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.jsonpermissions 
 - 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 { Deno.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.jsonfile - Maintain the same directory structure as development
 - Document workspace dependencies clearly
 - Use build scripts to manage context
 - Include only required workspace members
 - Update 
.dockerignorewhen dependencies change