尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

1Panel服务离线迁移实战:Docker镜像与数据完整搬迁至Ubuntu 22.04

1Panel服务离线迁移实战:Docker镜像与数据完整搬迁至Ubuntu 22.04 接手过一次“把 1Panel 管理的所有服务迁移到一台离线 Ubuntu 22.04 新服务器”之后你会发现这类迁移根本不是“拷贝文件、跑起来”这么简单。尤其目标机器在隔离内网里没有外网、不能在线拉镜像连 Docker 和 1Panel 本身都得想办法离线装好后面还有一堆数据一致性、面板配置、旧 IP 残留的问题要处理。这篇文章把我实际操作中踩过的坑、验证过的步骤完整记下来覆盖四个关键环节离线环境准备Ubuntu 22.04 Docker 1Panel、源服务器备份镜像/数据/配置、新服务器恢复面板/容器/数据库、以及迁移后的常见问题排查。适合正在做同类迁移、而且目标环境是离线内网的人直接参考。1. 迁移前先想清楚服务清单与方案选型1.1 盘点源服务器上的服务动手之前不要急着打包先在源服务器上把“家底”盘清楚。我习惯同时从 1Panel 面板和命令行两个视角去核对避免漏掉那些不在面板里、但实际还在跑的老容器。打开 1Panel 面板的“容器”页面把每一个容器名称、镜像、端口、挂载目录、重启策略截个图或导出清单。再登录 SSH 执行一遍 docker ps把面板可能漏掉的容器也捞出来。我常用的盘点命令组合# 查看所有运行中容器 docker ps --format table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}} # 查看容器挂载卷和宿主机目录 docker inspect $(docker ps -q) --format {{.Name}} - {{range .Mounts}}{{.Source}}:{{.Destination}} {{end}} # 查看宿主机磁盘占用 df -h把服务信息整理成一张表格后面每一步都对照它操作服务名称镜像容器内端口宿主机数据目录依赖的数据库备注openrestyopenresty:1.2580/443/opt/1panel/apps/openresty/...MySQL1Panel 内置mysql-8.0mysql:8.03306/opt/1panel/apps/mysql/...自身1Panel 内置redisredis:7.06379/opt/1panel/apps/redis/...无1Panel 内置业务 Java 服务registry.local/app:2.18080/data/appMySQL自定义挂载业务前端nginx:1.248081/opt/1panel/www/sites/xxx无1Panel 网站这张表不光是给自己看的更是为了判断“哪些目录必须完整拷走”“哪些镜像必须 save”“数据库之间有没有互调关系”。1.2 明确离线服务器的硬件与网络要求新服务器虽然离线但基础要求不能糊弄。我的建议是CPU 核数和内存不低于源服务器磁盘预留至少是源数据总量的 1.5 倍因为 docker 镜像包、数据 tar 包、解压后的副本在同一台机器上都会占空间。系统盘单独分出来建议 50GB 以上/opt 和 /var/lib/docker 所在的数据盘按源服务器实际使用情况分配。如果源服务器数据总量 200GB新服务器数据盘至少给 300GB。网络方面注意三点给新服务器配置固定的内网 IP不要用 DHCP尤其是要跟源服务器保持同一网段或互相能连通方便 rsync/scp 传数据。新服务器的 hostname 如果会被业务服务内部调用最好和源服务器保持一致如果服务之间都用 IP 互调那 IP 也得保持或统一改配置。离线环境要自己维护时间同步。装上 chrony配一台内网 NTP 服务器否则数据库日志、接口鉴权的时间错乱会让你查问题查到怀疑人生。1.3 迁移方案选型为什么我选择“镜像导出 数据卷拷贝 compose 还原”针对 1Panel 环境的迁移主流有三种做法我这里直接说结论方案 A在新机器上重新部署每个应用再手动配置。风险最大。1Panel 里的服务往往有大量环境变量、自定义网络、依赖关系靠人力重新建环境很容易漏参数而且特别耗时。方案 B整机或者整块磁盘克隆。在硬件差异较大的情况下驱动、分区表、系统配置都会出问题而且克隆出来还带着源机器的 hostname、IP、启动项反而不干净。方案 Cdocker save/load 做镜像迁移加上数据目录冷拷贝最后用 docker compose 恢复服务。这套方案最贴合 1Panel 的架构因为 1Panel 管理的应用本身就是标准 Docker Compose 项目只要目录结构正确迁移后 1Panel 依然能正常纳管新环境里的容器。方案 C 的整体思路是“镜像搬过来、数据搬过来、配置搬过来最后原样起服务”而不是“在新机器上重装一个同款服务”。这套思路的核心前提是1Panel 应用编排文件、数据目录结构没有发生跨版本冲突。所以新环境安装的 1Panel 版本尽量和源服务器保持一致小版本差异通常无碍但大版本跨代升级建议先问官方支持矩阵。2. 离线环境准备装好 Ubuntu 22.04、Docker 与 1Panel2.1 Ubuntu 22.04 系统安装与初始化Ubuntu 22.04 的安装这里不赘述但离线服务器有两点要特别留心。第一安装时断网也没关系选好“最小安装”即可安装源不用纠结。第二分区时建议单独挂一个数据盘到 /data或者根据你的习惯挂到 /opt后续把所有服务数据、备份包都放数据盘避免系统盘塞满导致整机卡死。系统装完先做基础初始化# 设置静态IP编辑 /etc/netplan/00-installer-config.yaml # 注意 Ubuntu 22.04 使用 netplan 管理网络 network: ethernets: eno1: dhcp4: false addresses: [192.168.10.20/24] routes: - to: default via: 192.168.10.1 nameservers: addresses: [192.168.10.2] version: 2应用 netplan 配置后确认 SSH 可以登录然后关闭可能干扰容器端口的外部防火墙管理策略。Ubuntu 默认没有启用 ufw 就不需要管但如果启用了要放行 22、80、443、面板端口和相关业务端口。2.2 在联网机器上准备 Docker 离线安装包离线环境装 Docker 最省心的方式找一台和离线服务器同 CPU 架构通常是 amd64、同系统版本Ubuntu 22.04的联网机器先把 Docker 相关的 deb 包全部下载好再传到离线机器上安装。在联网机器上执行# 添加 Docker 官方源这里只讲命令具体源地址以官方文档为准 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 下载 docker 及相关组件 apt download docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-buildx-plugin下载完成后把这些 .deb 文件传到离线服务器的临时目录然后执行dpkg -i *.deb # 如果报依赖缺失用下面的命令检查缺什么 dpkg -i --force-all docker-ce_*.deb如果依赖仍然报错多半是缺少某些基础依赖包回到联网机器上继续 apt download 补齐即可。装完后配置 Docker 守护进程我的建议是至少设置好>mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 50m, max-file: 5 }, storage-driver: overlay2 } EOF systemctl daemon-reload systemctl enable --now docker docker info注意>1pctl version或者面板首页的“系统”里能看到版本号。然后在联网机器上下载对应版本的 1Panel 离线安装包官方发布页提供离线包解压后传到新服务器。离线安装的核心是“先装 Docker再装 1Panel”并且安装脚本指定离线模式# 解压离线包后进入目录执行安装脚本以官方包内脚本为准 ./install.sh安装过程中会让你设置面板端口、用户名、密码。端口尽量和源服务器保持相同省得后面 Nginx 反代或者浏览器书签都要改。1Panel 安装完成后先不要急着启动任何应用因为此时面板还是“干净”的容器数据还没恢复。我们需要在恢复数据之后再让面板接管容器。这里有一个经验安装完面板后先把面板服务停掉再恢复数据最后启动面板能避免面板在启动时初始化出空的数据库或空的数据目录把原有数据顶掉。3. 源服务器全量备份与镜像导出3.1 数据库数据备份数据库备份我强烈建议做“逻辑备份”而不是直接把数据文件拷贝走。逻辑备份的通用性更好能跨小版本恢复直接拷贝 ibdata1、binlog 这类物理文件一旦 MySQL 版本有差异或者配置不同恢复时很容易报错。以 1Panel 内置的 MySQL 为例先找到管理员账号和密码在 1Panel 应用详情里可以看到或查看 /opt/1panel/apps/mysql/.../docker-compose.yml 中的环境变量然后执行全量逻辑备份docker exec mysql-8.0 mysqldump \ --single-transaction \ --set-gtid-purgedOFF \ --all-databases \ -uroot -p你的密码 /data/backup/mysql_all.sql如果还有 PostgreSQL 或其他数据库一并导出docker exec postgresql pg_dumpall -U postgres /data/backup/pg_all.sqlRedis 相对简单等数据落盘后拷贝 RDB 文件即可docker exec redis redis-cli BGSAVE sleep 3 # 找到 redis 数据目录拷贝 dump.rdb导出后对备份文件做一个 md5 校验记录尺寸方便传输后比对。3.2 Docker 镜像导出源服务器上可能有很多镜像手动一个个 docker save 太费劲建议写个脚本循环处理。#!/bin/bash mkdir -p /data/backup/images docker images --format {{.Repository}}:{{.Tag}} | grep -v none /data/backup/image-list.txt while read img; do name$(echo $img | tr /: __) docker save $img | gzip /data/backup/images/$name.tar.gz done /data/backup/image-list.txt为什么用 gzip 压缩因为镜像 tar 包往往是纯数据压缩率可观离线传输时能省不少时间。等全部导出后用 docker images 的清单和导出的文件一一对应确认没有漏。另外1Panel 应用编排的 compose 文件也要完整带走。默认在 /opt/1panel/apps 目录下每个应用一个文件夹里面是 docker-compose.yml、.env、conf 等配置。这个目录是整个迁移能否被 1Panel 重新纳管的关键。tar czf /data/backup/1panel-apps.tar.gz -C /opt/1panel apps3.3 数据卷与持久化目录拷贝1Panel 默认把内置应用的数据放在 /opt/1panel/apps 下比如 MySQL 的数据目录在 /opt/1panel/apps/mysql/mysql-8.0/dataRedis 在 /opt/1panel/apps/redis/redis-7.0/data。网站站点文件通常在 /opt/1panel/www/sites 下。如果源服务器上还有自己手动部署的容器数据卷可能在 /var/lib/docker/volumes 或被 bind mount 到自定义目录。用之前盘点得到的挂载信息把每个服务对应的宿主机数据目录完整打包。推荐在源服务器上按目录分批打包cd /opt/1panel tar czf /data/backup/1panel-data.tar.gz apps www # 自定义数据目录单独打包 tar czf /data/backup/biz-data.tar.gz -C /data app打包完成后用 rsync 把备份文件传到新服务器。rsync 支持断点续传比 scp 更适合大文件传输rsync -avP --bwlimit50000 /data/backup/ root192.168.10.20:/data/restore/带宽限制参数可以根据网络情况调整避免把业务带宽全抢走。备份文件一定要做一次完整性和大小校验我建议在源服务器和目标服务器分别生成 md5 清单再对比。4. 新服务器恢复从镜像到数据再到面板4.1 Docker 镜像导入把镜像包传到新服务器后先解压再导入。注意 Docker 可以直接 load gzip 压缩的 tarcd /data/restore/images for f in *.tar.gz; do docker load $f done导入完成后对照 /data/restore/image-list.txt 检查镜像是否齐全。docker images | grep -E REPOSITORY|你的镜像名如果发现镜像名称变了或者 tag 变成 不要急着用容器先 docker tag 修正。某些老镜像在导出导入后 registry 路径会丢尤其是私有仓库里的镜像这时候用 compose 文件中的 image 字段反查并手动打 tag 即可。4.2 恢复数据卷与持久化目录这一步是我整个迁移中最看重的一步目录必须先还原再启动容器。如果目录不存在时容器先启动了Docker 会按 bind mount 的路径自动创建一个空目录然后把容器里原本的文件“映射”到空目录里原有数据就像被覆盖了一样命好的还能在容器层找到命不好直接就没。所以在导入镜像之后先把应用程序的数据目录解压到对应位置cd /opt/1panel tar xzf /data/restore/1panel-data.tar.gz解压后检查目录属主。容器内进程通常以特定 UID 运行例如 MySQL 镜像默认以 mysql 用户运行UID 可能是 999。如果目录权限不对容器起来后会报“Permission denied”或者直接崩溃。# 查看原容器挂载目录所归属的 UID ls -ln /opt/1panel/apps/mysql/mysql-8.0/data # 如果新环境解压后属主不对按原 UID 重新 chown chown -R 999:999 /opt/1panel/apps/mysql/mysql-8.0/data由于我前面把 Docker># 如果在前面没有完整备份 apps/www需要单独备份 db 和 conf cd /opt/1panel tar czf /data/backup/panel-conf.tar.gz db conf # 新服务器上解压覆盖 tar xzf /data/restore/panel-conf.tar.gz覆盖的时候注意先停掉 1Panel 服务systemctl stop 1panel docker stop $(docker ps -q) # 覆盖数据 systemctl start 1panel如果覆盖后还是报“未设置服务器地址”大概率是面板设置表里存储的服务器地址还是旧 IP。1Panel 的表结构和字段在不同版本可能有差异但常见的存储位置是面板数据库的 system_setting 表字段类似 ServerAddress、ServerIP。修改前先备份数据库然后执行sqlite3 /opt/1panel/db/1Panel.db select key,value from system_setting where key like %Server%; sqlite3 /opt/1panel/db/1Panel.db update system_setting set valuehttp://192.168.10.20:面板端口 where keyServerAddress;注意1Panel 的面板数据库可能是 SQLite也可能是内置 MySQL取决于版本。如果是 MySQL就通过 mysql 命令行去修改。不确定时先查 /opt/1panel/conf/app.yaml 中 database 段配置别盲目操作。4.4 容器应用启动与配置修正1Panel 数据恢复后面板会识别到之前安装过的应用但容器是否已经拉起取决于 docker compose 的状态。在 1Panel 面板的“容器”页面如果看不到容器可以手动去对应应用目录执行 compose up。我的建议是按依赖顺序启动先数据库和缓存MySQL、Redis、PostgreSQL再中间件OpenResty、Nginx最后业务应用。cd /opt/1panel/apps/mysql/mysql-8.0 docker compose up -d cd /opt/1panel/apps/redis/redis-7.0 docker compose up -d每个容器起来后立刻看日志docker logs -f --tail 100 mysql-8.0如果容器起来后立刻退出大概率是数据目录权限问题、配置文件路径不对、或者解压后目录层级多了一层。这时候先看日志再 docker inspect 容器的挂载点不要盲目重启。业务应用如果有 .env 文件要重点检查里面是否写了旧服务器 IP。比如数据库连接地址从 192.168.10.10 改到 192.168.10.20否则业务容器虽然起来了数据库连接还是会失败。1Panel 的网站配置在 /opt/1panel/apps/openresty/openresty/conf/conf.d 下如果你迁移后域名和端口没变配置文件通常不用改但如果新服务器 IP 变了DNS 解析需要切到新 IP这个属于外部变更别漏掉。4.5 数据库恢复与业务验证容器和面板都恢复后开始导入数据库。以 MySQL 为例docker exec -i mysql-8.0 mysql -uroot -p密码 /data/restore/mysql_all.sql导入完成先做基础校验docker exec mysql-8.0 mysql -uroot -p密码 -e show databases; # 逐个业务库检查表数量 docker exec mysql-8.0 mysql -uroot -p密码 -e use 业务库; show tables;Redis 的 RDB 文件拷回数据目录后重启容器即可自动加载。检查一下 Redis 是否正常响应、密码是否还是老配置。业务验证不能只验证数据库还要模拟真实用户的访问路径访问前端站点确认页面正常加载静态资源没有 404。调用后端接口确认能拿到数据没有 502/504。如果服务之间用了内部网络互联比如 Java 通过容器名访问 MySQL确认 Docker 网络已经正确创建容器名解析正常。用 curl 检查关键接口和证书链是否正常。这里建议做一张自检清单逐项打勾检查项命令/方法预期结果是否通过面板可访问浏览器访问 https://新IP:面板端口能打开登录页MySQL 数据完整mysql 登录后对比行数库表数量一致Redis 可用redis-cli pingPONG站点可访问curl -I https://域名200/301接口连通curl 业务接口正常返回 JSON5. 常见问题与排查经验5.1 1Panel 打不开或者报“未设置服务器地址”这个报错在迁移场景里非常典型。在源服务器上1Panel 记住了当时的服务器访问地址迁移到新机器后 IP 变了面板校验发现地址对不上就会在登录前报错。处理办法主要有两步。第一步确认 1Panel 版本一致否则先把面板升级到和源服务器相同版本。第二步找到面板数据库中存放的 ServerAddress 配置改成新 IP 并重启服务。如果修改后仍然报错检查 /opt/1panel/conf/app.yaml 里的端口和监听地址是否为 0.0.0.0有些版本面板默认只监听 127.0.0.1外部访问自然失败。5.2 容器启动失败目录权限或空目录覆盖数据典型场景启动 MySQL 容器发现日志里写着 “Permission denied” 或者 “Unable to lock ./ibdata1”。原因基本都是数据目录 UID 不对。1Panel 内置的 MySQL 镜像一般以 mysql 用户运行UID 通常是 999。解决chown -R 999:999 /opt/1panel/apps/mysql/mysql-8.0/data另外就是空目录覆盖问题。如果你在数据目录还没还原时就启动了容器Docker 会创建一个空目录并关联这时候不要慌先停止容器删除那个被 Docker 生成的空目录再重新解压原数据包最后启动。5.3 MySQL 无法启动或导入数据报错如果导入时遇到 “Unknown collation” 或者 “Table doesnt exist”先检查两台服务器的 MySQL 版本是否一致。1Panel 源服务器是 MySQL 8.0新环境误装了 MariaDB或者镜像 tag 不对都会导致兼容问题。另外注意 my.cnf 中 lower_case_table_names 参数。Linux 下 MySQL 默认区分表名大小写如果旧环境把这个参数设成 0新环境没设置或设置成 1会导致表找不到。查一下 /opt/1panel/apps/mysql/.../conf 下的配置文件确保关键参数一致。5.4 镜像 load 后业务容器找不到镜像docker load 导入 gzip 包后镜像仓库和标签可能被保留也可能变成 : 。尤其旧版 Docker 在 load 某些私有仓库镜像时会把 registry 地址去掉。解决思路用 docker-compose.yml 里的 image 字段做基准逐个确认镜像是否存在。如果不存在或者 tag 不对用 docker tag 手动修正。修改后 docker compose up -d 就能正常拉取到本地镜像。5.5 离线安装软件时依赖缺失离线环境 dpkg -i 时报依赖缺失最折磨人。我的经验是在一台全新、干净的 Ubuntu 22.04 联网机器上用同样的方式下载依赖能最大程度还原目标机器的依赖全集。# 用 apt-rdepends 递归分析依赖 apt-rdepends docker-ce | grep ^ | awk {print $1} | sort -u | xargs apt download把这些依赖包全部传到目标机器然后先装基础依赖再装 Docker。不要想当然跳步骤依赖顺序错了会反过来报错。写在最后的几点经验这类把 1Panel 服务整体搬到离线服务器上的操作我做过不止一次。最深刻的感受是时间往往不是花在“copy 文件”上而是花在排错上。目录权限不对、面板地址残留、数据库版本差异每一个坑都够你查半天。如果你要动手我建议先做两件事第一把源服务器的版本号、端口、账号、数据库密码、关键目录完整记录成一张表不要靠记忆第二新服务器恢复数据前先停掉面板和容器确认目录结构完整再启动。顺序对了迁移就顺了一半。迁移全部完成、业务验证通过之后记得在 1Panel 面板里做一次完整的全量备份把新环境的状态固化下来。之后再回头检查旧服务器确认没有遗漏的任何定时任务、cron 脚本或者外部依赖再考虑下线旧机器。离线环境最怕“以为迁移完了结果某天发现某台老机器的日志服务还在被新环境依赖着”。这种细节只有做完整张自检清单的人才会懂。
返回列表