C'est l'histoire d'un compagnon qui devient un peu trop curieux et qu'il faut enfermer avant qu'il ne fasse des bêtises...
Qui cela ? Claude.
Car quand il ne trouve pas, il cherche encore plus loin. Sur le papier c'est appréciable, mais en pratique ça devient vite une future brèche de confidentialité quand Claude (code) s'exécute sur votre machine de travail et va avoir accès à tout: historique git, clefs SSH, clients, secrets indus, mails...
On en revient aux basiques de l'enfermement: Docker. Car ça va nous permettre d'avoir toutes les fonctions de la machine hôte via le noyau partagé, sans que Claude n'ai accès aux choses vraiment sensibles.
Sur la Debian 13 que j'utilise, l'installation s'est faite avec les informations de la documentation Docker que l'on remet ici brièvement:
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
Puis une fois cela fait, on doit pouvoir installer Docker et confirmer qu'il fonctionne bien avec les commandes suivante:
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl status docker
La dernière étape c'est de rendre Docker utilisable sans être root ; il faut pour cela:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
Pour confirmer que c'est bon, faire docker ps -a sans sudo.
C'est un projet github qui permet d'utiliser Docker pour avoir Claude Code dans un conteneur dédié, isolé des autres et de la machine, n'ayant accès qu'au répertoire du projet (et ses sous répertoires) et accessoirement (et après configuration) à certaines ressources comme des périphériques matériels (/dev/*).
Par ailleurs le tout fonctionne en CLI ; donc utilisable sur des serveurs puissants et lointains !
L'installation se fait avec:
$ npm install -g @devcontainers/cli
$ git clone https://github.com/trailofbits/claude-code-devcontainer ~/.claude-devcontainer
$ cd ~/.claude-devcontainer
$ git describe --tags --always HEAD
40ca54d
$ ~/.claude-devcontainer/install.sh self-install
$ export PATH="$HOME/.local/bin:$PATH"
La commande npm suggérée dans le README.md installe l'outil principal devcontainer dont devc est un wrapper. Donc même si on ne sert pas de l'outil, il le faut quand même.
Si vous êtes dans un répertoire contenant un projet que vous voulez explorer avec Claude Code pour la première fois, alors il faut initialiser le conteneur avec:
$ cd foo-repo
$ devc .
$ devc shell
Si le projet cloné a déjà été initialisé ailleurs et que .devcontainer/ est présent, alors on peut ré-utiliser ce travail et exploiter l'avantage des conteneurs: reproduire un environnement à l'identique sur diverses machines. Pour cela utiliser les commandes:
$ cd foo-repo
$ devc rebuild
$ devc shell
Si après une installation on souhaite modifier le conteneur il faut modifier les fichiers dans .devcontainer/ puis lancer la commande devc rebuild de sorte à parser à nouveau les variables et faire à nouveau les installations. Ces fichiers sont donc à push dans le projet.
On donne ici quelques configurations pratiques et astuces courantes.
Lors des tests les commandes:
export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-foo
devc rebuild
devc shell
Ne permettent pas d'avoir Claude automatiquement connecté au compte lors du démarrage dans le conteneur ; à la place, il faut importer les fichiers depuis l'host où claude est présumé initialisé.
L'on peut utiliser ce script exécuté depuis .devcontainer dans un premier temps (avant création du conteneur), puis dans le conteneur (aller dans .devcontainer). Une fois installé on pourra lancer claude.
#!/bin/bash
d=$( printf '%s\n' "${PWD##*/}" )
if [[ "x$d" != "x.devcontainer" ]]; then
echo "must be run into .devcontainer"
exit 1
fi
if [[ "x$DEVCONTAINER" == "xtrue" ]]; then
echo "Container part"
cp claude.json $HOME/.claude/.claude.json
cp settings.json $HOME/.claude/settings.json
cp credentials.json $HOME/.claude/.credentials.json
chmod 600 $HOME/.claude/.credentials.json
else
echo "Host part"
cp $HOME/.claude.json claude.json
cp $HOME/.claude/settings.json settings.json
cp $HOME/.claude/.credentials.json credentials.json
fi
Dans .devcontainer/devcontainer.json ajouter dans runArgs les éléments suivants pour qu'il ressemble à cela:
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW",
"-p",
"8080:8080"
],
Il faut faire deux modifications:
.devcontainer/Dockerfile modifier ENV SHELL=/bin/bash~/.claude-devcontainer/install.sh modifier cmd_shell() pour lancer bash plutôt que zshOu soit prendre l'habitude d'exécuter devc exec bash plutôt que devc shell
À la fin de .devcontainer/Dockerfile ajouter cette commande:
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path
Depuis le conteneur on peut vouloir flasher des périphérique directement ou permettre à Claude de le faire pour aller plus vite sur les cycles de test and fail ; pour cela modifier .devcontainer/devcontainer.json pour transformer runArgs en:
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW",
"--group-add",
"dialout",
"--device=/dev/ttyUSB0:/dev/ttyUSB0",
"--device=/dev/ttyUSB1:/dev/ttyUSB1",
"--device=/dev/bus/usb"
],
Depuis la suppression de zsh les caractères unicode s'affichent mal dans la session tmux ; il faut donc ajouter dans le Dockerfile juste après les installations de paquet les quelques lignes suivantes:
RUN sudo sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8