Comment déployer Code Server avec Docker

Dans ce tutoriel, je vais vous expliquer comment déployer Code Server avec Docker, qui va vous permettre d’accéder à Visual Studio Code (VS Code) depuis un navigateur Internet, ce qui rend disponible votre environnement de développement depuis n’importe quel ordinateur et si vous le publiez sur Internet, vous pourrez même accéder à votre environnement de développement depuis m’importe où.

Code Server est une version cloud de Visual Studio Code accessible via un navigateur web. Il permet de développer à distance en offrant une interface familière, avec support des extensions et du terminal intégré, sans nécessiter d’installation locale. Idéal pour coder depuis n’importe quel appareil tout en centralisant l’environnement de développement sur un serveur.

Code Server – limitation à un seul utilisateur par instance

Code Server, lorsqu’il est déployé via une instance Docker standard, est conçu pour un seul utilisateur à la fois. Cela signifie que chaque conteneur Code Server gère une seule session utilisateur, avec un environnement isolé et sécurisé.

La limitation vient du fait que Code Server ne gère pas nativement plusieurs sessions utilisateurs simultanées dans la même instance. Pour permettre à plusieurs utilisateurs d’accéder à Code Server en même temps, il faut déployer une instance distincte par utilisateur (par exemple, un conteneur Docker par utilisateur) ou utiliser une solution externe de gestion multi-utilisateurs, comme un reverse proxy avec authentification ou des plateformes d’orchestration qui lancent une instance par utilisateur.

En résumé, la limitation « un utilisateur par instance Docker » est liée à la conception de Code Server et à la manière dont la session et les ressources sont isolées, garantissant sécurité et stabilité mais demandant une architecture adaptée pour le multi-utilisateurs.

Par de panic, dans ce tutoriel, je vais vous expliquer comment gérer plusieurs instances Code Server avec N8N pour démarrer des conteneurs Code Server à la demande.

Prérequis pour déployer Code Server avec Docker

Vous aurez besoin :

Si vous souhaitez publier sur Internet ou utiliser une URL pour accéder à code vous aurez besoin :

  • D’un reverse proxy Nginx
  • D’un nom de domaine dédié (vscode.domain.tld)
  • De certbot pour générer une certificat SSL pour utiliser le protocole HTTPS

Déploiement de Code Server avec Docker

Pour commencer, créer un dossier où l’on va stocker, les fichiers nécessaire pour le conteneur ainsi que les dossiers et fichiers que vous allez éditer.

Pour ma part, je vais travailler dans le dossier : /containers/code-server/.

sudo mkdir -p /containers/code-server

Ensuite aller dans le dossier créé (cd) puis créer le fichier docker-compose.yml :

sudo nano docker-compose.yml
---
services:
  code-server:
    image: lscr.io/linuxserver/code-server:latest
    container_name: code-server
    env_file: "codeserver.env"
    volumes:
      - ./code-server/config:/config
    ports:
      - 8443:8443
    restart: unless-stopped

Si nécessaire changer le port publier sur l’hôte Docker

Ensuite créer le fichier codeserver.env qui va contenir les variables d’environnement qui va permettre la configuration de Code Server.

sudo nano codeserver.env
PUID=1000
PGID=1000
TZ=Etc/Paris
PASSWORD=ChangeMe 
PROXY_DOMAIN=vscode.domain.tld #optional

Là aussi, adapter les variables à votre environnement, il est impératif de changer le mot de passe, si vous ne souhaitez pas utiliser d’URL avec un enregistrement DNS personnalisé, commenter la dernière ligne (PROXY_DOMAIN).

Télécharger l’image du conteneur :

sudo docker compose pull

Démarrer le conteneur :

sudo docker compose up -d

Le conteneur Code Server est prêt à être utilisé.

Virtualhost Nginx pour Code Server

Si vous prévoyez l’utilisation d’une URL et donc d’un enregistrement DNS et d’utiliser Nginx comme Reverse proxy, voici un exemple de virtualhost utilisant le port 80.

server{
	listen 80;
	server_name: codeserver.domaine.tld;
	
	location /{
		proxy_pass A.B.C.B:8443;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Host $http_host;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection $http_connection;
		proxy_http_version 1.1;
	}
}

Adapter le fichier du virtualhost à votre configuration.

Accéder à Code Server

Lancer un navigateur Internet, puis aller sur l’IP:PORT du serveur Docker ou utiliser le DNS configuré.

On arrive sur la page de connexion, où, il faut renseigner le mot de passe 1 qui a été mis dans le fichier codeserver.env, puis cliquer sur SUBMIT 2.

Pour utiliser pleinement Code Server, on va faire confiance au fichier qui se trouve dans notre espace de travail (workspace), cliquer sur le bouton Yes, I trust authors 1.

On arrive sur interface qui est celle de VSCode comment on peut l’avoir sur Windows.

Comment vous pouvez le voir j’ai créé un dossier et un fichier (docker-compose.yaml), le but ici est de vous montrer où sont stockés les fichiers et dossiers qui sont utilisés dans Code Server.

