LFCE 4 🐧 Building a Lab with VMs or Containers
The previous chapter introduced the practice lab options at the high level. This chapter dives into the two practical implementation paths: the virtual machines (the full isolation, the own kernel) and the containers (the lightweight, the shared kernel). The LFCE tested the multi-system scenarios: the DNS, the DHCP, the PXE, the centralized authentication. The virtual machines are the natural fit for these scenarios because the services require the separate kernels, the isolated network stacks, and the systemd init. The containers are the faster and the lighter, but the shared kernel and the missing systemd (in the default Docker) limit the service testing. The critical distinction is between the container for the application (the Docker, the Podman) and the system container (the LXC, the systemd-nspawn) that runs the full init.
Key point: The virtual machines (the KVM/libvirt, the VirtualBox, the Vagrant) are the recommended for the LFCE study because the service scenarios (the DNS, the DHCP, the PXE) require the separate kernels and the full init systems. The containers (the Docker) are the faster for the application isolation and the command-line practice, but the shared kernel limits the kernel-level and the init-level testing. The Vagrant with the VirtualBox or the libvirt is the best balance: the declarative multi-VM provisioning, the snapshots, and the disposable state.
Why the VM versus container distinction matters
The kernel problem. The LFCE tested the kernel-level configuration: the sysctl, the kernel modules, the boot parameters, the SELinux. The containers share the host kernel. The sysctl -w inside the container changes the host kernel, not the container’s. The uname -r returns the host kernel version. The kernel testing requires the VM with the own kernel .
The init problem. The LFCE tested the systemd services: the systemctl, the journalctl, the unit files. The default Docker container runs the single process, not the systemd. The systemd requires the privileged container or the system container (the LXC, the systemd-nspawn) with the --system flag. The service testing is the easier in the VM with the native systemd .
The network problem. The LFCE tested the DNS, the DHCP, the PXE. The DHCP server requires the broadcast on the isolated network. The PXE requires the TFTP and the DHCP integration. The container network is the bridge with the NAT; the broadcast is the limited. The VM with the host-only or the bridged network provides the realistic L2/L3 environment for the DHCP and the PXE testing .
The performance problem. The containers are the faster to start and the lighter on the RAM. The three containers use the 500 MB total. The three VMs use the 12 GB. The host with the 8 GB RAM can run the three containers, but not the three VMs. The candidate with the limited hardware uses the containers for the command-line practice and the cloud VMs for the service integration .
The trade-off. The VMs are the complete but the resource-heavy. The containers are the fast but the limited. The Vagrant with the VirtualBox is the best balance: the declarative provisioning, the snapshots, the full VM isolation. The Docker is the supplement for the quick command-line drills .
a. The VM lab with Vagrant
The Vagrant is the declarative VM provisioning. The single Vagrantfile defines the multiple VMs. The vagrant up creates and starts them. The vagrant destroy removes them. The vagrant snapshot save and the vagrant snapshot restore handle the disposable state .
The Vagrantfile with the three nodes.
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
nodes = [
{ name: "lab-node1", ip: "192.168.56.10" },
{ name: "lab-node2", ip: "192.168.56.11" },
{ name: "lab-node3", ip: "192.168.56.12" },
]
nodes.each do |node|
config.vm.define node[:name] do |n|
n.vm.hostname = node[:name]
n.vm.network "private_network", ip: node[:ip]
n.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
end
end
end
end
The private_network with the fixed IP creates the host-only network. The VMs can reach each other via the 192.168.56.0/24. The virtualbox provider sets the 2 GB and the 2 CPU per VM. The vagrant up creates all three .
The hosts file on each VM.
# On each VM
cat | sudo tee -a /etc/hosts <<EOF
192.168.56.10 lab-node1
192.168.56.11 lab-node2
192.168.56.12 lab-node3
EOF
The /etc/hosts provides the name resolution. The ping lab-node2 from the lab-node1 works. The SSH between the VMs works with the key auth.
The snapshot.
vagrant snapshot save lab-node1 clean
vagrant snapshot restore lab-node1 clean
The snapshot save creates the named snapshot. The snapshot restore reverts. The Vagrant snapshots are the fast reset for the destructive experiments .
b. The container lab with Docker
The Docker containers are the faster. The single host, the multiple containers on the user-defined bridge network. The containers can reach each other by the name .
The network and the containers.
# Create the user-defined network
docker network create lab-net
# Create the three containers
docker run -d --name lab-node1 --network lab-net --hostname lab-node1 alpine sleep infinity
docker run -d --name lab-node2 --network lab-net --hostname lab-node2 alpine sleep infinity
docker run -d --name lab-node3 --network lab-net --hostname lab-node3 alpine sleep infinity
The --network lab-net connects the containers to the same bridge. The --hostname sets the name. The containers can reach each other by the name (ping lab-node2) because the Docker DNS resolves the container names on the user-defined network .
The limitation: the Alpine does not have the systemd. The systemctl does not work. The service testing requires the system container.
The system container with the systemd.
# Run the systemd container (the privileged)
docker run -d --name sys-node1 --privileged --network lab-net \
--hostname sys-node1 \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
jrei/systemd-ubuntu:22.04
The --privileged and the /sys/fs/cgroup mount enable the systemd inside the container. The systemctl works. The limitation is the shared kernel: the uname -r returns the host kernel. The kernel-level testing is the not the accurate .
The Docker is the supplement for the command-line drills: the grep, the sed, the awk, the tar, the chmod. The fast and the disposable. The docker exec -it lab-node1 sh enters the shell. The docker rm -f lab-node1 removes the container .
c. The hybrid approach
The best strategy for the LFCE study is the hybrid: the containers for the daily command-line drills, the VMs for the service integration and the kernel-level testing, and the cloud VMs for the multi-system scenarios when the local hardware is the limited.
The containers for the essential commands.
# The daily drill
docker run --rm -it ubuntu:22.04 bash
# Practice the grep, the sed, the awk, the tar, the chmod
exit
The --rm removes the container on the exit. The clean state for every drill. The fast.
The VMs for the services.
# The Vagrant for the DNS, the DHCP, the PXE
vagrant up
vagrant ssh lab-node1
sudo apt install bind9 isc-dhcp-server
# Configure the services
The Vagrant VMs have the systemd, the network, the kernel. The service configuration is the realistic.
The LFCE-specific Vagrant.
# The lfce-vagrant-env (the CentOS 7 simulation)
git clone https://github.com/lrakai/lfce-vagrant-env.git
cd lfce-vagrant-env
bash up_exam.sh
The lfce-vagrant-env provides the box, the node1, the node2 with the /etc/hosts and the SSH. The closest to the LFCE exam .
The container-based LFCS practice tool.
# The lfcs-practice-tool (the container-based)
pip install lfcs
lfcs start
The lfcs-practice-tool builds the Docker images automatically on the first use. The 83+ scenarios with the automatic validation. The lfcs start launches the interactive practice. The lfcs start --category networking --difficulty easy filters the scenarios. The exit validates the work. The tool is the LFCS-focused, but the networking and the storage scenarios overlap with the LFCE .
Complete Example Session
# ============================================
# PART 1: VAGRANT VM LAB
# ============================================
# The Vagrantfile with the three nodes
vagrant up
vagrant status
# ============================================
# PART 2: HOSTS FILE
# ============================================
vagrant ssh lab-node1
echo "192.168.56.11 lab-node2" | sudo tee -a /etc/hosts
ping lab-node2
# ============================================
# PART 3: SNAPSHOT
# ============================================
vagrant snapshot save lab-node1 clean
# ============================================
# PART 4: DOCKER NETWORK
# ============================================
docker network create lab-net
docker run -d --name lab-node1 --network lab-net --hostname lab-node1 alpine sleep infinity
# ============================================
# PART 5: DOCKER PING
# ============================================
docker exec -it lab-node1 sh
ping lab-node2
exit
# ============================================
# PART 6: SYSTEMD CONTAINER
# ============================================
docker run -d --name sys-node1 --privileged --network lab-net --hostname sys-node1 -v /sys/fs/cgroup:/sys/fs/cgroup:ro jrei/systemd-ubuntu:22.04
docker exec -it sys-node1 systemctl status
# ============================================
# PART 7: LFCE VAGRANT
# ============================================
git clone https://github.com/lrakai/lfce-vagrant-env.git
cd lfce-vagrant-env
bash up_exam.sh
# ============================================
# PART 8: LFCS PRACTICE TOOL
# ============================================
pip install lfcs
lfcs start
lfcs start --category networking --difficulty easy
# ============================================
# PART 9: THE HYBRID
# ============================================
# Containers: the daily drills
# VMs: the services and the kernel
# Cloud: the multi-system
# LFCE Vagrant: the exam simulation
The nine parts trace the VM and container lab: the Vagrant VMs, the hosts file, the snapshot, the Docker network, the Docker ping, the systemd container, the LFCE Vagrant, the LFCS tool, and the hybrid.
Quick Reference
VM Tools
| Tool | Purpose |
|---|---|
| Vagrant | Declarative multi-VM |
| VirtualBox | Hypervisor |
| KVM/libvirt | Linux hypervisor |
Container Tools
| Tool | Purpose |
|---|---|
| Docker | Application containers |
| Podman | Daemonless alternative |
| LXC/LXD | System containers |
Vagrant Commands
| Command | Purpose |
|---|---|
vagrant up | Create and start |
vagrant ssh | SSH into the VM |
vagrant snapshot save | Create the snapshot |
vagrant snapshot restore | Revert |
vagrant destroy | Remove the VMs |
Docker Commands
| Command | Purpose |
|---|---|
docker network create | User-defined network |
docker run --network | Connect to the network |
docker run --privileged | System container |
docker exec -it | Enter the container |
Best Practices
✅ Do This:
vagrant snapshot save lab-node1 clean
<!-- Snapshot before the experiments --> # ✅
docker network create lab-net
<!-- Create the user-defined network --> # ✅
docker run --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro
<!-- Run the systemd container --> # ✅
❌ Don’t Do This:
# Use the Docker for the kernel testing
<!-- The shared kernel limits it --> # ❌
# Use the Alpine for the systemd services
<!-- No systemd in the Alpine --> # ❌
# Skip the snapshot
<!-- The destructive change requires the reinstall --> # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Containers cannot ping by name | Default bridge | Use user-defined network |
| systemctl fails in Docker | No systemd | Use the system container |
| Vagrant VM slow | The host RAM insufficient | Reduce the VM RAM or use the cloud |
| VMs cannot reach each other | No the private network | Add the private_network |
| Snapshot lost | No the snapshot save | vagrant snapshot save |
Real-World Examples
1. Vagrantfile
config.vm.network "private_network", ip: "192.168.56.10"
2. Vagrant Up
vagrant up
3. Vagrant Snapshot
vagrant snapshot save lab-node1 clean
4. Docker Network
docker network create lab-net
5. Docker Run
docker run -d --name lab1 --network lab-net alpine
6. Docker Ping
docker exec lab1 ping lab2
7. Systemd Container
docker run --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro jrei/systemd-ubuntu
8. LFCE Vagrant
git clone https://github.com/lrakai/lfce-vagrant-env.git
9. LFCS Tool
pip install lfcs && lfcs start
10. Hybrid
Containers for the drills, VMs for the services
Visual
VM vs Container
┌──────────────────────────────────────────────┐
│ VM (the full isolation) │
│ ├── Own kernel │
│ ├── Own init (systemd) │
│ ├── Own network stack │
│ └── The service testing │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Container (the lightweight) │
│ ├── Shared kernel │
│ ├── Single process (default) │
│ ├── The NAT bridge │
│ └── The command-line drills │
└──────────────────────────────────────────────┘
The Hybrid Lab
┌──────────────────────────────────────────────┐
│ Daily drills: the Docker containers │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Service integration: the Vagrant VMs │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Multi-system: the cloud VMs │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Exam simulation: the lfce-vagrant-env │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| VM tool | Vagrant + VirtualBox/KVM |
| Container tool | Docker, Podman |
| Vagrant network | private_network |
| Docker network | User-defined bridge |
| System container | --privileged + cgroup |
| Snapshot | vagrant snapshot save |
| LFCE Vagrant | lfce-vagrant-env |
| LFCS tool | lfcs-practice-tool |
Key takeaways:
- The VMs are the complete. The separate kernel, the systemd, the isolated network. The service scenarios (the DNS, the DHCP, the PXE) require the VMs. The Vagrant is the declarative provisioning .
- The containers are the fast. The user-defined network provides the name resolution. The
--privilegedand the cgroup mount enable the systemd. The shared kernel limits the kernel-level testing . - The hybrid is the best. The containers for the daily command-line drills. The VMs for the service integration. The cloud for the multi-system. The LFCE Vagrant for the exam simulation .
- The snapshot is the reset. The
vagrant snapshot savebefore the destructive experiments. Thevagrant snapshot restoreto revert. The clean state is the fast recovery . - The LFCS practice tool is the supplement. The
lfcs-practice-toolbuilds the Docker images automatically and provides the 83+ scenarios with the validation. The networking and the storage overlap with the LFCE .
Remember: The VM is the complete. The container is the fast. The hybrid is the strategy. The Vagrant is the declarative. The snapshot is the reset. The exam tests the services and the kernel, and the VM is the environment for the testing.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!