基于 Docker 部署 OpenWrt 及数据持久化方案,通过备份upperdir和workdir实现。

495 阅读2分钟

juejin.cn/post/742005…

基于 Docker 部署 OpenWrt 及数据持久化方案

一、引言

随着容器技术的广泛应用,越来越多的人选择通过 Docker 来部署各种应用,以实现环境隔离、便于迁移等诸多优势。OpenWrt 作为一种高度灵活的嵌入式 Linux 发行版,在路由设备等领域应用广泛。将 OpenWrt 装进 Docker,并且实现所有文件的数据持久化,能让我们在享受容器便利的同时,更好地保障数据安全与持久可用。本文将详细阐述这一过程,包括如何使用备份和恢复 OverlayFS 的 upperdir 和 workdir 的方式来实现数据持久化。

二、Docker 环境搭建

如果您的宿主机尚未安装 Docker,可参考相关文档进行安装配置。以 Ubuntu 系统为例,以下是关键步骤:

  1. 设置 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
  1. 安装 Docker 相关的工具包:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 验证 Docker 是否安装成功:
sudo docker run hello-world

三、导入 OpenWrt 镜像

  1. 下载镜像文件:
wget https://dl.openwrt.ai/releases/targets/bcm27xx/bcm2711/openwrt-07.26.2024-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz
  1. 导入镜像:
sudo docker import openwrt-07.26.2024-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz supes_openwrt

四、启动 OpenWrt 容器并进行初始配置

  1. 创建项目目录并定义 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
  1. 启动容器:
sudo docker compose up -d
  1. 登录容器并修改配置:
sudo docker exec -it openwrt bash

在容器内部,您可以根据需要修改 OpenWrt 的配置文件,如网络配置等。

五、数据持久化之备份和恢复 OverlayFS 的 upperdir 和 workdir

  1. 使用docker inspect查看容器的文件系统信息:
docker inspect openwrt

在输出的信息中,找到Mounts部分,可以查看到容器的文件系统挂载情况,包括 upperdir 和 workdir 的路径等信息,这有助于我们准确地进行备份和恢复操作。

  1. 备份 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。

  1. 恢复 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

六、注意事项

  1. 权限管理 :在进行目录挂载和文件复制等操作时,注意确保宿主机上的目录和文件权限设置正确,以便 OpenWrt 容器能够正常读写。可以使用chmodchown命令来修改权限和所有者。
  2. 数据一致性保障 :备份操作应在容器停止状态下进行,以最大限度地保证数据的一致性,避免因数据正在写入等情况导致备份数据异常。
  3. 定期备份策略 :建议制定并执行定期备份计划,根据您的实际使用需求和数据重要性,设置合理的备份周期,如每周或每月备份一次。可以利用宿主机的定时任务功能(如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