Si on regarde avec le Terminal qui est dans vscode, on peut voir que les éléments sont dans le dossier workspace.

Depuis l’hôte Docker, dans le dossier ./config qui se trouve au même niveau que le fichier docker-compose.yml, on va retrouver les fichiers et dossiers qui sont créé depuis Code Server.

Vous savez maintenant comment déployer Code Server avec Docker.

Code Server multi-utilisateur avec N8N

Pour continuer ce tutoriel, on va voir comment rendre « muilti-utilisateur » Code Server en utilisant N8N.

Comment vous avez pu le voir, chaque conteneur code server dispose de son propre mot de passe et d’un espace où les fichiers et dossiers, si on partage cette espace, cela veut dire que tous les utilisateurs vont avoir accès aux fichiers et dossiers et le même mot de passe, ce qui est terme de sécurité et confidentialité n’est pas top.

On pourrait très bien lancer autant de Code Server que d’utilisateur qui pourrait en avoir besoin le problème de cette solution va être la consommation de ressource CPU / RAM importante pour des environnements qui ne seront peut être pas utilisés.

Le but va être de lancer les conteneurs Code Server à la demande quand un utilisateur en a besoin, pour cela, on va utiliser N8N.

Comment ça va se passer :

  • L’utilisateur par un formulaire va être son adresse e-mail
  • Envoie d’une commande SSH qui va exécuter un script pour, créer le conteneur, envoyer le mot de passe par e-mail à l’utilisateur et configurer le virtualhost Nginx

Je ne vais pas rentrer dans le détail de chaque étape, je vais vous expliquer les grandes étapes.

Avant de commencer, vous aurez besoin d’avoir un DNS dédié à la publication des Codes server et Nginx d’installé sur l’hôte Docker. Vous devez également créer un « Credential » dans N8N pour la connexion au serveur Docker qui va lancer les conteneurs Code Server.

Configuration du Workflow dans N8N

Commencer par créer un projet.

Créer la première étape, qui est un formulaire qui va demandé l’adresse e-mail de l’utilisateur.

Le seconde étape va être une connexion SSH au serveur Docker qui va faire fonctionner les conteneurs Code serveur, à cette étape, on va exécuté un script bash qui va prendre comme paramètre l’adresse e-mail.

Voici la commande executée :

bash /scripts/code-server-generate.sh {{ $item("0").$node["On form submission"].json["Email"] }}

Le Workflow est terminé.

Configuration du serveur Docker pour Code Server

Pour commencer installer et configurer msmtp qui va nous permettre d’envoyer les messages :

apt install msmtp -y

Editer le fichier de configuration :

sudo nano /etc/msmtprc

Voici un exemple de configuration pour un serveur SMTP sur le port 25 sans authentification.

# Configuration simple pour un serveur SMTP sans authentification
account default
host smtp.domain.tld
port 25
from [email protected]
tls off
auth off

Créer un dossier script à la racine /

mkdir /scripts

Dans ce dossier créer le fichier : code-server-generate.sh.

sudo nano code-server-generate.sh

Voici le script :

#!/bin/bash

USER_EMAIL=$1
USER_ID=$(echo $USER_EMAIL | sed 's/[@.]/-/g')  # Transformer email en ID

# Liste des domaines autorisés (laisser vide pour ne pas limiter)
ALLOWED_DOMAINS=("domain.tld")

# Extraire le domaine de l'email
USER_DOMAIN=$(echo $USER_EMAIL | awk -F '@' '{print $2}')

