This Docker image is the base image for Coder DDEV workspaces. It provides a complete development environment for DDEV projects with Docker-in-Docker support.
Base System:
- Ubuntu 24.04 LTS
- Essential build tools (gcc, make, git, curl, wget, vim)
- bash-completion for better shell experience
User Configuration:
coderuser (UID 1000, GID 1000)- Passwordless sudo access
- Member of docker group (GID 988)
Docker:
- Docker CE (latest stable)
- Docker Compose
- containerd
- Configured for Sysbox runtime (systemd enabled)
DDEV:
- DDEV (from official apt repository)
- Supports 20+ project types (PHP, Node.js, Python, static sites)
Development Tools:
- Node.js 24.x LTS (via NodeSource)
- npm with global package support
- Python 3 with pip
Path Configuration:
/home/coder/.local/bin- User-local binaries/home/coder/.npm-global/bin- Global npm packages
From the repository root:
# Build image with cache
make build
# Build without cache (clean build)
make build-no-cache
# Push to Docker Hub
make push
# Build and push in one command
make build-and-push
# Test built image
make test
# Show version information
make infoFrom this directory:
# Read version from ../VERSION file
VERSION=$(cat ../VERSION)
# Build image
docker build -t ddev/coder-ddev:$VERSION .
# Tag as latest
docker tag ddev/coder-ddev:$VERSION ddev/coder-ddev:latest
# Test image
docker run --rm ddev/coder-ddev:$VERSION ddev --version
docker run --rm ddev/coder-ddev:$VERSION docker --version
docker run --rm ddev/coder-ddev:$VERSION node --version
# Push to registry
docker push ddev/coder-ddev:$VERSION
docker push ddev/coder-ddev:latestEdit the Dockerfile to add packages:
# Add packages to base layer
RUN apt-get update && apt-get install -y \
your-package-here \
another-package \
&& rm -rf /var/lib/apt/lists/*Update the NodeSource setup in Dockerfile:
# For Node.js 20.x
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
# For Node.js 18.x
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -Add to the npm install layer:
RUN npm install -g \
@fission-ai/openspec \
typescript \
your-package-hereEdit scripts/.ddev/global_config.yaml:
# Example customizations
instrumentation_opt_in: false
internet_detection_timeout_ms: 3000
use_hardened_images: true
use_letsencrypt: false
# ... other settingsThis file is copied to /home/coder/.ddev/global_config.yaml during workspace startup.
The Dockerfile uses a multi-layer strategy for efficient caching:
- Base packages - System tools, build essentials
- User setup - Create coder user, configure sudo
- Scripts - Copy files to
/home/coder-files/(outside volume mount) - Python/Node - Install interpreters and package managers
- Global npm - Install global packages
- Docker - Install Docker daemon, CLI, containerd
- DDEV - Install DDEV from official repository
Layer tips:
- Frequently changing layers should come last
- Group related operations to reduce layer count
- Clean up package manager caches to reduce image size
image/
├── Dockerfile # Image build instructions
├── README.md # This file
└── scripts/ # Files embedded in image
├── .ddev/
│ └── global_config.yaml # DDEV global configuration
└── WELCOME.txt # Workspace welcome message
Important: Files in scripts/ are copied to /home/coder-files/ in the image. The startup script copies them to /home/coder/ during workspace initialization (because /home/coder volume mount hides image contents).
# Test DDEV
docker run --rm ddev/coder-ddev:v0.1 ddev version
# Test Docker CLI
docker run --rm ddev/coder-ddev:v0.1 docker --version
# Test Node.js
docker run --rm ddev/coder-ddev:v0.1 node --version
# Test user configuration
docker run --rm ddev/coder-ddev:v0.1 id
# Should show: uid=1000(coder) gid=1000(coder) groups=1000(coder),988(docker)Requires Sysbox installed on host:
# Run container with Sysbox runtime
docker run --runtime=sysbox-runc -d --name test-ddev \
ddev/coder-ddev:v0.1 sleep infinity
# Exec into container
docker exec -it test-ddev bash
# Inside container, start Docker daemon
sudo dockerd &
sleep 5
# Test Docker inside container
docker ps
docker run hello-world
# Test DDEV
mkdir -p ~/projects/test-site
cd ~/projects/test-site
ddev config --project-type=php --docroot=.
echo "<?php phpinfo();" > index.php
ddev start
curl localhost:80
# Cleanup
exit
docker stop test-ddev
docker rm test-ddevImage versions are managed via the VERSION file in the repository root.
Version scheme:
- v0.x - Beta versions during development
- v1.x - Stable releases
- latest - Always points to most recent build
Releasing a new version:
-
Update
VERSIONfile:echo "v0.7" > ../VERSION
-
Build, push image, and push template (VERSION is synced automatically):
cd .. # Back to repository root make deploy-user-defined-web
Package installation fails:
# Try build without cache
docker build --no-cache -t test-image .Docker daemon won't install:
- Verify base image is Ubuntu 24.04
- Check Docker apt repository is accessible
- Check for systemd configuration issues
DDEV installation fails:
- Verify DDEV apt repository is accessible (pkg.ddev.com)
- Check DDEV version availability
# Check image size
docker images ddev/coder-ddev
# Analyze layers
docker history ddev/coder-ddev:v0.1
# Common causes:
# - Package manager caches not cleaned
# - Unnecessary build dependencies included
# - Large files in COPY commandsOptimization tips:
- Combine RUN commands to reduce layers
- Clean apt cache:
rm -rf /var/lib/apt/lists/* - Use multi-stage builds for build tools
- Minimize COPY operations
Docker daemon won't start in container:
- Ensure host has Sysbox installed
- Check container uses
--runtime=sysbox-runc - Verify systemd is enabled in container
Permission issues:
- Check coder user has UID 1000
- Verify docker group has GID 988
- Confirm coder user is in docker group
- Operations Guide - Template deployment and management
- Troubleshooting Guide - Debugging workspace issues
- Dockerfile Best Practices - Official Docker docs
- Sysbox Documentation - Sysbox runtime details
- DDEV Documentation - DDEV reference