vagrant-docker-networks-manager
Vagrant plugin to manage Docker networks with labeled ownership, safe lifecycle hooks, JSON output, and conflict-aware validation.
- Creates a Docker network on
vagrant up(with labels & marker) - Cleans it on
vagrant destroyonly if owned by this machine (safe) -
vagrant networkCLI:init | destroy | info | reload | list | prune | rename - IPv4/CIDR validation, subnet conflict detection, optional macvlan
- i18n (English 🇬🇧 / Français 🇫🇷), emojis, and normalized JSON output
Requirements: Vagrant ≥ 2.2, Ruby ≥ 3.1, Docker (CLI + daemon) running
Table of contents
- Why this plugin?
- Installation
- Quick start
- Vagrantfile configuration
- CLI usage
- JSON output examples
- Ownership & safety
- Subnet validation & conflicts
- Internationalization
- Environment variables
- Permissions & OS notes
- Troubleshooting
- Contributing & Development
- License
🇫🇷 Français : voir README.fr.md
Why this plugin?
Managing Docker networks across Vagrant projects is tedious:
- naming consistency, subnet overlaps, and safe cleanup are error-prone
- destroying a VM shouldn’t delete someone else’s shared network
- operators need deterministic CLI and machine-readable output
This plugin solves these by labeling networks, keeping a marker per machine, validating CIDR + detecting overlaps, and offering a clean CLI with JSON output.
Installation
From RubyGems (once published):
vagrant plugin install vagrant-docker-networks-managerFrom source (local path):
git clone https://github.com/julienpoirou/vagrant-docker-networks-manager
cd vagrant-docker-networks-manager
bundle install
rake
vagrant plugin install . # install from the local gemspecCheck it’s available:
vagrant network version
vagrant network helpQuick start
Minimal Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/ubuntu-22.04"
# Docker network plugin config
config.docker_network.network_name = "myproj_net" # ⚠️ personalize to avoid collisions
config.docker_network.network_subnet = "172.28.50.0/24"
config.docker_network.network_gateway = "172.28.50.1"
config.docker_network.network_type = "bridge" # or "macvlan"
config.docker_network.network_parent = nil # required if macvlan
config.docker_network.network_attachable = true
config.docker_network.enable_ipv6 = false
config.docker_network.ip_range = nil # optional
config.docker_network.cleanup_on_destroy = true
config.docker_network.locale = "en" # "en" or "fr"
endCreate the network on up
vagrant upIf a network with the same name already exists:
- if it’s owned by this machine (labels match), it’s “adopted”
- otherwise you simply get an info message (no destructive action)
Destroy VM and clean the network
vagrant destroy- The network is removed only if created/owned by this machine.
- To also remove attached containers during Vagrant destroy:
VDNM_DESTROY_WITH_CONTAINERS=1 vagrant destroyVagrantfile configuration
All options (with defaults):
| Key | Type | Default | Notes |
|---|---|---|---|
network_name |
String | "network_lo1" |
⚠️ Personalize to avoid collisions across projects. |
network_subnet |
String | "172.28.100.0/26" |
Must be aligned IPv4/CIDR (e.g. x.y.z.0/nn). |
network_type |
String | "bridge" |
"bridge" or "macvlan". |
network_gateway |
String | "172.28.100.1" |
Must be a host address inside network_subnet. |
network_parent |
String | nil |
Required if network_type == "macvlan". |
network_attachable |
Bool | false |
Adds --attachable. |
enable_ipv6 |
Bool | false |
Adds --ipv6. |
ip_range |
String | nil |
IPv4/CIDR inside network_subnet. |
cleanup_on_destroy |
Bool | true |
Remove network on vagrant destroy if owned/created. |
locale |
String | "en" |
"en" or "fr". |
Validation performed:
- Docker name constraints, aligned IPv4/CIDR,
gatewaynot network/broadcast -
ip_rangemust be included innetwork_subnet -
macvlanrequiresnetwork_parent
CLI usage
vagrant network <command> [args] [options]
Commands:
init <name> <subnet>
destroy <name> [--with-containers] [--yes]
reload <name> [--yes]
info <name>
list [--json]
prune [--yes]
rename <old> <new> [<subnet>] [--yes]
version
Global options:
--json # machine-readable output
--yes, -y # auto-confirm prompts
--quiet # reduce output (hide info)
--no-emoji # disable emojis
--lang en|fr # force language
Examples:
vagrant network init mynet 172.28.100.0/26
vagrant network info mynet
vagrant network list
vagrant network destroy mynet --with-containers --yes
vagrant network reload mynet --yes
vagrant network rename oldnet newnet --yes
vagrant network rename oldnet same-name 10.10.0.0/24 --yes
vagrant network prune --yesJSON output examples
Enable with --json for any command.
init
{"action":"init","status":"success","data":{"name":"mynet","subnet":"172.28.100.0/26"}}info
{
"action":"info",
"status":"success",
"data":{
"network":{
"Name":"mynet",
"Id":"...docker-id...",
"Driver":"bridge",
"Subnets":["172.28.100.0/26"],
"Containers":[{"Name":"web","IPv4":"172.28.100.2/26"}]
}
}
}prune (nothing to do)
{"action":"prune","status":"success","data":{"pruned":0,"items":[]}}Errors are normalized:
{"action":"destroy","status":"error","error":"Network not found.","data":{"name":"ghost"}, "code":1}Ownership & safety
- Networks are created with labels:
com.vagrant.plugin=docker_networks_managercom.vagrant.machine_id=<VAGRANT_MACHINE_ID>
- A marker file is also written in:
.vagrant/machines/<name>/<provider>/docker-networks/<network>.json
On vagrant destroy, the plugin only removes a network if:
- the marker indicates it was created by this machine, or
- labels match this machine’s id (ownership)
If a network exists but is not owned, the plugin leaves it untouched.
Subnet validation & conflicts
Before creating (or renaming to a new subnet), the plugin:
- Validates
network_subnetis an aligned IPv4/CIDR
(e.g.172.28.100.0/24, not172.28.100.1/24) - Scans existing Docker networks and checks for overlaps
(ignoring the target network when appropriate)
This prevents hard-to-debug IP conflicts.
Internationalization
- Locales: en, fr
- Choose via CLI
--lang en|fr, or setlocalein your Vagrantfile, orVDNM_LANG=en|fr.
Emojis can be disabled with --no-emoji.
Environment variables
| Variable | Purpose |
|---|---|
VDNM_LANG |
Force locale (en/fr) in hooks. |
VDNM_VERBOSE |
When 1, prints the full docker command on STDERR and shows the native Docker output. |
VDNM_SKIP_CONFLICTS |
When 1, the reload ignores subnet conflict detection (dangerous, for experts only). |
VDNM_DESTROY_WITH_CONTAINERS |
When 1, on Vagrant destroy the plugin also runs docker rm -f for attached containers (in addition to disconnect). |
The CLI
vagrant network destroy <name> --with-containersachieves the same for the manual command.
Permissions & OS notes
This plugin only calls docker CLI commands — no elevated privileges are required by the plugin itself. However, the Docker daemon must be reachable by the current user (e.g. the user must be in the docker group on Linux, or Docker Desktop must be running on macOS/Windows).
Troubleshooting
-
Docker is unavailable: ensure Docker Desktop/daemon is running and the CLI works (
docker info). -
Invalid subnet: use aligned IPv4/CIDR (e.g.
10.0.0.0/24). - Subnet already in use: another network overlaps. Pick a different range.
-
Remove failed: some containers or other constraints may block
docker network rm. Try--verbose(VDNM_VERBOSE=1) to see Docker’s output. -
macvlan: remember to set
network_parent(host interface).
Contributing & Development
git clone https://github.com/julienpoirou/vagrant-docker-networks-manager
cd vagrant-docker-networks-manager
bundle install
rake # runs RSpec- Conventional Commits enforced in PRs.
- CI runs RuboCop, tests, and builds the gem.
- See
docs/en/CONTRIBUTING.mdanddocs/en/DEVELOPMENT.mdif present.
License
MIT © 2025 Julien Poirou
Tip: prefer setting a project-specific
network_name(e.g.myapp_net) to avoid collisions if multiple Vagrant projects run on the same host.