# Vérifier si le domaine est autorisé
if [[ ${#ALLOWED_DOMAINS[@]} -ne 0 ]]; then
    DOMAIN_ALLOWED=false
    for domain in "${ALLOWED_DOMAINS[@]}"; do
        if [[ "$USER_DOMAIN" == "$domain" ]]; then
            DOMAIN_ALLOWED=true
            break
        fi
    done

    if [[ "$DOMAIN_ALLOWED" == "false" ]]; then
        echo "Erreur : Le domaine $USER_DOMAIN n'est pas autorisé."
        exit 1
    fi
fi

# Trouver un port disponible
while : ; do
    PORT=$(( RANDOM % 1000 + 8000 ))
    ss -tuln | grep -q ":$PORT " || break
done

# Arrete et supprime conteneur si present
docker stop code-$USER_ID
docker rm code-$USER_ID
rm /var/lib/code-server/$USER_ID.passwd
rm /etc/nginx/code-server-users/$USER_ID.conf
nginx -t
systemctl reload nginx


# Générer un mot de passe aléatoire
PASSWORD=$(openssl rand -base64 12)

# Démarrer le conteneur Code Server
docker run -d --name code-$USER_ID -p $PORT:8443 \
  -e PASSWORD="$PASSWORD" \
  -e PROXY_DOMAIN=codes.domain.tld \
  -e TZ=Europe/Paris \
  -v /code-server-data/$USER_ID/config:/config \
  lscr.io/linuxserver/code-server

# Vérifier que le conteneur démarre correctement
for i in {1..10}; do  
    if docker ps | grep -q "code-$USER_ID"; then
        echo "Le conteneur code-$USER_ID est démarré !"
        break
    fi
    sleep 1
done

if ! docker ps | grep -q "code-$USER_ID"; then
    echo "Erreur : Le conteneur ne s'est pas lancé correctement."
    exit 1
fi

# Stocker le mot de passe
echo "$PASSWORD" > "/var/lib/code-server/$USER_ID.passwd"

# Créer le fichier de configuration Nginx
NGINX_USER_CONF="/etc/nginx/code-server-users/$USER_ID.conf"

cat > "$NGINX_USER_CONF" EOF
location /$USER_ID/ {
    proxy_pass http://127.0.0.1:$PORT/;
    proxy_set_header Host \$host;
    proxy_set_header X-Real-IP \$remote_addr;
    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host \$http_host;
    proxy_set_header X-Forwarded-Proto \$scheme;
    proxy_set_header Upgrade \$http_upgrade;
    proxy_set_header Connection \$http_connection;
    proxy_http_version 1.1;
}
EOF

# Recharger Nginx pour prendre en compte la nouvelle configuration
systemctl reload nginx

# Envoyer l'email SEULEMENT si le conteneur fonctionne bien
EMAIL_BODY="Bonjour,

Votre espace Code Server est prêt !

🌍 Accès : https://codes.domain.tld/$USER_ID  
🔑 Mot de passe : $PASSWORD  

Cordialement,
L'équipe Admin."

echo "$EMAIL_BODY" | msmtp -a default "$USER_EMAIL"

echo "Code Server pour $USER_EMAIL créé avec succès !"

Dans le fichier adapter domain.tld par votre domaine, il est possible de déclarer plusieurs domaine de messagerie ALLOWED_DOMAINS=("domain.tld" "domain-2.tld").

Maintenant, on va configurer le reverse proxy, car comment vous pouvez le voir dans le script, le conteneur Code Server sera disponible à l’adresse suivante : https://codes.domain.tld/$USER_ID.

Commencer par créer le dossier qui va recevoir les configurations d’URL pour chaque utilisateur :

sudo mkdir -p /etc/nginx/code-server-users

Ensuite créer le virtualhost, ci dessous la configuration :

server{
    listen 443 ssl;
    http2 on;
    server_name codes.domain.tld

    access_log /var/log/nginx/codesdomaintld_access.log;

    ssl_certificate /etc/nginx/ssl/domaintld.cert;
    ssl_certificate_key /etc/nginx/ssl/domaintld.key;

    location /{
        proxy_pass http://localhost;
        include proxy_params;
        proxy_ssl_verify off;
    }

    # Inclusion dynamique des configurations utilisateurs
    include /etc/nginx/code-server-users/*.conf;

}

server{
    listen 80;
    server_name codes.domain.tld;
    if ($host = codes.domain.tld) {
        return 301 https://$host$request_uri;
    }
}

Vous avez tous les éléments pour configurer le serveur.

Tester le Workflow

Depuis un navigateur, aller sur l’URL du formulaire N8N, entrer votre adresse e-mail et envoyer le formulaire.

Un e-mail est envoyé avec l’url pour accéder au conteneur Code Server avec le mot de passe.

En cas d’arrêt du serveur hôte Docker, les utilisateurs devront refaire une demande pour démarrer le conteneur et avoir le nouveau mot de passe. Le dossier config étant redirigé localement, ils récupéreront leur espace.

Complément

Pour compléter cette partie, voici un script pour la maintenance.

Suppression des conteneurs en gardant les dossiers utilisateurs.

#!/bin/bash

echo "🔴 Suppression de tous les Code Servers..."

# Supprimer tous les conteneurs Code Server
docker ps -a --format "{{.Names}}" | grep "code-" | while read -r container; do
    echo "Arrêt et suppression de $container..."
    docker stop "$container"
    docker rm "$container"
done

# Supprimer toutes les configurations Nginx des utilisateurs
NGINX_CONF_DIR="/etc/nginx/code-server-users"
if [ -d "$NGINX_CONF_DIR" ]; then
    echo "Suppression des configurations Nginx..."
    rm -f "$NGINX_CONF_DIR"/*.conf
    systemctl reload nginx
fi

# Supprimer tous les fichiers de mots de passe stockés
PASSWD_DIR="/var/lib/code-server"
if [ -d "$PASSWD_DIR" ]; then
    echo "Suppression des mots de passe stockés..."
    rm -f "$PASSWD_DIR"/*.passwd
fi

echo "✅ Tous les Code Servers ont été supprimés avec succès."

Vous savez maintenant comment créer des conteneurs Code Server par utilisateurs à l’aide de N8N et d’un script pour générer les conteneurs.

Romain Drouche
Architecte Système | MCSE: Core Infrastructure
Expert en infrastructures IT avec plus de 15 ans d’expérience sur le terrain. Actuellement Chef de projet Systèmes et Réseaux et Référent SSI (Sécurité des Systèmes d’Information), je mets mon expertise au service de la fiabilité et de la sécurité des environnements technologiques.

Laisser un commentaire