Des boxes Vagrant Docker avec WSL 2
Pour ceux qui veulent tout de même utiliser WSL plutôt qu’une machine hyper-v, il est compliqué de faire fonctionner Vagrant. Pourtant, on peut y arriver en utilisant des boxes au format Docker. Le fonctionnement sera le même qu’avec des machines provisionnées avec libvirt sauf une seule chose : Les services ne seront pas utilisables, Docker oblige, à moins peut être de créer ses propres boxes ou systemd est opérationnel. Je l’ai déjà fait dans un job précédent, je vais fouiller dans mon historique et je vous les ajouterai au bout de ce billet.
Installation de Docker sur WSL
Ici je ne vais pas utiliser Docker Desktop, qui consomme des ressources mémoires qui parfois sont limitées sur un poste d’entreprise. Je vais donc installer Docker au sein de WSL et ajouter à mon profil le lancement de celui-ci.
# Installation des pre-requissudo apt updatesudo apt install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release
# Ajout du repo Dockerecho "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Ajout de la clé du repo Dockercurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Installation de Dockersudo apt update && sudo apt install docker-ce docker-ce-cli containerd.io
# Ajout du user courant au group Dockersudo usermod -aG docker $USER
Maintenant l’astuce pour le démarrer.
- Sous windows 11, il faut ajouter ces lignes au fichier
/etc/wsl.conf
:
vi /etc/wsl.conf
[boot]command = "service docker start"
wsl.exe --shutdown
Une fois la machine WSL redémarré vérifier que Docker est bien opérationnel :
docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- Sous Windows 10, il faut ajouter ces lignes à votre
.profile
:
vi ~/.profile
if service docker status 2>&1 | grep -q "is not running"; then wsl.exe -d "${WSL_DISTRO_NAME}" -u root -e /usr/sbin/service docker start >/dev/null 2>&1fi
wsl.exe --shutdown
Une fois la machine WSL redemarrer vérifier que Docker est bien opérationnel
docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Installation de Vagrant
Il ne reste plus qu’à installer Vagrant :
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"sudo apt update && sudo apt install vagrant
On redémarre pour récupérer le groupe vagrant
:
wsl.exe --shutdown
Utilisation d’une box Vagrant utilisant le provider Docker
Nous allons créer notre image Docker à base d’Ubuntu :
FROM ubuntu:jammy
ENV DEBIAN_FRONTEND noninteractive
# Install packages needed for SSH and interactive OSRUN apt update && \ yes | unminimize && \ apt -y install \ openssh-server \ passwd \ sudo \ man-db \ curl \ wget && \ apt -qq clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Enable systemd (from Matthew Warman's mcwarman/vagrant-provider)RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*; \ rm -f /etc/systemd/system/*.wants/*; \ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*; \ rm -f /lib/systemd/system/anaconda.target.wants/*;
# Create the vagrant userRUN useradd -m -G sudo -s /bin/bash vagrant && \ echo "vagrant:vagrant" | chpasswd && \ echo 'vagrant ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vagrant && \ chmod 440 /etc/sudoers.d/vagrant
# Establish ssh keys for vagrantRUN mkdir -p /home/vagrant/.ssh; \ chmod 700 /home/vagrant/.sshADD https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub /home/vagrant/.ssh/authorized_keysRUN chmod 600 /home/vagrant/.ssh/authorized_keys; \ chown -R vagrant:vagrant /home/vagrant/.ssh
# Enable ssh for vagrant
RUN systemctl enable ssh.service;EXPOSE 22
# Run the init daemonVOLUME [ "/sys/fs/cgroup" ]CMD ["/usr/sbin/init"]
Maintenant notre Vagrantfile :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
Vagrant.configure("2") do |config| config.vm.provider "docker" do |docker| docker.name = "test" docker.build_dir = "vagrant_docker" docker.remains_running = true docker.has_ssh = true docker.privileged = true docker.create_args = ['--tmpfs', '/tmp', '--tmpfs', '/run', '--tmpfs', '/run/lock', '-v', '/sys/fs/cgroup:/sys/fs/cgroup:ro', '-t'] # docker.run_args = ['--tmpfs', '/tmp', '--tmpfs', '/run', '--tmpfs', '/run/lock', '-v', '/sys/fs/cgroup:/sys/fs/cgroup:ro', '-t'] end config.vm.synced_folder ".", "/vagrant", disabled: trueend
On lance la construction de la box :
vagrant up==> default: Deleting the container...==> default: Creating and configuring docker networks...==> default: Building the container from a Dockerfile... default: Sending build context to Docker daemon 5.12kB default: Step 1/12 : FROM ubuntu:jammy default: ---> f0b07b45d05b default: Step 2/12 : ENV DEBIAN_FRONTEND noninteractive default: ---> Using cache default: ---> 8719e8bebd18 default: Step 3/12 : RUN apt update && yes | unminimize && apt -y install openssh-server passwd sudo man-db curl wget && apt -qq clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* default: ---> Using cache default: ---> b98aead5545e default: Step 4/12 : RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); rm -f /lib/systemd/system/multi-user.target.wants/*; rm -f /etc/systemd/system/*.wants/*; rm -f /lib/systemd/system/local-fs.target.wants/*; rm -f /lib/systemd/system/sockets.target.wants/*udev*; rm -f /lib/systemd/system/sockets.target.wants/*initctl*; rm -f /lib/systemd/system/basic.target.wants/*; rm -f /lib/systemd/system/anaconda.target.wants/*; default: ---> Using cache default: ---> 6446c02572c6 default: Step 5/12 : RUN useradd -m -G sudo -s /bin/bash vagrant && echo "vagrant:vagrant" | chpasswd && echo 'vagrant ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vagrant && chmod 440 /etc/sudoers.d/vagrant default: ---> Using cache default: ---> 85245e51458d default: Step 6/12 : RUN mkdir -p /home/vagrant/.ssh; chmod 700 /home/vagrant/.ssh default: ---> Using cache default: ---> 98f6d137e908 default: Step 7/12 : ADD https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub /home/vagrant/.ssh/authorized_keys default: default: ---> Using cache default: ---> 99f3d4a28c38 default: Step 8/12 : RUN chmod 600 /home/vagrant/.ssh/authorized_keys; chown -R vagrant:vagrant /home/vagrant/.ssh default: ---> Using cache default: ---> 911ca2434ea8 default: Step 9/12 : RUN systemctl enable ssh.service; default: ---> Using cache default: ---> 53a988bb68c2 default: Step 10/12 : EXPOSE 22 default: ---> Using cache default: ---> 37d6136d6e1b default: Step 11/12 : VOLUME [ "/sys/fs/cgroup" ] default: ---> Using cache default: ---> 4b5c40d8c1ea default: Step 12/12 : CMD ["/usr/sbin/init"] default: ---> Using cache default: ---> 3c5a7f9c664a default: Successfully built 3c5a7f9c664a default: default: Image: 3c5a7f9c664a==> default: Creating the container... default: Name: test default: Image: 3c5a7f9c664a default: Port: 127.0.0.1:2222:22 default: default: Container created: b46c9ae50f3f3cac==> default: Enabling network interfaces...==> default: Starting container...==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key default: default: Vagrant insecure key detected. Vagrant will automatically replace default: this with a newly generated keypair for better security. default: default: Inserting generated public key within guest... default: Removing insecure key from the guest if it's present... default: Key inserted! Disconnecting and reconnecting using new SSH key...==> default: Machine booted and ready!
On vérifie que notre container tourne :
docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESb46c9ae50f3f 3c5a7f9c664a "/usr/sbin/init" 8 seconds ago Up 7 seconds 127.0.0.1:2222->22/tcp test
On se connecte :
vagrant ssh
Welcome to Ubuntu 22.04 LTS (GNU/Linux 5.10.102.1-microsoft-standard-WSL2 x86_64)
* Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantagevagrant@b46c9ae50f3f:~$systemctl status sshd.service
● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2022-04-21 07:36:51 UTC; 6min ago Docs: man:sshd(8) man:sshd_config(5) Process: 22 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS) Main PID: 23 (sshd) Tasks: 6 (limit: 1157) Memory: 23.6M CGroup: /system.slice/ssh.service ├─ 23 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups" ├─261 "sshd: vagrant [priv]" ├─271 "sshd: vagrant@pts/1" "" ├─272 -bash ├─275 systemctl status sshd
On se croirait sur un VM, non ? En plus ça se lance très vite !
Il ne reste plus qu’à créer notre provisioner ansible
. On crée le fichier
provision.yml avec ce contenu :
---- hosts: all tasks: - debug: msg: "Hello from Docker"
On met à jour notre Vagrantfile :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
Vagrant.configure("2") do |config| config.vm.provider "docker" do |docker| docker.name = "test" docker.build_dir = "vagrant_docker" docker.remains_running = true docker.has_ssh = true docker.privileged = true docker.create_args = ['--tmpfs', '/tmp', '--tmpfs', '/run', '--tmpfs', '/run/lock', '-v', '/sys/fs/cgroup:/sys/fs/cgroup:ro', '-t'] end config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provision "ansible" do |ansible| ansible.playbook = "provision.yml" endend
On relance la box :
vagrant reload==> default: Stopping container...==> default: Deleting the container...==> default: Creating and configuring docker networks...==> default: Building the container from a Dockerfile......
==> default: Machine booted and ready!==> default: Running provisioner: ansible... default: Running ansible-playbook...
default: Running ansible-playbook... ____________< PLAY [all] > ------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
________________________< TASK [Gathering Facts] > ------------------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
ok: [default] ______________< TASK [debug] > -------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
ok: [default] => { "msg": "Hello from Docker"} ____________< PLAY RECAP > ------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
default : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Et voilà le top du top !!!!