界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

docker-networking

docker-networking

【部署与运维】Use when configuring Docker container networking — bridge networks, overlay networks, macvlan, host networking, DNS resolution between containers, published ports, network isolation, container-to-container communication, load balancing with Docker, IPv6, custom network drivers, and network troubleshooting. Part of the docker-* skill family. OS-agnost…

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: docker-networking description: Use when configuring Docker container networking — bridge networks, overlay networks, macvlan, host networking, DNS resolution between containers, published ports, network isolation, container-to-container communication, load balancing with Docker, IPv6, custom network drivers, and network troubleshooting. Part of the docker-* skill family. OS-agnostic. family: docker disambiguation: Container networking itself on any host — bridge, overlay, macvlan, DNS, port publishing. Installing and running the daemon on a distro is ubuntu-docker-host or rhel-docker-host.

Docker Networking

OS-agnostic Docker networking. For core Docker concepts, see parent skill docker-fundamentals. For OS-specific setup, see ubuntu-docker-host or rhel-docker-host.


1. Network Drivers Overview

DriverScopeDNSUse Case
bridge (default)Single hostNo auto DNSIsolated single-host containers (not recommended for multi-container)
User-defined bridgeSingle hostYesStandard multi-container apps, development, production single-host
hostSingle hostN/AMaximum network performance, no port mapping overhead
noneSingle hostNoComplete network isolation, security-sensitive workloads
macvlanSingle hostNoContainers need real LAN IPs, legacy app integration
ipvlanSingle hostNoSimilar to macvlan but works when promiscuous mode is blocked
overlayMulti-hostYesDocker Swarm services, multi-host container communication

Default Bridge vs User-Defined Bridge

FeatureDefault bridgeUser-Defined Bridge
DNS resolution by nameNo (IP only)Yes (automatic)
Network aliasesNoYes
Automatic isolationNo (all containers share it)Yes (per-network)
Connect/disconnect liveNoYes
--link supportYes (legacy)Not needed (use DNS)
ConfigurableLimitedFull (subnet, gateway, MTU)
# List all networks
docker network ls

# Inspect a network
docker network inspect bridge

# See which containers are on a network
docker network inspect mynet --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}'

2. User-Defined Bridge Networks

Creating Networks

# Basic creation
docker network create mynet

# With specific subnet and gateway
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  mynet

# With IP range (allocatable range within subnet)
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --ip-range 172.20.10.0/24 \
  --gateway 172.20.0.1 \
  mynet

# Internal network (no external/internet access)
docker network create --internal backend

# With custom MTU and other options
docker network create \
  --driver bridge \
  --opt com.docker.network.bridge.name=br-mynet \
  --opt com.docker.network.driver.mtu=9000 \
  mynet

Connecting Containers

# Run container on a specific network
docker run -d --name web --network mynet nginx:alpine

# Run with a static IP
docker run -d --name db --network mynet --ip 172.20.0.100 postgres:16-alpine

# Connect a running container to an additional network
docker network connect mynet existing-container

# Connect with a specific IP
docker network connect --ip 172.20.0.50 mynet existing-container

# Disconnect from a network
docker network disconnect mynet existing-container

DNS Resolution and Network Aliases

# Containers on user-defined bridges automatically resolve each other by name
docker network create app-net
docker run -d --name api --network app-net myapi:latest
docker run -d --name web --network app-net myweb:latest

# From 'web', 'api' resolves to the api container's IP:
# curl http://api:8080/health   <-- works automatically

# Network aliases — multiple names for one container
docker run -d --name api-v2 --network app-net --network-alias api myapi:v2

# Multiple containers with the same alias = round-robin DNS (basic load balancing)
docker run -d --name api-1 --network app-net --network-alias api myapi:latest
docker run -d --name api-2 --network app-net --network-alias api myapi:latest
docker run -d --name api-3 --network app-net --network-alias api myapi:latest
# Requests to 'api' rotate across api-1, api-2, api-3

