ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

openEuler 部署 Docker UI 全链路:选型、安装调优与安全收口

openEuler 部署 Docker UI 全链路:选型、安装调优与安全收口 Docker 容器与虚拟化技术这条线上的活我这几年干得最多的不是“怎么把容器跑起来”而是“怎么让一群人能安全地看见并管住跑起来的容器”。openEuler 部署 Docker UI 就是典型的后者机器装好、引擎起来了不代表团队能用得顺手命令行敲得再熟交接给同事、交给值班同学、交给不常碰服务器的人效率立刻掉一半。所以这篇我想聊的是完整的落地链路——从容器和虚拟化的取舍开始到 openEuler 上的引擎安装、参数调优再到 Docker UI 的选型、部署、入口收口和后续的日常巡检把我踩过的坑和调过的参数都摊开讲。先说清楚这东西是什么。Docker UI 是给 Docker 引擎套的一层 Web 管理界面它本身也是一个容器通过挂载宿主机的容器运行时接口来读取和操作容器、镜像、网络、数据卷。它能解决三件事第一把docker ps、docker logs、docker exec这些高频动作变成点选第二让多人协作时有账号和权限的概念而不是所有人共用一个 root shell第三把“部署一套服务”沉淀成模板或编排文件减少口口相传。适合的读者范围其实挺宽刚接手一台 openEuler 服务器、想把容器管起来的新手能照着把流程走完已经在用 Docker 但界面还停留在命令行的老手可以重点看参数调优、安全收口和排查那几节。1. 动手之前先想清楚为什么是 openEuler 加 Docker UI1.1 容器与虚拟化不是替代关系是两把不同型号的刀很多人一上来就问“容器能不能完全取代虚拟机”这个问题本身就问偏了。虚拟化是在硬件之上插一层 Hypervisor给每台虚拟机切出独立的内核、独立的设备视图隔离边界在硬件抽象层容器是复用宿主机内核靠 namespace 做视图隔离、靠 cgroup 做资源限制隔离边界在操作系统内核里。这个差别决定了它们在启动速度、资源密度、隔离强度上的全部差异也决定了你在 openEuler 上做选型时该怎么摆位置。我给一个自己常用的对照方便你直接对着业务场景挑对比维度虚拟机容器隔离层级硬件抽象层独立内核内核级共享宿主内核启动耗时十几秒到一分钟毫秒到几秒资源开销需要预留固定内存与 vCPU按需占用超卖空间大镜像体积GB 级别几十 MB 到几百 MB单机密度十几到几十台几十到上百个典型用途强隔离、异构系统、遗留应用微服务、持续集成、灰度发布看这张表你会发现一个规律需要“内核级隔离”和“跑不同内核版本”的场景虚拟机仍然是唯一答案需要“密度”和“交付速度”的场景容器优势压倒性。我实际的做法是分层——底层用虚拟机切出资源池和故障域池子里跑 openEuler再用 Docker 在池子里切服务。UI 这一层就落在这个混合结构的上半部分它管的是容器不管虚机所以定位一定要清楚别指望它替你把资源池也管了。提示如果你所在的环境里已经有成熟的虚拟化平台Docker UI 的定位应该是“应用侧的可视化入口”不要试图让它承担基础设施层的编排职责职责一旦混了权限模型会变得很难收口。1.2 openEuler 作为宿主发行版特性带来的真实影响openEuler 这几年在服务器侧的存在感越来越强它默认内核版本较新cgroup v2 支持完整安全加固策略也相对严格。这些特性对跑容器是好事但也带来几个必须在部署前确认的点。第一是 cgroup 版本cgroup v1 和 v2 下容器引擎的资源限制行为不完全一样docker info里能看到 Cgroup Driver 和 Cgroup Version装完第一件事就该看这个。第二是 SELinux 的默认状态openEuler 上通常是 enforcing 或 permissive这两个状态对挂载宿主机 socket 文件的影响完全不同后面第三节我会专门讲。第三是软件源。openEuler 有自己的软件仓库体系社区也维护了一部分容器相关包但版本更新节奏和上游不完全同步。我在实际项目里遇到过 EPOL 仓库里的引擎版本落后于业务需要的 API 版本导致某些 compose 特性用不了。这种情况下我一般优先选择“官方静态二进制 自建 systemd 单元”的方式绕开发行版打包差异代价是要自己处理依赖和升级收益是版本完全可控、行为可预期。还有一个容易被忽略的点openEuler 默认可能预装了 podman 或 buildah 这类容器工具它们和 Docker 的命令行工具在部分路径上会打架尤其是/usr/bin/docker这个位置。装之前先确认一下有没有残留比装完再排查省事得多。这个我在第四节会给出检查命令。1.3 UI 解决的是“人”的问题别把它当技术方案我想强调一个观点Docker UI 不提升任何技术指标。它不会让你的容器跑得更快不会让镜像变小也不会自动帮你做高可用。它解决的是协作成本——值班同学半夜要看日志不用再找人要 SSH 权限新人接手项目能直观看到有哪些容器、映射了什么端口、挂在哪个卷上交接时不用再写“这台机器上跑了什么”的文档界面本身就是文档。理解了这一点你在部署时的取舍就会清楚很多。既然是给人用的那么访问入口、账号体系、审计记录就比“功能多不多”更重要既然是内部工具就不要把它暴露在公网也不要用默认端口和默认密码。我见过太多把管理面板直接映射到 0.0.0.0 上、跑了半年没人管的例子这类资产一旦被扫到等于把整台机器的 root 权限拱手让人因为 UI 容器挂载了容器运行时接口它天然具备宿主机的等效权限。这句话不是危言耸听后面讲 socket 挂载时我会展开。2. 部署前的环境盘点三个必须先确认的硬条件2.1 系统版本、内核与磁盘的规划方法动手前先跑几条命令把底摸清比装到一半发现问题强。系统版本用cat /etc/openEuler-release内核用uname -r架构用uname -m。openEuler 主流在用的是 22.03 LTS 和 24.03 LTS 两个系列前者内核 5.10后者更新一些两者都完整支持 Docker 需要的 namespace 和 cgroup 特性不需要额外编译内核模块。磁盘是重点。Docker 的默认数据目录在/var/lib/docker这里会同时存放镜像层、容器可写层、数据卷和构建缓存。我的经验值是只跑几个轻量服务给 40GB 起步跑十几个中等规模服务100GB 比较踏实如果涉及数据库容器或者构建流水线单独挂一块盘给/var/lib/docker是必须的。原因很直接——镜像层是共享的删了标签数据层未必马上释放加上日志默认不限制大小一台跑了三个月的机器被日志撑爆根分区是极常见的事故。这里给一个可以照着算的公式用来估日志占用上限单容器日志上限等于max-size乘以max-file。假设你设置成 50MB 和 3 个文件那么单个容器最多占 150MB机器上跑 50 个容器最坏情况就是 7.5GB。这个数字必须在磁盘规划里预留出来而不是等它涨到把根分区吃满再去清理。我在第六节会给出对应的daemon.json配置。内存方面引擎本身加 UI 的常驻开销并不大Docker 守护进程通常在 100MB 到 200MB 量级Portainer 这类面板容器也差不多在 100MB 上下真正吃内存的是业务容器。所以规划时别把 UI 当成负担它几乎可以忽略不计。不过有一点要注意如果宿主机内存比较紧张务必给容器设置内存上限否则单个容器内存泄漏会触发宿主机 OOM Killer它挑谁下手是随机的杀掉引擎进程导致整机容器全挂的情况我遇到过不止一次。2.2 软件源、依赖与旧组件的清理顺序装 Docker 之前有一轮清理工作顺序错了会很麻烦。第一步查残留rpm -qa | grep -Ei docker|podman|buildah|containerd|runc把结果看一眼。如果存在 podman 和 buildah它们和 Docker 共享runc和部分容器运行时组件同时装可能引发依赖冲突实践中最省事的处理是先卸载它们装完 Docker 需要的话再单独装回来。第二步处理仓库。openEuler 上可以走社区维护的容器相关仓库也可以直接配置上游的软件源。走上游源时有个坑必须提前说上游仓库路径里通常带$releasever变量而 openEuler 的$releasever值是22.03这种格式拼出来的路径在上游并不存在dnf makecache会直接报 404。解决办法是把仓库文件里的变量写死成对应的主版本号比如按兼容性填8或9或者干脆不用仓库走静态二进制。这个细节网上很多教程不会提但它确实是新手卡住时间最长的一步。第三步是基础依赖。静态二进制方案需要iptables、iproute、libcgroup、systemd这些openEuler 默认基本都齐了只需要确认iptables是 nft 还是 legacy 后端。新版 Docker 默认走 nft 后端如果系统里只有 legacy 的iptables引擎启动后创建规则会失败表现为容器端口映射不生效但容器本身是运行状态。检查命令是iptables --version如果输出里没有nf_tables字样就需要额外装iptables-nft包让两个后端并存。注意清理和卸载动作一定要在业务低峰做并要求有回滚手段。删除包的同时如果带走了配置文件重建所需的时间往往比预想的长。2.3 网络、时间与安全基线的三件小事第一件是时间同步。容器里跑的东西一旦涉及证书、令牌、日志时间戳宿主时间漂移就是灾难。timedatectl status看一眼有没有同步源chronyc tracking看偏差。我一般要求偏差控制在秒级以内因为 TLS 证书校验对时间很敏感差出几分钟就会报证书未生效或已过期而这个报错在容器里往往被翻译成“连接失败”排查方向会被带偏。第二件是防火墙。openEuler 默认可能启用 firewalld这里有一个非常经典的坑Docker 启动时会自己往 iptables 的nat表和filter表里写规则而这些规则位于 firewalld 管理链的下游导致你通过 firewalld 关掉的端口只要被容器映射了仍然能从外部访问。也就是说firewall-cmd --remove-port对容器端口是无效的。正确的做法有两种要么把容器端口绑定到127.0.0.1上只让本机的 Nginx 转发要么把限制规则写进DOCKER-USER链这个链是 Docker 专门留给用户自定义规则的入口位置在容器规则之前优先级正确。第三件是主机名和 DNS。给机器起一个能看懂的名字比如docker-ui-01后续在界面里看到节点名字时不会一脸懵。DNS 方面建议确认/etc/resolv.conf里没有指向127.0.0.53这类只有本机 systemd-resolved 才认的地址因为容器默认继承宿主 DNS 配置而127.0.0.53在容器网络命名空间里是不可达的结果就是容器能启动、能 ping 通 IP但域名解析全部失败。这个问题在第六节还会详细讲。3. 引擎安装的完整实操两条路线与参数调优3.1 路线选择仓库安装还是静态二进制我把两条路线的差异摊开方便你按场景选。仓库安装的优点是省事dnf install一条命令依赖自动处理升级也走dnf upgrade缺点是版本受限于仓库遇到上游打包滞后时没辙。静态二进制的优点是版本完全由你决定解压即用迁移方便缺点是需要自己写 systemd 单元升级要手动替换二进制并重启而且出问题时没有包管理器的完整性校验兜底。我的选择逻辑是如果是个人实验或者小规模环境仓库安装足够如果是团队共用、需要长期维护、对版本有明确要求走静态二进制更省心。下面两条路线我都会给出关键步骤仓库那条我会写清变量替换的坑静态那条我会写全单元文件。3.2 路线一配置软件源后安装仓库配置文件放在/etc/yum.repos.d/下名字随意后缀必须是.repo。内容的关键是baseurl里的版本号不能留变量gpgcheck保持开启gpgkey指向对应的密钥地址。写完执行dnf clean all dnf makecache能正常拉到元数据说明配置对了。安装时我习惯显式带上--allowerasing原因是如果系统里还有旧的运行时组件不加这个参数会因为文件冲突直接失败报错信息里一堆file /usr/bin/xxx conflicts新手看了容易懵。带上之后 dnf 会自动把冲突的包换掉代价是你得确认被换掉的包不是业务依赖。装完之后立刻验证docker version看客户端和服务端是否都返回只出来客户端说明服务端没起docker info看Server Version、Storage Driver、Cgroup Version、Kernel Version四项这四项是后续所有问题的判断依据。还需要处理用户组。把日常运维账号加进docker组避免每条命令都sudousermod -aG docker your_user newgrp docker这里必须说一句实话加入docker组等价于拿到 root 权限因为你可以直接docker run -v /:/host把宿主机根目录挂进容器再改文件。这不是设计缺陷是机制使然。所以我的做法是只给确实需要的人开同时把 UI 的权限体系用起来让大部分人通过 UI 操作而不是直接上 SSH。3.3 路线二静态二进制安装与 systemd 单元下载对应架构的压缩包解压后把docker/目录下的可执行文件复制到/usr/bin/然后在/etc/systemd/system/docker.service写单元文件。核心配置如下[Unit] DescriptionDocker Application Container Engine Afternetwork-online.target firewalld.service Wantsnetwork-online.target [Service] Typenotify ExecStart/usr/bin/dockerd ExecReload/bin/kill -s HUP $MAINPID TimeoutStartSec0 Restartalways RestartSec2 LimitNOFILEinfinity LimitNPROCinfinity Delegateyes KillModeprocess OOMScoreAdjust-500 [Install] WantedBymulti-user.target几个参数值得解释。Typenotify让 systemd 等引擎真正就绪后才认为启动完成避免服务状态显示 running 但实际还在初始化。LimitNOFILEinfinity是因为容器密集场景下文件句柄消耗很大默认的 1024 远远不够容器数一多就会出现too many open files。OOMScoreAdjust-500降低引擎被内核优先杀掉的概率这个在内存紧张时能救命。Restartalways配合RestartSec2提供基础的自动拉起能力但注意它不是万能的如果引擎是因为配置错误反复崩溃你会看到不断重启的循环要结合journalctl -u docker -n 100看具体原因。写完之后systemctl daemon-reload systemctl enable --now docker再跑一次docker info验证。静态二进制方案下 containerd 会由 dockerd 自己拉起不需要额外启用 containerd 服务这一点和包管理器方案不同别多此一举去启两个 containerd 抢同一个 socket 目录会直接报错。3.4 daemon.json五个真正影响长期运行的参数配置文件放在/etc/docker/daemon.json改完必须重启引擎systemctl reload docker只对部分参数生效图省事用 reload 结果参数没生效、排查半天的情况我见过。下面这份是我在多数环境里会用的基线{ data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 }, live-restore: true, default-address-pools: [ { base: 172.30.0.0/16, size: 24 } ], exec-opts: [native.cgroupdriversystemd] }>docker volume create portainer_data docker run -d \ --name portainer \ --restartalways \ -p 127.0.0.1:9443:9443 \ -p 127.0.0.1:8000:8000 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:lts-p前面的127.0.0.1是我强烈建议加的。不加的话端口监听在0.0.0.0等于把管理面板直接暴露出去后面再加 Nginx 也挡不住——别人可以直接打容器端口。加上绑定之后外部只能通过本机的转发层访问攻击面立刻收窄了一大截。8000端口是边缘计算代理用的单机环境其实用不上我保留它是因为某些版本的界面会用到这个端口做节点注册去掉也能跑属于可选项。9443是默认的 HTTPS 端口新版 UI 默认只走 HTTPS早期版本还提供过一个 HTTP 端口现在需要显式打开才有我倾向于不开 HTTP直接走 HTTPS 更省心。-v /var/run/docker.sock:/var/run/docker.sock这一行是整个部署里最需要理解的。它把宿主机上的容器运行时接口以 Unix socket 文件的形式挂进容器UI 通过这个文件发 HTTP 请求来操作引擎。这意味着容器里的进程实际拥有和宿主机 root 同等的容器管理权限。所以这个挂载不能给任意镜像用只能给自己审查过的 UI 镜像用而且一旦 UI 本身被攻破宿主机也就失守了。如果你对这点比较介意有一个中间方案在前面加一层 socket 白名单网关只放行读操作和有限的写操作UI 连网关不连原始 socket。这个方案会增加一个容器和一份配置但能把“UI 被攻破等于宿主机失守”降级成“只能做允许的动作”。规模不大时可以先不做但要清楚这个风险存在。portainer/portainer-ce:lts这个标签我建议在生产上换成具体版本号比如明确写死到某个小版本。浮动标签在升级时可能带来非预期变更管理面组件尤其不该这样因为界面结构变化会影响值班同学的操作习惯。4.3 首次初始化与安全收口容器起来之后先看日志确认没有报错docker logs portainer里如果出现权限相关的错误基本都是 socket 挂载或 SELinux 的问题第六节有排查表。然后浏览器访问https://服务器IP:9443此时是自签证书浏览器会告警点继续即可反正后面会用 Nginx 接管。第一件事是设置管理员密码第二件事是选环境类型单机选 Docker 就行。初始化完成后有几个收口动作建议立刻做把默认的admin用户名改掉开启双因素认证如果环境支持给团队成员建普通账号而不是共用管理员把“允许外部加载应用模板”这类用不到的功能关掉。管理面的原则是能关就关留下的每一个入口都会成为后续审计的负担。还有一个细节初始化有个时间窗口如果容器起来后超过几分钟没人访问某些版本会要求重启容器才能继续初始化。这不是故障是安全设计。我遇到过同事以为部署失败反复重建容器其实是没在窗口内完成初始化白折腾。4.4 用编排文件管理 UI 自身UI 自己也是容器用编排文件管它升级和迁移会舒服很多services: portainer: image: portainer/portainer-ce:2.20.3 container_name: portainer restart: always ports: - 127.0.0.1:9443:9443 volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data volumes: portainer_data: external: true注意数据卷声明成external因为你已经用命令建过了编排文件如果自己再建一个同名卷会冲突。把文件放在/opt/stacks/portainer/这类固定路径下和业务编排文件分开避免哪天误删业务目录把管理面一起带走。升级时改镜像版本号docker compose up -d就完成替换回滚就把版本号改回去比记命令靠谱。5. 访问入口收口Nginx 前置与证书配置5.1 为什么建议再套一层UI 自带的 HTTPS 用的是容器内置的自签证书每次重建容器证书都可能变浏览器告警会反复出现值班同学点“继续访问”点多了就麻木了这恰恰是安全习惯被磨掉的过程。套一层 Nginx 的好处有三个证书统一管理换证书不用动容器可以加访问控制比如只允许内网段访问、加基础认证做二次校验可以做统一入口多个管理面板挂在不同路径下对外只暴露一个域名和端口。这一层的定位就是转发不做缓存不做改写配置越简单越好因为它是所有管理流量的必经之路多一条规则就多一个故障点。5.2 配置示例与证书生成先出证书内网用自签就够了关键是把它固定下来mkdir -p /etc/nginx/certs openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /etc/nginx/certs/docker.key \ -out /etc/nginx/certs/docker.crt \ -subj /CNdocker-ui.internal有效期给到 3650 天内网自签没必要频繁换但要在日历上记一笔到期提醒我吃过证书过期导致整个面板打不开、排查半天以为是服务挂了的亏。如果内网有统一的证书签发设施优先用统一签发省掉信任导入的麻烦。Nginx 配置的关键点在于后端是 HTTPS需要关掉后端证书校验同时要把长连接的升级头带上否则界面里某些实时刷新的功能会失效server { listen 443 ssl; server_name docker-ui.internal; ssl_certificate /etc/nginx/certs/docker.crt; ssl_certificate_key /etc/nginx/certs/docker.key; client_max_body_size 0; location / { proxy_pass https://127.0.0.1:9443; proxy_ssl_verify off; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; } }client_max_body_size 0是必须的因为通过界面上传镜像或导入编排文件时请求体可能很大默认的 1MB 限制会直接返回 413而界面上只会显示一个含糊的失败提示。proxy_read_timeout拉长到一小时是因为查看日志流这类长连接会被默认 60 秒掐断表现为日志看一会儿就不动了容易误判成服务卡死。proxy_ssl_verify off只在这个内网回环场景下可以接受因为后端就在本机不存在被中间人截获的路径。配完nginx -t验证语法再systemctl reload nginx。验证方式是访问域名看证书是不是 Nginx 那张同时确认界面能正常加载、日志能持续刷新。6. 踩过的坑排查思路与速查表6.1 镜像拉不下来先分层排除再动手这个问题我被问得最多排查顺序错了会浪费大量时间。正确的顺序是从外到内先在宿主机上curl -I目标仓库地址确认网络可达和证书链正常再docker pull一个极小的公共镜像做对照排除是单个镜像的问题还是全局问题再看journalctl -u docker -n 200里的具体错误码。常见的三种错误对应三种原因。报 TLS 握手超时多半是宿主时间偏差或者中间有设备做了证书拦截报no such host或者解析超时是 DNS 问题容器内继承的resolv.conf指向了本机回环地址的解析服务在容器命名空间里根本连不上解决办法是在daemon.json里显式指定dns字段或者把宿主机的解析配置改成容器可访问的地址报i/o timeout但curl正常很可能是 MTU 不匹配链路上存在隧道或者 overlay 封装时默认 1500 的 MTU 会让大包被丢弃小包正常大包卡住表现就是拉取进度条走到一半停住。MTU 的处理方法是在daemon.json里加mtu: 1450然后重启引擎并重建网络。这个值不是固定的1400 到 1450 之间试判断标准是ping -M do -s 1472这类不分片探测能不能通。我给的这个排查法虽然土但比翻日志快。6.2 端口不通与权限拒绝两类完全不同的原因容器跑了但端口访问不了第一步看docker port 容器名确认映射关系第二步在宿主机curl 127.0.0.1:端口绕开防火墙测试第三步从另一台机器测。这三步能把问题定位到“映射错”“本机防火墙”“链路防火墙”三个层面之一。如果本机通、外部不通八成是前面说的 firewalld 与 Docker 规则顺序问题。验证方法很直接iptables -t nat -L -n看有没有对应的 DNAT 规则有规则但外部不通就去DOCKER-USER链里找有没有被拦截。解决办法是把放行规则插到DOCKER-USER链首iptables -I DOCKER-USER -s 内网段 -j ACCEPT再补一条默认拒绝。注意这些规则重启会丢要写进开机脚本或者用iptables-save持久化。另一类问题是 SELinux 拒绝。表现是容器启动失败日志里有permission deniedausearch -m avc -ts recent能看到具体的拒绝记录。UI 挂载 socket 时最容易碰到处理办法有两种给挂载加:z标签让 SELinux 重打上下文或者针对容器相关布尔值做定向放行。我不建议直接把 SELinux 设成 disabled那等于放弃了最后一道防线而且改回来很麻烦。定向放行虽然要多花十分钟但长期看是值得的。6.3 磁盘告急与数据目录迁移根分区被吃满的现场通常是这样的df -h显示 100%du -sh /var/lib/docker/*一看overlay2占了绝大部分再进去看是某个容器的日志文件几个 G。这时候别急着删目录先按前面说的给daemon.json加日志上限并重启引擎新日志会按新策略滚动老的大文件再单独清理。直接rm正在被进程打开的文件空间不会立刻释放因为文件句柄还在lsof | grep deleted能看到这类悬空文件。数据目录迁移要按顺序来停业务容器、停引擎、用rsync -aHAX同步、确认新目录权限、改daemon.json、启引擎、验证docker info里的 Root Dir 已指向新路径、再启业务容器。中间任何一步跳过都可能出现“容器还在但数据没了”的情况。我一般会在迁移前把docker ps -a和docker volume ls的输出存一份迁移后逐项核对虽然土但有效。6.4 UI 打不开或报 500 的速查路径这类问题的排查我整理成了一张表按命中率排序现象最可能原因验证方式处理页面 500日志报连接 socket 失败socket 挂载路径错或权限不足ls -l /var/run/docker.sock确认挂载路径检查 SELinux 上下文页面能开但容器列表为空UI 连的是别的引擎或环境配错看 UI 里的环境配置重新指向本机 socket上传编排文件报 413转发层请求体限制看 Nginx 错误日志调整client_max_body_size日志界面几秒后停止刷新转发层读超时观察停止的固定间隔调大proxy_read_timeout界面操作全部超时引擎无响应或磁盘满docker info是否卡住先救引擎再查 UI证书告警反复出现用了容器内置自签证书看证书签发者用 Nginx 统一证书6.5 三条来自现场的经验第一条出问题先看引擎再看 UI。UI 只是壳它所有的能力都来自引擎接口引擎不健康的时候 UI 的表现五花八门容易把人引向错误方向。养成先跑docker info的习惯能省掉一半排查时间。第二条任何变更前先留证据。docker ps -a、docker images、docker volume ls、daemon.json备份四样东西存一份出问题时对照着看比凭记忆靠谱得多。第三条别在生产上试新版本 UI。管理面的界面变更会影响操作习惯而操作习惯在应急时就是肌肉记忆。要升级先在测试环境用一周确认常用路径没变再推。7. 长期可用备份、升级与日常巡检7.1 备份策略备份的是配置不是数据管理面的备份重点在于数据卷和编排文件不在镜像。数据卷里存的是用户、环境、模板、设置这些信息丢了就得重建一套重新配权限很烦。备份方式很直接停容器用临时容器把卷打包成 tar 落到宿主机再传到备份目录最后启容器。整个过程对业务容器没有影响因为停的只是管理面。编排文件和证书目录要一起备份因为它们和卷里的配置是配套的。我习惯把这三样东西卷归档、编排文件、证书放在同一个带日期的目录下恢复时整体解压不会漏。备份频率看团队规模账号体系变化不频繁的话一周一次加上变更前手动一次就够。7.2 升级与回滚的具体动作升级前先看新版本的变更说明里有没有涉及认证方式、数据结构的调整有的话必须先备份再动。动作顺序是改编排文件里的镜像版本、docker compose pull、docker compose up -d、看日志确认迁移完成、登录验证核心功能。如果验证不通过把版本号改回旧值再up -d因为数据卷通常做了向后兼容迁移回滚到旧版本多数情况下能正常读取但有极小概率旧版本读不了新结构所以备份是回滚的前提。引擎本身的升级我建议和 UI 升级错开至少一周。两个组件同时变更出问题时无法判断是谁引起的排查成本翻倍。7.3 巡检清单每周花十分钟我给自己定的巡检项很朴素docker system df看镜像和卷的占用趋势涨得太快说明有东西在堆积df -h看磁盘水位超过 80% 就提前处理docker ps --filter healthunhealthy看有没有不健康的容器journalctl -u docker --since 7 days ago | grep -i error看引擎有没有反复报错最后登录 UI 扫一眼确认账号没有多余的、模板没有被乱改。这套动作十分钟能做完但能挡住绝大多数“突然全线崩”的场景因为所有大故障在发生前都会有小征兆只是没人看。我在实际使用中最大的体会是容器这套东西的上手门槛很低但长期可用性完全取决于这些琐碎的日常动作装的时候花的心思只是开头后面每周十分钟才是真正决定它能不能撑住的部分。最后分享一个小技巧给 UI 加一个只读账号专门给不常操作但需要看状态的同事用然后把这个账号的登录方式写进值班手册第一页。既省了开权限的沟通成本也把误操作的可能性压到了最低。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表