ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于Docker部署Rocky Linux基础镜像平台实战指南

基于Docker部署Rocky Linux基础镜像平台实战指南 上周有个同事跑过来问我公司生产环境里一堆 CentOS 7 马上就到维护节点了运维脚本跑了好几年不想重写新上的容器镜像到底该选哪个发行版。我直接跟他说Rocky Linux。如果你也在纠结容器基础镜像选型或者想把现有 RHEL 系的运维经验平滑迁移到 Docker 场景这篇文章能帮你少走不少弯路。这篇博文会围绕一个核心问题展开怎么用 Docker 部署 Rocky Linux把它打造成一个可以反复复用的 RHEL 兼容企业级基础镜像平台。我不只会给你一个能直接跑的 Dockerfile还会把选型逻辑、镜像源配置、静态 IP 规划、基于这个镜像搭建 MySQL 和 Redis 主从的实战过程以及镜像仓库和多架构构建这些“往后走”的环节都讲清楚。无论你是刚接触 Docker 的运维新人还是已经深入容器化改造的架构师都能在里面找到可以直接落地的内容。1. 内容整体设计与思路拆解1.1 为什么选 Rocky Linux 作为 Docker 基础镜像先说结论Rocky Linux 是 Red Hat Enterprise LinuxRHEL的社区重新编译版本目标就是做到和 RHEL 完全二进制兼容。这意味着在 RHEL 上能跑的 rpm 包、能用的 systemd 服务管理方式、能执行的 firewalld 规则在 Rocky Linux 上基本都可以直接复用。CentOS 7 停更之后很多企业都在找替代品。Rocky Linux 之所以被认可关键在于三点兼容性它是 RHEL 的下游发行版rpm 包、依赖库、内核模块的使用习惯都和 RHEL 一致不会出现“换个发行版运维脚本全废掉”的情况。长期维护Rocky Linux 8 和 9 都有明确的维护周期安全补丁会持续跟进这对企业生产环境来说比“尝鲜版”重要得多。社区治理由社区主导的治理模式透明度高不会因为商业策略调整就突然改变发布节奏。在 Docker 场景下选 Rocky Linux 还有一个额外优势很多第三方软件源比如 MySQL 官方 Yum 源、EPEL 源都明确支持 RHEL 8/9而 Rocky Linux 属于“RHEL 兼容发行版”所以这些源可以直接配上去不用像某些发行版那样绕来绕去。这点在搭建基础镜像平台时非常省事。1.2 基础镜像平台到底在搭什么很多人理解的“基础镜像”就是docker pull rockylinux:8.10拉下来直接用。但“平台”两个字意味着它不是一次性动作而是一套可复用、可扩展、有规范的体系。我习惯把基础镜像平台分成三层来看第一层最小化 OS 镜像。就是官方提供的 Rocky Linux 镜像只包含最基本的文件和包管理器体积小作为一切构建的起点。第二层企业级初始化镜像。在这一层解决时区、字符集、软件源、基础工具、CA 证书、DNS 配置这些“每台机器都要做一遍”的事情。这一层也是本文重点。第三层运行时镜像。在第二层基础上叠加具体运行环境比如 JDK、Python、Node.js或者 MySQL、Redis 这类中间件。打个比方第一层是毛坯房第二层是统一水电和装修标准第三层才是入驻后按需添置家具。如果没有第二层每个应用都从毛坯房开始装修风格会五花八门后续排查问题也得跑遍各家看差异。有了统一标准镜像构建速度和可维护性都会明显提升。我们这篇文章要做的就是把这个平台搭起来并用 MySQL 8.0 和 Redis 主从两个案例演示怎么在这一层上面快速长出应用镜像。2. 环境准备与基础配置2.1 安装 Docker 引擎不管最终目标是什么第一步都是先把 Docker 装好。我下面分 Linux 和 Windows 两种常见场景简单说一下。Linux 环境安装最常用的还是官方安装脚本curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo systemctl enable --now docker安装完成后把当前用户加入 docker 组避免每次敲命令都要加 sudosudo usermod -aG docker $USER newgrp docker这里的坑是加入 docker 组后需要重新登录终端才生效很多人直接敲docker version发现还是提示权限不足其实是会话缓存的问题不是安装失败。Windows/macOS 环境用 Docker Desktop 是最省事的方式。启动时如果提示虚拟化没开启比如virtualization support wasnt detected需要进 BIOS 开启 VT-x/AMD-V。这个在笔记本上尤其常见装完 Docker Desktop 打不开先别急着卸载十有八九是虚拟化开关的问题。2.2 解决镜像下载慢的问题拉官方镜像慢几乎是绕不开的问题。大家可以配置 Docker 镜像加速器修改/etc/docker/daemon.json{ registry-mirrors: [ https://docker.mirrors.ops.example.com ] }配置说明这里填的是你所在网络环境里可用的镜像加速地址不同云厂商都有对应服务。配好后重启 Dockersudo systemctl daemon-reload sudo systemctl restart docker然后拉一个镜像验证docker pull rockylinux:8.10如果还有报错看下/etc/resolv.conf的 DNS 设置镜像加速器域名解析失败也会导致拉取超时表现和“源不可用”很像。2.3 静态 IP 与容器网络规划相关热搜词里有一个“rocky linux 设置静态 ip”这个在纯虚拟机场景下是常识但在 Docker 场景里容易被忽略。我们搭建基础镜像平台通常宿主机是 Rocky Linux上面跑一批容器。如果宿主机 IP 是 DHCP 分配的重启后 IP 一变私有仓库地址、NFS 挂载、监控采集基本全断所以宿主机必须设置静态 IP。用nmcli设置静态 IP 的命令如下sudo nmcli connection modify ens33 \ ipv4.method manual \ ipv4.addresses 192.168.10.20/24 \ ipv4.gateway 192.168.10.1 \ ipv4.dns 223.5.5.5 8.8.8.8 sudo nmcli connection up ens33改完先ip addr确认 IP 生效然后再ping网关。这里有个经验nmcli connection modify修改的是连接配置不是网卡本身所以写网卡名的时候要对应好nmcli connection show里的连接名别直接拿接口名去套否则不会生效。容器网络的静态 IP 规划也要提前想清楚。我推荐在部署中间件之前先创建自定义网络避免容器 IP 漂移docker network create --subnet192.168.100.0/24 --driver bridge app-network之后创建容器时指定docker run --network app-network --ip 192.168.100.10 ...自定义网络的好处是容器之间可以用服务名互相访问同时可以给重要容器固定 IP方便防火墙规则和运维脚本调用。这里不做固定 IP 的话容器重建后 IP 就变了监控告警设备全部失联排查起来很头疼。2.4 基础镜像版本选择与标签规范Rocky Linux 主流版本是 8.x 和 9.x两者都能在 Docker Hub 找到官方镜像。从稳定性和第三方软件兼容性来看生产环境我更推荐 8.x 系列因为大量企业级软件的 Yum 源都最先保证 RHEL 8 兼容性Rocky 8 作为 RHEL 8 的社区重建版能直接享受这个红利。镜像标签尽量不要用latest。虽然本地测试方便但生产环境一旦基础镜像更新容器重建时“悄悄升级”可能引发兼容问题。我建议在基础镜像平台里指定具体小版本比如rockylinux:8.10并在 Dockerfile 里用FROM rockylinux:8.10锁定必要时再加上镜像摘要FROM rockylinux:8.10sha256:xxxxxxxx确保可复现。3. 核心细节解析与实操要点构建企业级基础镜像3.1 一个最小可用的 Dockerfile 长什么样先给一个能跑起来的初版 Dockerfile后面的章节再逐个拆解为什么这么写FROM rockylinux:8.10 ENV TZAsia/Shanghai \ LANGen_US.UTF-8 \ LC_ALLen_US.UTF-8 RUN cd /etc/yum.repos.d/ \ sed -i s/^mirrorlist/#mirrorlist/ /etc/yum.repos.d/Rocky-*.repo \ sed -i s|^#baseurlhttp://dl.rockylinux.org/$contentdir|baseurlhttps://mirrors.example.com/rocky| /etc/yum.repos.d/Rocky-*.repo \ dnf install -y epel-release \ dnf makecache \ dnf install -y curl wget vim-minimal openssl ca-certificates tzdata tar \ util-linux procps-ng which \ dnf clean all RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezone RUN useradd -m -s /bin/bash appuser CMD [/bin/bash]这个文件看起来短但每一行都有自己的作用下面拆开讲。3.2 软件源配置是基础镜像的“地基”基础镜像的原生软件源大多指向官方源从国内网络访问速度往往不理想。第二行 RUN 做的事情就是把默认源替换成本地网络可达的镜像源并启用 EPEL 仓库。这里有一个常见误区只替换Rocky-AppStream.repo、Rocky-BaseOS.repo这些主仓库却忽略了 EPEL 和 CRB 仓库。EPEL 是 Extra Packages for Enterprise Linux 的缩写很多运维工具都在这个仓库里CRBCodeReady Builder则提供开发相关依赖。基础镜像如果不提前配好这两个仓库以后想安装某个工具临时在容器里加源会非常慢而且容易因为环境的不可复现性埋雷。替换软件源有一个关键点要注意Rocky 8 仓库文件里同时存在mirrorlist和baseurl两个字段直接用sed注释掉mirrorlist行再把baseurl改成镜像源地址。不注释mirrorlist的话系统仍然会优先去请求官方镜像列表导致配置不生效。这里补充一个实用建议基础镜像里不要安装太多包。很多人的第一版基础镜像把能想到的工具全装上结果不仅镜像体积膨胀到几个 G还扩大了攻击面。我的选择标准是容器里大概率用到的、且编译安装特别耗时的基础工具才进基础镜像。像 curl、wget、tar、openssl、ca-certificates、tzdata 这些是刚需其他的等具体应用镜像里按需装。如果你要在这个基础镜像上跑 LibreOffice 这类大型 rpm 应用也可以提前把/usr/bin/soffice依赖的 libX 相关库装上或者干脆在应用层单独处理。基础镜像的原则是“能少则少缺了再补”。3.3 时区、字符集与语言环境配置企业级容器最常见的两个问题一是日志时间差了 8 小时二是中文乱码。前者基本都跟时区没设置有关后者则和LANG、LC_ALL、字体有关。ENV TZAsia/Shanghai \ LANGen_US.UTF-8 \ LC_ALLen_US.UTF-8 RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezoneENV指令设置的时区变量只是环境变量容器进程读取TZ后会用对应时区输出时间。但很多老程序不读环境变量只读/etc/localtime所以还需要建立软链接双管齐下才稳妥。语言环境这里我反而推荐用en_US.UTF-8而不是zh_CN.UTF-8。原因是中文语言环境需要安装额外的语言包会增大镜像体积而且如果字体没配好中文照样会乱码。企业级应用更常见的做法是数据本身存中文系统日志和错误信息用英文这样排查问题时通用性更高。如果你确实需要中文显示可以额外安装langpacks-zh_CN并做字体配置但这个作为扩展方案留到具体应用层处理就好。3.4 容器内创建非 root 用户安全底线的必修课很多人初写 Dockerfile 会把所有操作放在 root 下应用也以 root 启动。这在本地测试没问题但作为企业级基础镜像这一点必须改。核心原因很简单容器内 root 和宿主机 root 的权限边界没有新手想的那么严格。如果容器被攻破攻击者拿到 root 后一旦配合 Docker 的权限配置缺陷就可能影响到宿主机。所以在基础镜像里提前创建一个普通用户RUN useradd -m -s /bin/bash appuser后续所有应用镜像统一使用这个用户启动进程。需要注意如果应用需要监听 80/443 端口普通用户无法直接绑定 1024 以下端口。这时可以在应用 Dockerfile 里用chown调整端口或者让宿主机用 iptables 做端口转发反正不要在基础镜像里把 appuser 设成 root 权限。3.5 构建基础镜像并验证在包含 Dockerfile 的目录下执行docker build -t registry.example.com/base/rockylinux:8.10-20250427 .构建完成后进入镜像验证docker run --rm -it registry.example.com/base/rockylinux:8.10-20250427 bash date cat /etc/redhat-release which curl如果date输出的是 UTC 时间说明时区配置有问题如果cat /etc/redhat-release显示Rocky Linux release 8.10说明基础镜像版本正确。这一步验证非常关键很多问题都是在真实环境跑起来才发现提前验证可以省掉后面排障的时间。4. 实操过程与核心环节实现基于基础镜像部署 MySQL 8.0 与 Redis 主从基础镜像搭好之后不能只停留在“我能构建一个镜像”这个层面上。下面用两个企业级中间件的部署过程演示基础镜像平台如何在实际业务中复用。4.1 为什么不自接用官方 MySQL/Redis 镜像我知道大家的第一反应是Docker Hub 上明明有官方 MySQL 镜像和 Redis 镜像为什么要费劲自己基于 Rocky Linux 搭我的答案是场景驱动。官方 MySQL 镜像基于 Oracle Linux 或 Debian官方 Redis 镜像基于 Debian。如果团队运维栈完全围绕 RHEL 系建立比如有现成的 RPM 包扫描、安全基线检查、systemd 兼容脚本那 Debian 系镜像就和这些工具对不上。加上某些内网环境的软件源策略非常严格只允许通过企业 Yum 源获取软件包这时候官方镜像既不符合安全审计要求也无法利用已有的软件分发通道。另外一个实际原因是基础镜像平台的价值在于“统一”。如果 MySQL 用官方镜像、Redis 用官方镜像、自研服务用 Rocky 基础镜像那监控 agent 的安装方法、安全扫描策略、日志采集方式都不一样每加一个组件就要单独适配一套。统一到 Rocky Linux 基础镜像后所有组件的初始化、监控、加固都能走同一套流程运维成本是肉眼可见的下降。当然如果你的团队没有这些历史包袱直接用官方镜像完全没问题。这里讨论的是“在已经决定使用 RHEL 兼容基础镜像平台”的前提下中间件应该如何融入这套体系。4.2 MySQL 8.0 容器化部署在基础镜像之上构建 MySQL 8.0 镜像核心步骤是配置 MySQL 官方 Yum 源并安装mysql-community-server包。项目里新建mysql/DockerfileFROM registry.example.com/base/rockylinux:8.10-20250427 COPY mysql.repo /etc/yum.repos.d/mysql.repo RUN dnf install -y mysql-community-server \ dnf clean all RUN mkdir -p /var/lib/mysql /var/run/mysqld \ chown -R appuser:appuser /var/lib/mysql /var/run/mysqld USER appuser EXPOSE 3306 CMD [mysqld]其中mysql.repo内容如下注意 baseurl 要根据 MySQL 官方列表选择[mysql80-community] nameMySQL 8.0 Community Server baseurlhttps://repo.mysql.com/yum/mysql-8.0-community/el/8/$basearch/ enabled1 gpgcheck1 gpgkeyhttps://repo.mysql.com/RPM-GPG-KEY-mysql-2022启动命令里要把数据目录挂到宿主机docker run -d \ --name mysql8 \ --network app-network \ --ip 192.168.100.10 \ -e MYSQL_ROOT_PASSWORDMyStrongPass123 \ -v /opt/mysql/data:/var/lib/mysql \ -p 3306:3306 \ mysql8:1.0这里有几个关键点容器内的/var/lib/mysql必须是可写的而且权限要匹配appuser否则 MySQL 初始化会直接失败。使用自定义网络并指定固定 IP是为了让 Redis、应用服务都能通过固定地址连数据库IP 漂移的影响会小很多。数据卷挂载后宿主机目录权限默认是 root容器内用户写入时可能遇到 permission denied解决办法是在宿主机执行chown 1000:1000 /opt/mysql/data注意这里 1000 对应容器内 appuser 的 UID。MySQL 初始化完成后用客户端验证docker exec -it mysql8 bash -c mysql -uroot -p进入 MySQL 后执行SELECT VERSION();如果显示 8.0.x说明基础镜像上的 MySQL 部署成功。4.3 Redis 7 主从复制部署Redis 官方同样提供二进制包我们可以从源码编译也可以直接用软件源安装。为了演示基础镜像平台的灵活性这个例子用编译安装的方式因为很多企业需要对 Redis 做定制编译参数比如调整内存分配器、开启 TLS 支持。先写redis/DockerfileFROM registry.example.com/base/rockylinux:8.10-20250427 AS builder RUN dnf install -y gcc make \ curl -L -o /tmp/redis.tar.gz https://download.redis.io/releases/redis-7.2.4.tar.gz \ tar -xzf /tmp/redis.tar.gz -C /tmp \ cd /tmp/redis-7.2.4 make -j$(nproc) MALLOClibc FROM registry.example.com/base/rockylinux:8.10-20250427 COPY --frombuilder /tmp/redis-7.2.4/src/redis-server /usr/local/bin/ COPY --frombuilder /tmp/redis-7.2.4/src/redis-cli /usr/local/bin/ RUN mkdir -p /data chown appuser:appuser /data USER appuser EXPOSE 6379 CMD [redis-server]这里用多阶段构建第一阶段编译第二阶段只拷贝二进制文件最终镜像不会带 gcc 和源码体积能小很多。Redis 主从要部署两个容器规划固定 IP主节点192.168.100.21从节点192.168.100.22先启动主节点docker run -d \ --name redis-master \ --network app-network \ --ip 192.168.100.21 \ -v /opt/redis/master:/data \ redis7:1.0 \ redis-server --appendonly yes --requirepass RedisPass123再启动从节点用--replicaof参数指定主节点地址和端口并配置主节点密码docker run -d \ --name redis-slave \ --network app-network \ --ip 192.168.100.22 \ -v /opt/redis/slave:/data \ redis7:1.0 \ redis-server --appendonly yes \ --replicaof 192.168.100.21 6379 \ --masterauth RedisPass123验证主从关系docker exec -it redis-master redis-cli -a RedisPass123 info replication如果输出中role:master并且connected_slaves:1说明从节点已经连上。再到从节点上执行docker exec -it redis-slave redis-cli -a RedisPass123 info replication看到role:slave、master_link_status:up主从就算跑通了。4.4 基础镜像平台的复用价值MySQL 和 Redis 只是两个示例实际上 GitLab、Kodbox、Hadoop 周边组件、自研 Java 服务等都能以同一套基础镜像为底座。关键在于我们所有镜像都基于同一个 Rocky Linux 企业级基线日志路径、时区、用户、软件源都一致出了问题只要排查一遍所有组件都能受益。这种“一次构建、处处复用”的效果才是基础镜像平台的真正价值。5. 镜像仓库与多架构构建让基础镜像平台真正“企业级”5.1 自建私有镜像仓库企业环境里不能只依赖公共镜像仓库一是拉取不稳定二是镜像内容和版本不受控。自建一个私有镜像仓库是基础镜像平台建设的自然延伸。最快的方案是直接用官方 Registry 镜像docker run -d \ --name registry \ --restartalways \ -p 5000:5000 \ -v /opt/registry:/var/lib/registry \ registry:2配置好后把之前构建的基础镜像推送到私有仓库docker tag registry.example.com/base/rockylinux:8.10-20250427 192.168.10.20:5000/base/rockylinux:8.10-20250427 docker push 192.168.10.20:5000/base/rockylinux:8.10-20250427需要注意Docker 客户端默认只允许 HTTPS 访问镜像仓库。如果私有仓库暂时没有配置 TLS 证书需要在每台机器的/etc/docker/daemon.json里添加{ insecure-registries: [192.168.10.20:5000] }然后重启 Docker。这里要提醒一句insecure-registries在生产环境尽量少用如果条件允许还是建议给镜像仓库配置合法的 TLS 证书避免镜像在传输过程中被篡改。私有仓库搭建完成后所有服务器从这台 Registry 拉镜像速度稳定版本也统一。这就是企业级基础镜像平台和“从网上随便拉个镜像”的本质区别。5.2 用 Docker Compose 编排整套平台如果微服务组件多逐个docker run不仅繁琐还容易遗漏参数。推荐在项目根目录写一个docker-compose.yml把基础镜像构建、MySQL、Redis 等串起来services: mysql8: build: ./mysql image: 192.168.10.20:5000/mysql8:1.0 container_name: mysql8 restart: always networks: app_net: ipv4_address: 192.168.100.10 environment: MYSQL_ROOT_PASSWORD: MyStrongPass123 volumes: - /opt/mysql/data:/var/lib/mysql ports: - 3306:3306 redis-master: build: ./redis image: 192.168.10.20:5000/redis7:1.0 container_name: redis-master restart: always networks: app_net: ipv4_address: 192.168.100.21 command: redis-server --appendonly yes --requirepass RedisPass123 volumes: - /opt/redis/master:/data redis-slave: build: ./redis image: 192.168.10.20:5000/redis7:1.0 container_name: redis-slave restart: always depends_on: - redis-master networks: app_net: ipv4_address: 192.168.100.22 command: redis-server --appendonly yes --replicaof 192.168.100.21 6379 --masterauth RedisPass123 volumes: - /opt/redis/slave:/data networks: app_net: external: true name: app-network注意这里的networks.app_net.external: true对应之前手动创建的自定义网络。Compose 默认会创建一个新网络但为了保证 IP 规划和之前手动创建的网络一致这里显式引用外部网络。执行docker compose up -d docker compose ps可以看到 MySQL 和 Redis 主从全部就绪。这套编排文件的另一个好处是通过build和image两个字段同时指定可以先把镜像构建并推送到私有仓库别人直接docker compose pull就能部署不需要在每台机器上重新编译安装软件。5.3 多架构镜像构建x86 与 ARM 一网打尽现在的服务器架构不只有 x86_64ARM 服务器也越来越常见。要让基础镜像平台在两种架构上都能用最简单的是用docker buildx做多架构构建。先创建并使用多架构构建器docker buildx create --name multiarch --use docker buildx inspect --bootstrap然后构建并推送多架构镜像docker buildx build \ --platform linux/amd64,linux/arm64 \ -t 192.168.10.20:5000/base/rockylinux:8.10-20250427 \ --push \ .这样一次构建会同时生成 amd64 和 arm64 两个平台的镜像推送到 Registry 后各架构的服务器在拉取时 Docker 会自动选择对应平台镜像。这里有一个值得注意的点--push参数会把镜像直接推送到远程仓库否则多架构清单只存在于本地 buildx 缓存中。另外如果 Dockerfile 里有某些操作是平台相关的比如安装特定架构的二进制文件多架构构建时要用TARGETARCH参数做区分。基础镜像平台的构建尽量保持纯 rpm/dnf 操作因为 Rocky Linux 官方仓库本身就区分架构这正好是它的优势。5.4 镜像更新与安全补丁基线基础镜像平台不是构建一次就结束了操作系统安全补丁需要不断更新。我的建议是设置一个固定的重建周期比如每月一次从软件源拉取最新 rpm 包。重新构建基础镜像。跑一次基础的连通性测试和常用命令验证。推送到私有仓库更新版本标签。下游应用逐步滚动更新。整个过程要尽量自动化。如果每个版本都手工构建、手工验证这个平台很快会随着人员流动而无人维护。至少你要把 Dockerfile、构建命令、版本标签约定写进项目文档保证任何一个人拿着这份文档都能重建出一模一样的镜像。6. 常见问题与排查技巧实录6.1 典型问题速查表下面这张表是我在实际操作中常遇到的问题按“症状—可能原因—解决办法”整理建议先收藏再慢慢看。症状可能原因解决办法docker pull镜像非常慢或超时未配置镜像加速器或配置后未重启 Docker修改/etc/docker/daemon.json的registry-mirrors重启 docker基础镜像构建时dnf install报错软件源 baseurl 不可达或mirrorlist未注释检查 yum 源文件替换可访问的镜像源dnf clean all dnf makecache容器内date显示 UTC 时间未设置时区或未建立/etc/localtime软链接安装tzdata设置ENV TZAsia/Shanghai并ln -snf对应时区文件容器日志中文乱码LANG/LC_ALL未被设置为 UTF-8设置环境变量为en_US.UTF-8或按需安装中文字体挂载数据卷后容器内 permission denied宿主机目录权限和容器用户 UID 不匹配chown宿主机目录为容器用户 UID例如chown 1000:1000 /opt/mysql/data容器连接 MySQL 时报 Access denied密码认证方式或网络 ACL 问题使用自定义网络确认 MySQL 用户授权范围包含容器 IPRedis 主从不复制数据主从网络不通、replicaof地址写错或认证失败检查info replication中master_link_status确认masterauth和requirepass一致Docker Desktop 提示虚拟化未开启BIOS 中虚拟化开关未启用重启进入 BIOS开启 VT-x/AMD-V执行docker命令提示权限错误当前用户不在 docker 组usermod -aG docker $USER重新登录生效容器重建后 IP 变化使用默认 bridge 网络创建自定义网络并指定固定 IP私有仓库推拉镜像报http: server gave HTTP response私有仓库未配置 TLS客户端未添加 insecure-registries在daemon.json中配置insecure-registries并重启 Docker6.2 我们在实际项目里踩过的三个坑第一个坑是软件源配置不彻底。我第一次构建基础镜像时就只改了 BaseOS 源没管 AppStream结果装mysql-community-server时提示找不到包折腾半天才发现是 AppStream 仓库还指向官方源。所以配置软件源时最好一次性把所有带Rocky-*.repo的文件全处理掉别只盯着某一个文件。第二个坑是过度精简镜像导致排障工具缺失。有段时间我想让镜像尽量小连procps-ng都没装结果容器跑到一半要查内存和进程数里面连ps、free都没有只能硬着头皮重新打镜像。从那以后我就在基础镜像里固定保留procps-ng、util-linux、which这几个诊断必备的小工具成本很低收益却很明显。第三个坑是在容器里直接用 systemctl。RHEL 系用惯了 systemd总想在容器里systemctl restart mysql。但容器默认没有 init 进程systemd 跑不起来正确方式是直接执行服务二进制或者用构建脚本封装 start/stop 命令。这一点对从传统运维转容器的人来说特别容易踩。6.3 容器网络相关问题的排查思路容器网络问题是最难查的一类问题。我的排查顺序是先用docker network inspect app-network查看容器 IP 和网关是否正确。到容器里执行ping判断到目标 IP 能不能通如果ping不通看宿主机防火墙和自定义网络的安全组规则。如果端口通但应用连不上检查目标服务是否监听在错误的地址上。比如 Redis 默认bind 127.0.0.1容器内外部访问就会失败需要改bind 0.0.0.0或指定容器网卡地址。最后检查 DNS 解析如果容器之间用服务名访问失败检查容器是否在同一自定义网络里。逻辑上从底层连通性一层层往上排查通常不会漏掉问题。6.4 别忘了给基础镜像做安全加固这个点容易被忽略但对“企业级”来说特别重要。基础镜像里不应该包含多余的服务、多余的用户、弱口令密码。建议在构建脚本里加上以下措施删除默认密码为空的用户锁定不常用的系统用户。清空/var/log下历史日志避免把宿主机敏感信息带进镜像。不需要的网络服务一律不启动。设置dnf自动安装安全更新或者定期重新构建镜像。确保容器内没有硬编码的密钥和证书。安全加固做得好不好直接决定这套基础镜像平台能不能通过企业安全审计。技术细节再完美如果安全合规过不了生产环境依然上不了线。结尾最后分享一点个人体会这套基于 Docker 部署 Rocky Linux 的基础镜像平台我从最早的手工docker commit一路改到现在用 Dockerfile 加 Compose 加私有仓库的标准化流程期间也推翻过好几个版本的设计。最大的体会是基础镜像的构建一定要“标准化优先”不要为了某一个应用的突发需求往里面塞不相关的东西。一旦基础镜像开始失控所有依赖它的应用镜像都会跟着失控。另外有个小技巧我一直保留每次重新构建基础镜像后都会顺手跑一个容器执行基础自检脚本检查时区、字符集、软件源、关键工具、非 root 用户这几个项点确认没问题再推送到私有仓库。这个自检脚本不复杂也就十几行 shell但能在问题流到下游应用之前拦住绝大部分基础性错误。如果你正准备在公司搭建自己的基础镜像平台建议从 Rocky Linux 8.x 开始先把系统时区、软件源、基础工具、非 root 用户这四件事固化到 Dockerfile 里再基于它去构建 MySQL、Redis 等中间件。后面慢慢加入私有仓库、多架构构建、自动化重建流程这套平台就会越来越接近“企业级”的样子。希望这篇文章能给你一些参考少踩那些我踩过的坑。
返回列表