Compose Networking

# compose.yaml — Compose creates a default network automatically
# named <project>_default. All services join it.
services:
  web:
    image: nginx:alpine
    networks:
      - frontend
      - backend
  api:
    image: myapi:latest
    networks:
      backend:
        aliases:
          - api-service
  db:
    image: postgres:16-alpine
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true    # no external access
    ipam:
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.0.1

3. Host Networking

# Container shares the host's network namespace — no port mapping needed
docker run -d --network host nginx:alpine
# Nginx is now directly on host port 80

# Check — container has no separate IP
docker inspect --format '{{.NetworkSettings.IPAddress}}' <container>
# Returns empty string — it uses the host's IP

When to Use Host Networking

ScenarioRecommendation
Maximum network performanceUse host — eliminates NAT overhead
Application binds to many dynamic portsUse host — avoids mapping hundreds of ports
Network monitoring / packet captureUse host — sees all host traffic
Standard web appsUse bridge — isolation is more important than marginal performance

Limitations

  • No port mapping (-p is ignored) — container binds directly to host ports
  • No network isolation — container sees all host network interfaces
  • Port conflicts with host services or other host-mode containers
  • Does not work on Docker Desktop for Mac/Windows (runs inside a VM)
  • Cannot connect to user-defined bridge networks simultaneously

4. Macvlan Networks

Macvlan gives each container its own MAC address and a real IP on the physical network. Other devices on the LAN can reach containers directly.

Basic Macvlan

# Enable promiscuous mode on parent interface
sudo ip link set eth0 promisc on

# Create macvlan network
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macnet

# Run container with a LAN IP
docker run -d --name web --network macnet --ip 192.168.1.50 nginx:alpine
# Container is reachable at 192.168.1.50 from any device on the LAN

802.1q Trunk Mode (VLAN Tagging)

# Create macvlan on a VLAN-tagged sub-interface
docker network create -d macvlan \
  --subnet=10.10.20.0/24 \
  --gateway=10.10.20.1 \
  -o parent=eth0.20 \
  macvlan20

docker network create -d macvlan \
  --subnet=10.10.30.0/24 \
  --gateway=10.10.30.1 \
  -o parent=eth0.30 \
  macvlan30

# Containers on different VLANs
docker run -d --name web --network macvlan20 --ip 10.10.20.10 nginx
docker run -d --name db --network macvlan30 --ip 10.10.30.10 postgres:16

Host-to-Macvlan Container Communication

The host cannot directly communicate with its own macvlan containers (by design — macvlan filters traffic between parent and sub-interfaces). Workaround:

# Create a macvlan sub-interface on the host
sudo ip link add macvlan-shim link eth0 type macvlan mode bridge
sudo ip addr add 192.168.1.200/32 dev macvlan-shim
sudo ip link set macvlan-shim up

# Add route to container subnet via the shim
sudo ip route add 192.168.1.50/32 dev macvlan-shim

Ipvlan (Alternative)

# L2 mode — like macvlan but shares parent MAC (no promiscuous mode needed)
docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  -o ipvlan_mode=l2 \
  ipvlan-net

# L3 mode — routing-based, no broadcast, better for large-scale
docker network create -d ipvlan \
  --subnet=10.10.0.0/24 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  ipvlan-l3

5. Overlay Networks

Overlay networks span multiple Docker hosts using VXLAN encapsulation. Requires Docker Swarm or an external key-value store.

Swarm Overlay

# Initialize Swarm (required for overlay)
docker swarm init --advertise-addr 10.0.0.1

# Create overlay network
docker network create -d overlay myoverlay

# Create service on overlay
docker service create --name web --network myoverlay --replicas 3 nginx:alpine

# Encrypted overlay (data plane encryption — AES-GCM)
docker network create -d overlay --opt encrypted myoverlay-enc

