基于 Docker 部署 OpenWrt 及数据持久化方案
一、引言
随着容器技术的广泛应用,越来越多的人选择通过 Docker 来部署各种应用,以实现环境隔离、便于迁移等诸多优势。OpenWrt 作为一种高度灵活的嵌入式 Linux 发行版,在路由设备等领域应用广泛。将 OpenWrt 装进 Docker,并且实现所有文件的数据持久化,能让我们在享受容器便利的同时,更好地保障数据安全与持久可用。本文将详细阐述这一过程,包括如何使用备份和恢复 OverlayFS 的 upperdir 和 workdir 的方式来实现数据持久化。
二、Docker 环境搭建
如果您的宿主机尚未安装 Docker,可参考相关文档进行安装配置。以 Ubuntu 系统为例,以下是关键步骤:
-
设置 Docker 的 apt 存储库:
- 更新包索引并安装必要的包:
sudo apt-get update
sudo apt-get install ca-certificates curl
* 安装 Docker 的官方 GPG 密钥:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
* 将 Docker 的 apt 源添加到系统中:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
- 安装 Docker 相关的工具包:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- 验证 Docker 是否安装成功:
sudo docker run hello-world
三、导入 OpenWrt 镜像
- 下载镜像文件:
wget https://dl.openwrt.ai/releases/targets/bcm27xx/bcm2711/openwrt-07.26.2024-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz
- 导入镜像:
sudo docker import openwrt-07.26.2024-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz supes_openwrt
四、启动 OpenWrt 容器并进行初始配置
- 创建项目目录并定义
docker-compose.yml文件:
mkdir openWrt
cd openWrt
cat >> docker-compose.yml << EOF
version: '3.8'
services:
openwrt:
image: supes_openwrt
container_name: openwrt
command: /sbin/init
privileged: true
restart: always
networks:
openwrt-macvlan:
ipv4_address: 192.168.0.222
networks:
openwrt-macvlan:
driver: macvlan
driver_opts:
parent: eth0
ipam:
config:
- subnet: 192.168.0.0/24
gateway: 192.168.0.1
EOF
- 启动容器:
sudo docker compose up -d
- 登录容器并修改配置:
sudo docker exec -it openwrt bash
在容器内部,您可以根据需要修改 OpenWrt 的配置文件,如网络配置等。
五、数据持久化之备份和恢复 OverlayFS 的 upperdir 和 workdir
- 使用
docker inspect查看容器的文件系统信息:
docker inspect openwrt
在输出的信息中,找到Mounts部分,可以查看到容器的文件系统挂载情况,包括 upperdir 和 workdir 的路径等信息,这有助于我们准确地进行备份和恢复操作。
-
备份 upperdir 和 workdir:
- 创建备份目录:
mkdir -p /backup/openwrt_upperdir_backup
mkdir -p /backup/openwrt_workdir_backup
* 停止容器(为确保数据一致性):
docker stop openwrt
* 复制 upperdir 和 workdir:
cp -r /var/lib/docker/overlay2/<CONTAINER_ID>/upper /backup/openwrt_upperdir_backup/
cp -r /var/lib/docker/overlay2/<CONTAINER_ID>/work /backup/openwrt_workdir_backup/
这里的<CONTAINER_ID>需要替换为实际的容器 ID,您可以通过docker ps -a命令查看到已停止的容器的 ID。
-
恢复 upperdir 和 workdir:
- 创建新的容器:
sudo docker compose up -d
* 停止新容器:
docker stop openwrt
* 删除新容器原有的 upperdir 和 workdir:
rm -rf /var/lib/docker/overlay2/<NEW_CONTAINER_ID>/upper
rm -rf /var/lib/docker/overlay2/<NEW_CONTAINER_ID>/work
* 将备份的 upperdir 和 workdir 复制到新容器:
cp -r /backup/openwrt_upperdir_backup/upper /var/lib/docker/overlay2/<NEW_CONTAINER_ID>/
cp -r /backup/openwrt_workdir_backup/work /var/lib/docker/overlay2/<NEW_CONTAINER_ID>/
* 重启新容器:
docker start openwrt
六、注意事项
- 权限管理 :在进行目录挂载和文件复制等操作时,注意确保宿主机上的目录和文件权限设置正确,以便 OpenWrt 容器能够正常读写。可以使用
chmod和chown命令来修改权限和所有者。 - 数据一致性保障 :备份操作应在容器停止状态下进行,以最大限度地保证数据的一致性,避免因数据正在写入等情况导致备份数据异常。
- 定期备份策略 :建议制定并执行定期备份计划,根据您的实际使用需求和数据重要性,设置合理的备份周期,如每周或每月备份一次。可以利用宿主机的定时任务功能(如
cron)来自动执行备份脚本,以确保数据安全。
通过以上步骤,您就可以将 OpenWrt 装进 Docker,并利用备份和恢复 OverlayFS 的 upperdir 和 workdir 的方式实现数据持久化,这有助于在容器迁移、系统故障等情况下保障 OpenWrt 的数据安全与持久可用。
在备份和恢复之前都要先停止容器,备份和恢复完成后再启动.
mkdir -pv /root/openwrt/
备份
tar -z -C $( docker inspect openwrt | jq --raw-output .[0].GraphDriver.Data.UpperDir) -v -cf /root/openwrt/openwrt-backup-upper.tar.gz .
恢复
tar -C $( docker inspect openwrt | jq --raw-output .[0].GraphDriver.Data.UpperDir) -v -xf /root/openwrt/openwrt-backup-upper.tar.gz
最后贴上immortalwrt的docker镜像和容器的docker compose文件
name: openwrt
services:
openwrt:
volumes:
- "/mnt:/mnt"
- "/media:/media"
restart: always
container_name: openwrt
environment:
- "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
- "TZ=Asia/Shanghai"
stdin_open: true
tty: true
privileged: true
image: "immortalwrt/rootfs:x86-64-openwrt-24.10"
command: "/sbin/init"
networks: # 设置链接的网络
openwrt-macvlan:
ipv6_address: fe80:1::11 # - 连接的网络名
ipv4_address: 192.168.31.11 # - 容器内部 IP 地址
networks: # 定义网络
openwrt-macvlan: # 网络名称
name: "openwrt"
driver: macvlan # 指定驱动程序(macvlan: 容器直接连接宿主网络)
driver_opts:
parent: eth0 # parent 配置用于指定 macvlan 网络驱动程序的父接口
ipam: # 配置网络的 IP 地址分配策略
config:
- subnet: 192.168.31.0/24 # 子网段(ip route 查到的信息)
gateway: 192.168.31.1 # 网关(ip route 查到的信息, 其实就是主路由地址)
- subnet: fe80:1::/64 # 子网段(ip route 查到的信息)
gateway: fe80:1::1