配置ipv6
cat /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "fd00:dead:beef::/48"
}
让容器内应用也能访问ipv6
ipv6nat:
container_name: "ipv6nat"
image: "robbertkl/ipv6nat"
network_mode: "host"
privileged: true
restart: "unless-stopped"
volumes:
- "/lib/modules:/lib/modules:ro"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
创建macvlan
根据自己网络配置修改
docker network create -d macvlan --subnet=192.168.10.0/24 --gateway=192.168.10.1 --ipv6 --subnet=fe80::2e2:69ff:fe5e:aed9/64 --gateway=fe80::3abc:1ff:fe5c:3e22 -o parent=vmbr0 mvl
docker network create -d macvlan \
--subnet=192.168.10.0/24 \
--gateway=192.168.10.1 \
--ipv6 \
--subnet=fd0d:7eb5:2afd::/64 \
--gateway=fd0d:7eb5:2afd::1 \
-o parent=vmbr0 \
mvl
解决容器和宿主机通信问题
在 macvlan 模式下,出于安全考虑,默认禁止宿主机与容器的通信,也就是宿主机无法访问以及反代容器。但是局域网中的其他设备可以访问到容器。此时的网络拓扑如下图所示,可以将接入 macvlan 的容器看作一个直接接入局域网的设备(蓝色线),只是无法与宿主机(以及宿主机中使用 brigde 模式的设备)直接通信(红色线)。
配置过程
- 使用 root 用户执行以下命令,创建一个名为
macvlan-host
的网卡,连接到ovs_eth0
物理网卡上(需要根据实际情况修改网卡名字)
ip link add macvlan-host link ovs_eth0 type macvlan mode bridge
- 设置该虚拟接口的 IP,需要在 macvlan 网段内
ip addr add 192.168.1.254 dev macvlan-host
- 启动接口
ip link set macvlan-host up
- 修改路由,其中
192.168.1.201
、192.168.1.202
是容器 ip,如果有多个容器,需要分别设置
ip route add 192.168.1.201 dev macvlan-host
ip route add 192.168.1.202 dev macvlan-host
至此,即可实现宿主机到容器的访问。
修改完成后的网络拓扑类似下图。通过手动配置静态路由,将 192.168.1.201
、192.168.1.202
的路由指向新建的 macvlan-host 虚拟接口,由于该接口视作一个局域网设备可以访问到容器,因此从主机 -> 容器变得可达。(粉色线)
反过来,若是 macvlan 下的容器需要访问主机,直接访问主机 IP 也是不通的(红色线),但此时访问主机可以直接使用虚拟接口的 IP 来替代(绿色线),即在 macvlan 容器下使用 192.168.1.254:port
即可正常访问到主机服务。
持久化配置
由于该网卡和路由设置在宿主机重启后会丢失,因此需要创建开机启动脚本,以实现自动配置。
使用 Systemd
Debian 等 Linux 可以用 Systemd 管理 macvlan,该方法可以实现与 docker 服务关联,docker 启动时自动设置 macvlan,启动失败或者退出时还原修改。
群晖也可以(推荐)使用该方法,但与 Linux 有一点不同,且看后文。
具体步骤如下:
- 将以下脚本放到一个文件夹,例如
/usr/local/bin/setup_docker_macvlan.sh
,注意修改其中的变量。并赋予可执行权限:sudo chmod +x /usr/local/bin/setup_docker_macvlan.sh
sudo vim /etc/systemd/system/setup_docker_macvlan.service
创建 Systemd 服务单元文件,内容如下:
[Unit]
Description=Setup macvlan shim for docker to allow to route to host
BindsTo=docker.service
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/setup_docker_macvlan.sh start
ExecStop=/usr/local/bin/setup_docker_macvlan.sh stop
RemainAfterExit=yes
Restart=no
[Install]
WantedBy=multi-user.target
如果是群晖用户,由于群晖的 docker systemed 不是 `docker.service`,因此需要修改 `BindsTo`、`Requires` 和 `After`,根据 DSM 版本不同,服务名称可能也不同,可以通过以下方式查看:
systemctl list-units --type=service | grep docker
目前已知可能的名称有:
- `pkgctl-Docker.service`
- `pkg-ContainerManager-dockerd.service`
- `pkg-Docker-dockerd.service`
**当然也可以使用 `network.target`,当网络服务设置完成后启动,不强制依赖 docker,是一种更宽松的设置方式。**
- 启用服务单元
sudo systemctl daemon-reload
sudo systemctl enable setup_docker_macvlan.service
群晖 DSM
更简单的配置方式:群晖 DSM7 下可以在 /usr/local/etc/rc.d
中写入启动脚本,例如 vim /usr/local/etc/rc.d/macvlan.sh
,然后通过 chmod +x /usr/local/etc/rc.d/macvlan.sh
赋予可执行权限;也可以通过控制面板 - 任务计划来设置开机脚本。
脚本内容参考:
#!/bin/sh
ip link add macvlan-host link ovs_eth0 type macvlan mode bridge
ip addr add 192.168.1.254 dev macvlan-host
ip link set macvlan-host up
ip route add 192.168.1.201 dev macvlan-host
ip route add 192.168.1.202 dev macvlan-host
删除配置
sudo rm -rf /var/lib/docker/network