Attachable Overlay (Standalone Containers)

# By default, overlay networks are only for Swarm services.
# --attachable allows standalone containers to join.
docker network create -d overlay --attachable shared-overlay

# Standalone container joins the overlay
docker run -d --name standalone-app --network shared-overlay myapp:latest

Overlay with Custom Subnet

docker network create -d overlay \
  --subnet=10.100.0.0/16 \
  --gateway=10.100.0.1 \
  --opt com.docker.network.driver.mtu=1450 \
  production-overlay

Ingress Network

# The default 'ingress' overlay handles Swarm routing mesh.
# Published ports on any node route to the correct container.
docker service create --name web -p 80:80 --replicas 3 nginx:alpine
# Port 80 on ANY Swarm node reaches one of the 3 replicas.

# Bypass routing mesh (only listen on nodes running the task)
docker service create --name web \
  --publish mode=host,target=80,published=80 \
  --mode global \
  nginx:alpine

6. DNS and Service Discovery

Embedded DNS Server

Docker runs a built-in DNS server at 127.0.0.11 for all user-defined networks.

# Check DNS config inside a container
docker exec mycontainer cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:0

# Test name resolution
docker exec mycontainer nslookup api
docker exec mycontainer getent hosts api

DNS Resolution Rules

What ResolvesWhereHow
Container nameSame user-defined networkAutomatic
Network aliasSame user-defined networkAutomatic
Service nameSwarm overlayAutomatic (VIP or DNSRR)
Container nameDefault bridgeDoes NOT resolve
External hostnamesAll networksForwarded to host DNS

Custom DNS Configuration

# Set custom DNS servers for a container
docker run -d --name web \
  --dns 8.8.8.8 \
  --dns 8.8.4.4 \
  nginx:alpine

# Set DNS search domain
docker run -d --name web \
  --dns-search example.com \
  nginx:alpine
# Allows resolving 'api' as 'api.example.com'

# Set custom hostname
docker run -d --name web \
  --hostname web.example.com \
  nginx:alpine

# Add /etc/hosts entries
docker run -d --name web \
  --add-host db:10.0.0.5 \
  --add-host cache:10.0.0.6 \
  nginx:alpine

# host-gateway — resolve to host's IP (Docker 20.10+)
docker run -d --name web \
  --add-host host.docker.internal:host-gateway \
  nginx:alpine

Daemon-Level DNS Config

// /etc/docker/daemon.json
{
  "dns": ["8.8.8.8", "8.8.4.4"],
  "dns-search": ["example.com"],
  "dns-opts": ["timeout:2", "attempts:3"]
}

Swarm Service Discovery Modes

# VIP mode (default) — single virtual IP, Docker load-balances
docker service create --name api \
  --endpoint-mode vip \
  --replicas 3 \
  myapi:latest
# 'api' resolves to one VIP; Docker handles round-robin behind it

# DNSRR mode — DNS returns all task IPs, client picks
docker service create --name api \
  --endpoint-mode dnsrr \
  --replicas 3 \
  myapi:latest
# 'api' resolves to 3 IPs; client or external LB picks

7. Port Publishing

Basic Port Mapping

# Map host port 8080 to container port 80
docker run -d -p 8080:80 nginx:alpine

# Map to localhost only (not exposed externally)
docker run -d -p 127.0.0.1:8080:80 nginx:alpine

# Map to specific host interface
docker run -d -p 10.0.0.5:8080:80 nginx:alpine

# Container port only (random host port assigned)
docker run -d -p 80 nginx:alpine

# Check assigned port
docker port <container>

UDP and Protocol-Specific

# UDP port
docker run -d -p 5514:514/udp syslog-ng

# TCP and UDP on same port
docker run -d -p 53:53/tcp -p 53:53/udp bind9

# SCTP (Docker 20.10+)
docker run -d -p 3868:3868/sctp diameter-server

Port Ranges

