sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
curl -sSL https://get.docker.com/ | CHANNEL=stable bash
sudo apt install jq -y && \
DOCKER_COMPOSE_VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | jq .name -r) && \
DOCKER_CLI_PLUGIN_PATH=/usr/local/lib/docker/cli-plugins && \
sudo mkdir -p $DOCKER_CLI_PLUGIN_PATH && \
sudo curl -L "https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m)" -o $DOCKER_CLI_PLUGIN_PATH/docker-compose && \
sudo chmod +x $DOCKER_CLI_PLUGIN_PATH/docker-compose
A macvlan network allows Docker containers to appear as physical devices on the physical network with their own MAC and IP addresses.
To create a macvlan network, you need to know the network's subnets, gateways, and the physical network interface name of the host machine.
ip route show defaultdev. (e.g., default via 192.168.1.1 dev enp87s0 -> Your interface is enp87s0).ip route show defaultvia. (e.g., 192.168.1.1).ip -o -f inet addr show <your_interface_name>0. (e.g., 192.168.1.95/24 becomes 192.168.1.0/24).ip -o -f inet6 addr show <your_interface_name>scope global. (e.g., fdaa:bbcc:ddee::/64). Your gateway is usually your router's IP on that same subnet, ending in ::1.Manual Command Execution:
docker network create -d macvlan \
--ipv6 \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.2 \
--subnet=fdaa:bbcc:ddee::/64 \
--gateway=fdaa:bbcc:ddee::1 \
-o parent=enp87s0 \
LAN
Use this automated script to detect the network settings and generate a Macvlan network.
nano create_macvlan.sh
#!/bin/bash
set -euo pipefail
# ANSI Escape Code for Colors
reset="\033[0m"
bold="\033[1m"
blue_bg="\033[44m"
yellow_bg="\033[43m"
red_bg="\033[41m"
blue_fg_strong="\033[94m"
yellow_fg_strong="\033[93m"
red_fg_strong="\033[91m"
cyan_fg_strong="\033[96m"
# Function to log messages with timestamps and colors
log_message() {
current_time=$(date +'%H:%M:%S')
case "$1" in
"INFO") echo -e "${blue_bg}[$current_time]${reset} ${blue_fg_strong}[INFO]${reset} $2" ;;
"WARN") echo -e "${yellow_bg}[$current_time]${reset} ${yellow_fg_strong}[WARN]${reset} $2" ;;
"ERROR") echo -e "${red_bg}[$current_time]${reset} ${red_fg_strong}[ERROR]${reset} $2" ;;
"SUCCESS") echo -e "${blue_bg}[$current_time]${reset} \033[92m[SUCCESS]${reset} $2" ;;
*) echo -e "${blue_bg}[$current_time]${reset} ${blue_fg_strong}[DEBUG]${reset} $2" ;;
esac
}
# Ensure root privileges
if [[ $EUID -ne 0 ]]; then
log_message "ERROR" "This script must be run as root. (Use sudo)"
exit 1
fi
clear
echo -e "\033]0;Docker [MACVLAN CONFIGURATOR]\007"
echo -e "${blue_fg_strong}${bold}╔══════════════════════════════════════════════════════════════╗${reset}"
echo -e "${blue_fg_strong}${bold}║ DOCKER MACVLAN AUTO-CONFIGURATOR ║${reset}"
echo -e "${blue_fg_strong}${bold}╚══════════════════════════════════════════════════════════════╝${reset}"
echo
# 1. Ask for Network Name & Check if it exists
while true; do
read -p " Enter Network Name [LAN]: " NET_NAME
NET_NAME=${NET_NAME:-LAN}
if docker network ls --format '{{.Name}}' | grep -wq "^${NET_NAME}$"; then
echo
log_message "WARN" "A Docker network named '${NET_NAME}' already exists!"
echo -e "${cyan_fg_strong} _____________________________________________________________${reset}"
echo -e "${cyan_fg_strong}| Menu Options: |${reset}"
echo -e " 1. ${red_fg_strong}DELETE${reset} existing '${NET_NAME}' and recreate it"
echo -e " 2. Choose a different network name"
echo -e " 0. Cancel and Exit"
echo -e "${cyan_fg_strong} _____________________________________________________________${reset}"
read -p " Choose an option: " subchoice
case $subchoice in
1)
log_message "INFO" "Removing existing network '${NET_NAME}'..."
docker network rm "$NET_NAME" || { log_message "ERROR" "Failed to remove network. Ensure containers are disconnected first."; exit 1; }
break
;;
2)
echo
continue
;;
0)
log_message "INFO" "Exiting."
exit 0
;;
*)
log_message "ERROR" "Invalid option."
continue
;;
esac
else
break
fi
done
echo
log_message "INFO" "Scanning system for network interfaces and routes..."
# 2. Auto-detect default interface
DEFAULT_IFACE=$(ip route show default | awk '/default/ {print $5}' | head -n 1)
read -p " Network Interface Name [$DEFAULT_IFACE]: " IFACE
IFACE=${IFACE:-$DEFAULT_IFACE}
# 3. Auto-detect IPv4 Gateway
DEFAULT_IPV4_GW=$(ip route show default | awk '/default/ {print $3}' | head -n 1)
read -p " IPv4 Gateway [$DEFAULT_IPV4_GW]: " IPV4_GW
IPV4_GW=${IPV4_GW:-$DEFAULT_IPV4_GW}
# 4. Auto-detect IPv4 Subnet
HOST_IPV4_CIDR=$(ip -o -f inet addr show $IFACE | awk '{print $4}' | head -n 1)
DEFAULT_IPV4_SUBNET=$(echo $HOST_IPV4_CIDR | awk -F. '{print $1"."$2"."$3".0/"$4}' | awk -F/ '{print $1"/"$3}')
read -p " IPv4 Subnet [$DEFAULT_IPV4_SUBNET]: " IPV4_SUBNET
IPV4_SUBNET=${IPV4_SUBNET:-$DEFAULT_IPV4_SUBNET}
# 5. Auto-detect IPv6 Subnet (Global or ULA, ignoring link-local fe80)
DEFAULT_IPV6_SUBNET=$(ip -o -f inet6 addr show $IFACE | awk '!/fe80/ {print $4}' | head -n 1 | awk -F: '{print $1":"$2":"$3":"$4"::/64"}')
if [ -z "$DEFAULT_IPV6_SUBNET" ]; then
DEFAULT_IPV6_SUBNET="Disabled"
fi
read -p " IPv6 Subnet (Leave blank or type 'Disabled' if none) [$DEFAULT_IPV6_SUBNET]: " IPV6_SUBNET
IPV6_SUBNET=${IPV6_SUBNET:-$DEFAULT_IPV6_SUBNET}
# 6. Guess IPv6 Gateway
if [[ "$IPV6_SUBNET" != "Disabled" ]] && [[ -n "$IPV6_SUBNET" ]]; then
DEFAULT_IPV6_GW=$(echo $IPV6_SUBNET | awk -F:: '{print $1"::1"}')
read -p " IPv6 Gateway [$DEFAULT_IPV6_GW]: " IPV6_GW
IPV6_GW=${IPV6_GW:-$DEFAULT_IPV6_GW}
fi
echo
echo -e "${cyan_fg_strong} _____________________________________________________________${reset}"
echo -e "${cyan_fg_strong}| OVERVIEW: Macvlan Creation Summary |${reset}"
echo -e " Network Name : ${yellow_fg_strong}${NET_NAME}${reset}"
echo -e " Interface : ${yellow_fg_strong}${IFACE}${reset}"
echo -e " IPv4 Subnet : ${yellow_fg_strong}${IPV4_SUBNET}${reset} via ${yellow_fg_strong}${IPV4_GW}${reset}"
if [[ "$IPV6_SUBNET" != "Disabled" ]] && [[ -n "$IPV6_SUBNET" ]]; then
echo -e " IPv6 Subnet : ${yellow_fg_strong}${IPV6_SUBNET}${reset} via ${yellow_fg_strong}${IPV6_GW}${reset}"
else
echo -e " IPv6 Subnet : ${red_fg_strong}Disabled${reset}"
fi
echo -e "${cyan_fg_strong} _____________________________________________________________${reset}"
echo
read -p " Does this look correct? [Y/N]: " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
log_message "WARN" "Aborted by user."
exit 0
fi
log_message "INFO" "Creating Macvlan network '${NET_NAME}'..."
if [[ "$IPV6_SUBNET" != "Disabled" ]] && [[ -n "$IPV6_SUBNET" ]]; then
docker network create -d macvlan \
--ipv6 \
--subnet="$IPV4_SUBNET" \
--gateway="$IPV4_GW" \
--subnet="$IPV6_SUBNET" \
--gateway="$IPV6_GW" \
-o parent="$IFACE" \
"$NET_NAME"
else
docker network create -d macvlan \
--subnet="$IPV4_SUBNET" \
--gateway="$IPV4_GW" \
-o parent="$IFACE" \
"$NET_NAME"
fi
if [[ $? -eq 0 ]]; then
log_message "SUCCESS" "Macvlan network '${NET_NAME}' created successfully!"
echo
log_message "INFO" "Macvlan IPAM Configuration saved in Docker:"
docker network inspect "$NET_NAME" | jq '.[0].IPAM.Config'
else
log_message "ERROR" "Failed to create Macvlan network. Please check the Docker output above."
fi
echo
chmod +x create_macvlan.sh && ./create_macvlan.sh
When configuring a Macvlan, setting up IPv4 is easy (it’s usually 192.168.1.0/24). However, when you check your IPv6 settings, you will likely see a massive list of addresses.
How do you know which one to use for the Docker Macvlan?
Unlike IPv4, a single device (like your PC or phone) usually has three different types of IPv6 addresses at the same time. You can identify them by looking at the first few letters/numbers:
Global Unicast Address (Starts with 2 or 3) - Avoid for Local DNS
2a02:f6e:c2ac::1585Link-Local Address (Starts with fe80::) - Ignore
fe80::6f25:4498:aba5Unique Local Address / ULA (Starts with fd or fc) - USE THIS ONE!!
fdaa:bbcc:ddee::1c51192.168.x.x.Now that you know you are looking for an address starting with fd or fc, here is how you find it.
Method 1: Look at your Router (Best Method)
Log into your ISP Modem or Main Router. Look for the "LAN" or "Local Network" settings. You should see a setting like:
LAN IPv6 Address: fdaa:bbcc:ddee:0000::1/64
Method 2: Use Windows Command Prompt
open CMD and type:
ipconfig /all
Look under your network adapter for an IPv6 address starting with fd:
IPv6 Address. . . . . : fdaa:bbcc:ddee:0:9474:8200:facd:1c51
Method 3: Use Linux Terminal
Open Terminal and type:
ip -o -f inet6 addr
Look for the fd address:
inet6 fdaa:bbcc:ddee:0:5a47:caff:fe76:9dd1/64 scope global
IPv6 addresses are made up of 8 blocks separated by colons (:).
In a standard home network (/64), the first 4 blocks belong to the Network, and the last 4 blocks belong to the specific device.
Take the address you found:
fdaa : bbcc : ddee : 0000 : 9474 : 8200 : facd : 1c51
fdaa:bbcc:ddee:0000fdaa:bbcc:ddee:0 (or just leave them off entirely if it's the 4th block).::/64: fdaa:bbcc:ddee::/64The final Docker Macvlan Subnet is: fdaa:bbcc:ddee::/64
The Docker Gateway (usually ends in 1): fdaa:bbcc:ddee::1
Easily deploy a structured Docker network template. Create isolated networks for management, production, and more with predefined subnets and gateways. Use this simple script to streamline network setup. Ideal for enhancing security and organization in Docker projects.
nano create_docker_networks.sh
#!/bin/bash
# Create Docker networks
# Create network: management
# VLAN ID: 99
docker network create --subnet=10.99.0.0/16 --gateway=10.99.0.1 --ip-range=10.99.0.0/16 --driver=bridge --attachable=true management
# Create network: DMZ
# VLAN ID: 80
docker network create --subnet=10.0.80.0/24 --gateway=10.0.80.1 --ip-range=10.0.80.0/24 --driver=bridge --attachable=true dmz
# Create network: security
# VLAN ID: 70
docker network create --subnet=10.0.70.0/24 --gateway=10.0.70.1 --ip-range=10.0.70.0/24 --driver=bridge --attachable=true security
# Create network: DN42
# VLAN ID: 42
# OPTIONAL!!! visit https://dn42.eu/Home
docker network create --subnet=10.42.42.0/24 --gateway=10.42.42.1 --ip-range=10.42.42.0/24 --driver=bridge --attachable=true dn42
# Create network: media
# VLAN ID: 30
docker network create --subnet=10.0.30.0/24 --gateway=10.0.30.1 --ip-range=10.0.30.0/24 --driver=bridge --attachable=true media
# Create network: GameLAN
# VLAN ID: 31
docker network create --subnet=10.0.31.0/24 --gateway=10.0.31.1 --ip-range=10.0.31.0/24 --driver=bridge --attachable=true gamelan
# Create network: PBS iSCSI
# VLAN ID: 21
# Proxmox Backup Server (PBS) to manage data transfers over iSCSI.
docker network create --subnet=10.0.21.0/24 --gateway=10.0.21.1 --ip-range=10.0.21.0/24 --driver=bridge --attachable=true pbs
# Create network: production
docker network create --subnet=10.0.1.0/24 --gateway=10.0.1.1 --ip-range=10.0.1.0/24 --driver=bridge --attachable=true production
# Create network: voip
docker network create --subnet=10.0.4.0/24 --gateway=10.0.4.1 --ip-range=10.0.4.0/24 --driver=bridge --attachable=true voip
# Create network: backup
docker network create --subnet=10.0.5.0/24 --gateway=10.0.5.1 --ip-range=10.0.5.0/24 --driver=bridge --attachable=true backup
# Create network: staging
docker network create --subnet=10.0.6.0/24 --gateway=10.0.6.1 --ip-range=10.0.6.0/24 --driver=bridge --attachable=true staging
# Create network: IoT
# VLAN ID: 101
docker network create --subnet=10.0.101.0/24 --gateway=10.0.101.1 --ip-range=10.0.101.0/24 --driver=bridge --attachable=true iot
# Create network: guest
# VLAN ID: 199
docker network create --subnet=10.0.199.0/24 --gateway=10.0.199.1 --ip-range=10.0.199.0/24 --driver=bridge --attachable=true guest
chmod +x create_docker_networks.sh && ./create_docker_networks.sh