Yes - It is possible to use DooD in a devcontainer
When setting up a real-world devcontainer, you often need more than just a simple “hello world” example. In practice, most development environments rely on several running containers at once — databases, caches, and supporting services. For that, it’s often easier to use Docker-out-of-Docker (DooD) so your devcontainer can talk to the host’s Docker daemon directly.
In this post, we’ll set up a devcontainer environment that uses:
• A custom Dockerfile for building the development container.
• docker-compose to orchestrate the environment.
• DooD via the mounted Docker socket, allowing us to run other containers from inside the devcontainer.
This gives you a solid foundation for building a “real-life” dev environment instead of the typical examples that don’t scale.
The file system
.devcontainer
├── devcontainer.json # Main devcontainer config
├── docker-compose.yml # Orchestration file
├── Dockerfile.debian # Custom base image for the devcontainer
└── .env # Environment variables
devcontainer.json
Here we enable the docker-outside-of-docker feature and configure environment variables:
{
"name": "Testcontainers Debian dev-environment",
"dockerComposeFile": "docker-compose.yml",
"service": "dev",
"workspaceFolder": "/workspace",
"remoteUser": "root",
"features": {"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}},
"containerEnv": {
"TZ": "Europe/Copenhagen",
"TESTCONTAINERS_HOST_OVERRIDE": "host.docker.internal"
}
}
docker-compose.yml
The compose file mounts the workspace and the host’s Docker socket:
services:
dev:
build:
context: .
dockerfile: Dockerfile.debian
volumes:
- ..:/workspace:cached
- /var/run/docker.sock:/var/run/docker.sock
networks:
- internal
command: ["sleep", "infinity"]
networks:
internal:
driver: bridge
Dockerfile.debian
We start from a slim .NET SDK base and install the necessary tooling (and some..):
# Use a base Debian image
FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim
# Set noninteractive mode to avoid prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Create docker group and add root to it
RUN groupadd -r docker && usermod -aG docker root
# Install dependencies
# Added ca-certificates as it's often needed for https downloads and the dotnet install script might rely on it
RUN apt-get update && \
apt-get install -y \
git \
dos2unix \
docker.io \ <-- MINIMUM
stow \
zsh \
tree \
clang \
jq \
unzip \
xclip \
wget \
curl \
ca-certificates \
apt-transport-https \
software-properties-common && \
rm -rf /var/lib/apt/lists/*
RUN dotnet tool install Nuke.GlobalTool --global
ENV PATH="$PATH:~/.dotnet/tools"
# Install .NET Runtime using the official script.
# This script handles architecture detection for you.
RUN curl -L https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh && \
chmod +x /tmp/dotnet-install.sh && \
/tmp/dotnet-install.sh --version 9.0.4 --runtime dotnet && \
rm /tmp/dotnet-install.sh
Now run the container and test that you have access to your host's docer environment:
That's it!
You now have a development environment capable using DooD and eg. running devcontainers like a true pro!
Next steps
Add your own services to the docker-compose.yml
and extend the Docker.debian
with your own installs :)