# Map a range of ports
docker run -d -p 8000-8010:8000-8010 myapp

# Publish all EXPOSEd ports (random host ports)
docker run -d --publish-all myapp
docker run -d -P myapp    # shorthand

Compose Port Syntax

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"                    # host:container
      - "443:443"
      - "127.0.0.1:8080:80"       # localhost only
      - "9090-9095:9090-9095"      # range
      - "514:514/udp"              # UDP
      - target: 80                 # long syntax
        published: 8080
        protocol: tcp
        mode: host                 # Swarm: bypass routing mesh

Default Bind Address

// /etc/docker/daemon.json — change default bind from 0.0.0.0
{
  "ip": "127.0.0.1"
}
// Now -p 8080:80 binds to 127.0.0.1:8080 by default

8. Network Isolation

Internal Networks

# No outbound internet access — containers can only talk to each other
docker network create --internal isolated-net

docker run -d --name db --network isolated-net postgres:16-alpine
docker run -d --name cache --network isolated-net redis:7-alpine
# db and cache can reach each other, but neither can reach the internet

Network Segmentation Pattern (Frontend / Backend)

# compose.yaml — classic three-tier isolation
services:
  proxy:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - frontend

  api:
    image: myapi:latest
    networks:
      - frontend      # reachable by proxy
      - backend        # can reach db

  db:
    image: postgres:16-alpine
    networks:
      - backend        # only reachable by api

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true     # no internet access for db

Result: proxy cannot reach db directly. api bridges the two networks. db has no internet access.

Inter-Container Communication (ICC)

// /etc/docker/daemon.json — disable ICC on default bridge
{
  "icc": false
}
// Containers on default bridge cannot communicate unless explicitly --link'd
// User-defined networks are unaffected (use network isolation instead)

iptables and Docker

# Docker manages iptables rules automatically. Key chains:
# DOCKER-USER — insert custom rules here (survives Docker restarts)
# DOCKER — managed by Docker (do not modify)
# DOCKER-ISOLATION-STAGE-1/2 — network isolation

# Block external access to a published port (except from trusted IP)
sudo iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 \
  ! -s 10.0.0.0/8 -j DROP

# Block container-to-container across networks
sudo iptables -I DOCKER-USER -i br-abc123 -o br-def456 -j DROP

# Allow established/related connections
sudo iptables -I DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Persist rules
sudo iptables-save > /etc/iptables/rules.v4

Disable Docker's iptables Management

// /etc/docker/daemon.json — NOT recommended unless using external firewall
{
  "iptables": false
}
// You must then manually configure all NAT and forwarding rules

9. Container-to-Container Communication

Same Network (By Name)

# Containers on the same user-defined network resolve each other by name
docker network create app-net
docker run -d --name api --network app-net myapi:latest
docker run -d --name web --network app-net myweb:latest

# From web container:
docker exec web curl http://api:8080/health    # resolves 'api' via DNS
docker exec web ping api                        # also works

Cross-Network Communication

# Container on two networks can bridge communication
docker network create frontend
docker network create backend

docker run -d --name api --network frontend myapi:latest
docker network connect backend api
# 'api' is now on both frontend and backend

docker run -d --name web --network frontend myweb:latest
docker run -d --name db --network backend postgres:16-alpine

# web -> api (via frontend) -> db (via backend)
# web cannot reach db directly

Link (Legacy — Do Not Use)

# --link is deprecated. Do NOT use in new projects.
# docker run --link db:database myapp    # legacy
# Instead, use user-defined networks (automatic DNS, no ordering dependency)

Container-to-Host Communication

# From a container, reach the host machine
# Docker Desktop: host.docker.internal (built-in)
# Linux Docker Engine 20.10+:
docker run --add-host host.docker.internal:host-gateway myapp

# Or use the docker0 bridge gateway IP (usually 172.17.0.1)
docker exec mycontainer ip route | grep default

10. IPv6

Enable IPv6

// /etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80",
  "ip6tables": true,
  "experimental": true
}
# Restart Docker after editing daemon.json
sudo systemctl restart docker

Dual-Stack User-Defined Network

# Create a dual-stack network
docker network create \
  --ipv6 \
  --subnet 172.20.0.0/16 \
  --subnet fd00:dead:beef::/48 \
  dualstack-net

# Run container — gets both IPv4 and IPv6 addresses
docker run -d --name web --network dualstack-net nginx:alpine

# Verify
docker inspect web --format '{{range .NetworkSettings.Networks}}IPv4: {{.IPAddress}} IPv6: {{.GlobalIPv6Address}}{{end}}'

IPv6 Port Publishing

# Publish on IPv6
docker run -d -p "[::1]:8080:80" nginx:alpine        # IPv6 localhost only
docker run -d -p "[::]:8080:80" nginx:alpine          # all IPv6 interfaces

Compose IPv6

networks:
  dualstack:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 172.20.0.0/16
        - subnet: fd00:dead:beef::/48

11. Network Troubleshooting

Inspecting Networks and Container IPs

# List all networks
docker network ls

# Detailed network info (connected containers, subnet, gateway)
docker network inspect mynet

# Get container's IP address
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>

# Get all network details for a container
docker inspect -f '{{json .NetworkSettings.Networks}}' <container> | jq

# Which networks is a container on?
docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' <container>

# List containers on a specific network
docker network inspect mynet -f '{{range .Containers}}{{.Name}}: {{.IPv4Address}}{{"\n"}}{{end}}'

DNS Debugging

# Check resolv.conf inside container
docker exec <container> cat /etc/resolv.conf

# Test name resolution
docker exec <container> nslookup api
docker exec <container> getent hosts api
docker exec <container> dig api    # if dig is installed

# Check /etc/hosts
docker exec <container> cat /etc/hosts

# Verify embedded DNS is working
docker exec <container> nslookup google.com 127.0.0.11

# Common DNS issue: wrong network
docker exec <container> nslookup other-container
# Fails? Check they are on the same user-defined network.

Connectivity Testing

# Ping between containers
docker exec web ping -c 3 api

# Test TCP connectivity
docker exec web nc -zv api 8080

# HTTP test
docker exec web curl -s -o /dev/null -w "%{http_code}" http://api:8080/health

# Test from host to container
curl http://localhost:8080/health

# Check published port mapping
docker port <container>

Packet Capture (tcpdump)

# Install tcpdump in a running container (if not present)
docker exec -u root <container> apt-get update && apt-get install -y tcpdump
docker exec -u root <container> apk add tcpdump     # Alpine

# Capture traffic
docker exec <container> tcpdump -i eth0 -n port 80

# Capture and save to host
docker exec <container> tcpdump -i eth0 -w - port 80 > capture.pcap

Netshoot Sidecar (Recommended)

The nicolaka/netshoot image includes every network debugging tool — use it as a sidecar without modifying your containers.

# Attach to a container's network namespace
docker run -it --rm \
  --net container:<target-container> \
  nicolaka/netshoot

# Inside netshoot, you now have:
# tcpdump, curl, dig, nslookup, nmap, iperf3, mtr,
# netstat, ss, ip, iftop, drill, traceroute, and more

# Attach to a container's network AND PID namespace
docker run -it --rm \
  --net container:<target-container> \
  --pid container:<target-container> \
  nicolaka/netshoot

# Attach to host network
docker run -it --rm --net host nicolaka/netshoot

# Capture traffic on a specific network
docker run -it --rm --net mynet nicolaka/netshoot tcpdump -i eth0

iptables Debugging

# View Docker-managed iptables rules
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v

# Check DOCKER-USER chain (custom rules)
sudo iptables -L DOCKER-USER -n -v

# Check network isolation rules
sudo iptables -L DOCKER-ISOLATION-STAGE-1 -n -v

# Watch rule hit counters in real-time
watch -n 1 'sudo iptables -L DOCKER-USER -n -v'

Common Issues and Fixes

ProblemCauseFix
Container can't resolve another by nameOn default bridge networkUse a user-defined bridge network
curl: (6) Could not resolve hostContainers on different networksConnect both to the same network
Port published but not reachableFirewall blocking on hostCheck ufw/firewalld/iptables rules
Port published but wrong interfaceBound to 0.0.0.0, expected specific IPUse -p 10.0.0.5:8080:80
Container can't reach internetOn --internal networkIntended. Move to non-internal network if access needed
Container can't reach host servicesNo route to host IPUse --add-host host.docker.internal:host-gateway
Macvlan container unreachable from hostMacvlan design (host-to-own-macvlan blocked)Create macvlan shim interface on host (see section 4)
DNS resolution slow (5s delay)IPv6 DNS query failing, falling back to IPv4Set --dns-opt single-request-reopen or fix IPv6 config
Overlay network not workingSwarm not initialized or ports blockedInit Swarm; open TCP 2377, TCP/UDP 7946, UDP 4789
Containers on same network can't communicateicc=false in daemon.jsonSet icc: true or use user-defined networks (unaffected)

Network Performance Testing

# iperf3 between containers
docker run -d --name iperf-server --network mynet networkstatic/iperf3 -s
docker run -it --rm --network mynet networkstatic/iperf3 -c iperf-server

# Measure latency
docker exec web ping -c 100 api | tail -1
# rtt min/avg/max/mdev = 0.030/0.045/0.120/0.015 ms

# Compare bridge vs host network performance
docker run -it --rm --network bridge networkstatic/iperf3 -c <host-ip>
docker run -it --rm --network host networkstatic/iperf3 -c <host-ip>

Quick Reference: Network Create Options

docker network create [OPTIONS] NETWORK

  --driver, -d        Driver (bridge, overlay, macvlan, ipvlan, none)
  --subnet            Subnet in CIDR format (e.g., 172.20.0.0/16)
  --ip-range          Allocatable IP range within subnet
  --gateway           Gateway for the subnet
  --ipv6              Enable IPv6
  --internal          No external connectivity
  --attachable        Allow standalone containers (overlay only)
  --opt, -o           Driver-specific options
  --label             Metadata labels


Anti-Patterns

Anti-PatternWhy It FailsCorrect Approach
Using the default bridge network for multi-container appsNo DNS resolution between containers; must use IP addresses; no network isolationCreate custom bridge networks; containers resolve each other by service name automatically
Publishing all ports to host with -p 0.0.0.0:port:portExposes services to all network interfaces including public; bypasses host firewall on some setupsBind to specific interface: -p 127.0.0.1:port:port for local-only; use reverse proxy for external access
Using host networking mode for everythingNo network isolation; port conflicts between containers; container can access all host servicesUse host mode only when performance-critical (raw socket, multicast); default to bridge networks
Not creating network aliases for service discoveryContainers reference each other by container name which changes; refactoring breaks connectivityUse --network-alias or Compose service names for stable DNS; decouple container names from service identity
Hardcoding container IP addressesDocker assigns IPs dynamically; IPs change on restart; breaks after any container recreationUse DNS-based service discovery; never reference container IPs in configuration

Related Skills

TopicSkill
Core Docker concepts, CLI, Dockerfiledocker-fundamentals
Compose, cross-platform, AD mappingdocker-admin
Volumes, bind mounts, storage driversdocker-storage
Image scanning, rootless, CIS benchmarkdocker-security
CI/CD, multi-platform builds, registriesdocker-cicd
Advanced Compose patternsdocker-compose-patterns
Docker on Ubuntu 24.04ubuntu-docker-host
Podman/Docker on RHEL 9rhel-docker-host
我的收藏