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

资讯详情

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

Docker新手完全指南:从CentOS 7内核升级到多阶段构建实战

Docker新手完全指南:从CentOS 7内核升级到多阶段构建实战 简介这份《Docker新手完全指南从入门到实战万字大全》面向零基础初学者与有一定经验的技术人员尤其适合对容器化技术感兴趣的开发者、运维人员和架构师。内容从容器与虚拟机的本质差异切入系统梳理镜像、容器、仓库三大核心概念并覆盖Linux、Windows、macOS跨平台安装配置及镜像加速避坑要点进而深入容器生命周期管理、镜像管理与诊断调试命令再延伸到Dockerfile多阶段构建优化、数据卷持久化、网络模式选择以及Docker Compose多容器编排实战最后附常见问题排错指南与进阶学习路径。资源包为1个PDF文档约1004KB结构按章节递进便于按模块查阅与系统学习。目前已有201人学习适合希望从零掌握容器化应用开发、测试与部署全流程的读者参考。1. 从一台 CentOS 7 老机器说起这份 Docker 万字指南到底能帮你省下多少折腾上周帮朋友救一台 CentOS 7 的测试机上面跑着三个 Java 服务部署方式是「scp 上传 jar 包 nohup 启动 手写 systemd」环境变量散落在三四个 shell 脚本里。他想迁到新机器结果光是把 JDK 版本、时区、字体、日志目录对齐就折腾了一整天。这种场景下Docker 的价值不是「新技术很酷」而是把「环境」这件事从口头约定变成可版本化的文件。这份《Docker 新手完全指南从入门到实战万字大全》就是围绕这条主线展开的从容器与虚拟机的本质差异讲起覆盖 Linux/Windows/macOS 三平台安装、镜像加速、容器生命周期命令、Dockerfile 多阶段构建、数据卷与网络模式、Docker Compose 编排最后落到常见排错。它适合两类人一是刚接触容器化、需要一份能照着敲的入门材料二是用过 Docker 但命令记不全、Dockerfile 写得随缘、Compose 只会up -d的从业者。下面我按「概念立住 → 动手复现 → 坑在哪」的顺序把这份资料里真正能落地的部分拆开讲。2. 容器隔离的底层逻辑与三平台安装为什么你的 CentOS 7 必须先升内核2.1 Namespace、Cgroups 与 Union FS 到底在干什么很多人背过「容器共享主机内核」但真到排查问题时说不清隔离边界在哪。Docker 在 Linux 上依赖三个内核特性Namespace 负责「看得见什么」Cgroups 负责「能用多少」Union FS 负责「镜像怎么分层」。Namespace 把进程的视图隔开——PID namespace 让容器内进程以为自己是 1 号进程Network namespace 给容器独立网卡和端口空间Mount namespace 隔离文件系统挂载点。Cgroups 则限制 CPU、内存、IOdocker run --memory 512m背后就是写 cgroup 的 memory.limit_in_bytes。Union FS常见实现是 overlay2把只读镜像层和可写容器层叠在一起容器删掉可写层就没了镜像层还在这就是「容器秒级启动」的物理基础。理解这三层之后很多现象就顺了容器里ps aux只看到自己的进程是 PID namespace容器内存超限被 OOM Kill是 Cgroupsdocker commit能把可写层固化成新镜像是 Union FS。资料里那张「虚拟机 vs 容器」对比表磁盘占用 GB 级 vs MB 级、启动分钟级 vs 秒级、性能损耗 15~30% vs 5%不是让你背数字而是让你在选型时能说清需要独立内核、强隔离、跑异构 OS 的场景选虚拟机需要快速交付、高密度部署、环境一致性的场景选容器。2.2 CentOS 7 升级内核与安装 Docker 引擎CentOS 7 默认内核 3.10overlay2 和部分 cgroup 特性支持不完整直接装 Docker 会出现存储驱动回退到 devicemapper、容器网络异常等玄学问题。资料里把「升级内核」放在第一步是对的我按它的思路补全可执行步骤# 1. 导入 ELRepo 仓库密钥并安装仓库 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-5.el7.elrepo.noarch.rpm # 2. 安装长期支持版内核kernel-lt yum --enablerepoelrepo-kernel install kernel-lt -y # 3. 把新内核设为默认启动项grub2 中索引 0 通常是新装的 grub2-set-default 0 grub2-mkconfig -o /boot/grub2/grub.cfg # 4. 重启然后用 uname -r 确认内核版本已变 reboot参数说明--enablerepoelrepo-kernel只在本次安装时启用 ELRepo 内核仓库避免污染默认源grub2-set-default 0里的 0 是菜单项索引如果机器上已有多个内核重启后先在 grub 菜单里确认新内核排在第几项再改。重启后uname -r应显示 4.x 或 5.x 的 lt 版本。内核就位后再装 Docker 引擎# 卸载可能存在的旧版本避免包冲突 sudo yum remove docker* -y # 添加阿里云 Docker CE 镜像源国内拉取快 sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装引擎、客户端和容器运行时 sudo yum install docker-ce docker-ce-cli containerd.io -y # 启动并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 验证 docker version这里docker-ce是引擎本体docker-ce-cli是命令行客户端containerd.io是底层容器运行时三者版本要匹配用同一个源安装就不会错。装完docker version能看到 Client 和 Server 两段信息Server 段出现说明守护进程正常。2.3 非 root 用户操作与镜像加速配置默认情况下只有 root 能调 Docker每次sudo很烦但直接把普通用户加进 docker 组等于给了它 root 权限docker 组能挂载宿主机根目录这是安全权衡测试机可以生产机要谨慎。资料里的做法sudo groupadd docker sudo usermod -aG docker $USER newgrp docker # 刷新当前会话的组或者重新登录newgrp docker只对当前终端生效新开终端如果还没生效就注销重登。验证方式是不加 sudo 跑docker ps。镜像加速解决的是拉取慢的问题编辑/etc/docker/daemon.json{ registry-mirrors: [ https://xxxxxx.mirror.aliyuncs.com ] }阿里云加速地址需要登录阿里云容器镜像服务控制台在「镜像加速器」页面拿到属于你账号的专属地址把xxxxxx替换掉。改完sudo systemctl daemon-reload sudo systemctl restart docker用docker info看 Registry Mirrors 字段确认生效。Windows/macOS 走 Docker Desktop在 Settings → Docker Engine 里改同样的 JSONWSL 2 后端和 VirtioFS 加速按资料提示开启即可这两个选项对文件 IO 性能影响明显。3. 容器生命周期与镜像管理把命令敲成肌肉记忆3.1 从 run 到 rm 的完整生命周期docker run是创建加启动的合体命令理解它的参数等于理解容器怎么跑起来。资料里给的 Nginx 示例值得逐参数拆docker run -d --name my-nginx -p 8080:80 nginx:1.23-d让容器在后台运行并返回容器 ID--name指定名字不指定会随机生成后续操作只能靠 ID-p 8080:80是端口映射格式为「宿主机端口:容器端口」这里把宿主 8080 映射到容器 80nginx:1.23是「镜像名:标签」不写标签默认latest生产环境强烈建议固定版本否则某天latest变了你的构建就翻车。访问http://localhost:8080看到 Welcome 页面说明映射成功。生命周期其余命令docker start/stop/restart 容器名或ID控制启停docker rm 容器删除已停止的容器加-f强制删除运行中的docker ps看运行中的容器docker ps -a看全部包括已退出的。一个高频误区是docker stop之后容器还在只是状态变 Exited磁盘和名字还占着要docker rm才真正清掉。3.2 镜像的拉取、查看、删除与推送镜像管理是日常最高频的操作资料里的命令够用但要补细节docker pull ubuntu:22.04 # 拉取指定版本 docker images # 列出本地镜像含镜像ID、大小 docker rmi redis:7 # 删除指定镜像 docker tag my-app:latest username/repo:tag # 打标签准备推送 docker push username/repo:tag # 推送到仓库docker rmi删不掉镜像时通常是还有容器哪怕已停止在引用它先docker ps -a找到容器删掉再删镜像。docker tag不复制镜像只是给同一个镜像 ID 加了个新名字所以打标签几乎不占空间。推送前要先docker login仓库地址默认 Docker Hub推私有仓库要写全registry.example.com/username/repo:tag。3.3 诊断三件套logs、exec、stats容器出问题时的第一反应应该是看日志而不是重装docker logs -f my-nginx # 实时跟踪日志-f 类似 tail -f docker logs --tail 100 容器ID # 只看最后 100 行 docker exec -it my-nginx /bin/bash # 进入容器交互式 shell docker stats # 实时看 CPU、内存、网络、IOdocker exec进容器排查时注意容器里往往没有 vim、curl、netstat 这些工具基础镜像越精简越缺所以别指望进去就能改配置更多是用cat、ls、env看状态。docker stats默认流式输出按 CtrlC 退出排查内存泄漏和 CPU 飙高时比宿主机 top 更直观因为它按容器维度聚合。4. Dockerfile 深度实践多阶段构建与镜像瘦身4.1 多阶段构建为什么能把镜像从 800MB 压到 20MB资料里的 Go 多阶段示例是这份文档最有价值的部分之一值得展开# 第一阶段构建环境带完整编译工具链 FROM golang:1.20 AS builder WORKDIR /app COPY . . RUN go build -o myapp # 第二阶段运行环境只要二进制和最小基础镜像 FROM alpine:3.18 WORKDIR /app COPY --frombuilder /app/myapp . EXPOSE 8080 CMD [./myapp]逻辑说明第一阶段golang:1.20镜像约 800MB包含 Go 工具链和依赖go build产出静态二进制myapp。第二阶段从alpine:3.18约 5MB重新开始用COPY --frombuilder只把二进制拷过来编译工具链、源码、缓存全部留在第一阶段被丢弃。最终镜像只有 alpine 加一个二进制通常 20MB 以内。AS builder是给阶段命名--frombuilder按名字引用多阶段可以有三四层比如测试阶段、构建阶段、运行阶段分开。4.2 四条最佳实践与构建缓存资料列的四条实践我按优先级重排并补原因第一固定基础镜像版本FROM node:18.17.0-alpine而不是node:latest避免上游更新导致构建结果漂移第二合并 RUN 减少层数RUN apt update apt install -y python3 rm -rf /var/lib/apt/lists/*注意rm要和install在同一层分开写清理不掉上一层的大小第三用.dockerignore排除node_modules、.git、target等否则COPY . .会把几百 MB 无关文件塞进构建上下文拖慢构建还可能覆盖容器内已装依赖第四非 root 运行USER nobody或自建用户降低容器逃逸后的影响面。构建与验证命令docker build -t my-app:v1 . # 构建末尾的点是构建上下文路径 docker history my-app:v1 # 看每一层大小定位哪层臃肿 docker scan my-app:v1 # 扫描已知漏洞需登录 Docker Hubdocker history是瘦身神器输出里 SIZE 列能直接看出哪条指令贡献了大体积常见元凶是没清理的包管理器缓存和误 COPY 的大文件。构建缓存方面Dockerfile 指令顺序影响命中率把不常变的装依赖放前面常变的COPY 源码放后面这样改代码不会导致重装依赖。5. 数据持久化与网络模式容器删了数据不能丢5.1 Volume 与 bind mount 的选择容器可写层随容器删除而消失所以数据库、上传文件这类数据必须外挂。Docker 提供两种方式Volume由 Docker 管理存在/var/lib/docker/volumes/和 bind mount挂宿主机任意目录。资料用的是命名卷docker volume create db-data docker run -d -v db-data:/var/lib/mysql mysql:8.0-v db-data:/var/lib/mysql把命名卷挂到 MySQL 数据目录容器重建数据还在。备份卷数据的技巧也实用docker run --rm -v db-data:/source -v $(pwd):/backup alpine tar czf /backup/db.tar.gz /source起一个临时 alpine 容器同时挂载数据卷和当前目录用 tar 打包。--rm让容器用完即删。选型上数据库、需要跨容器共享的数据用命名卷开发时挂源码、配置文件用 bind mount-v $(pwd)/html:/usr/share/nginx/html改宿主机文件容器内立即生效。5.2 四种网络模式与自定义网络资料列了 Bridge、Host、Overlay 三种实际常用的是前两种加自定义 bridge。默认 bridge 模式下容器之间只能用 IP 互访IP 还会变所以生产上更推荐自定义网络docker network create my-net docker run -d --net my-net --name web nginx docker run -it --net my-net --rm alpine ping web自定义网络自带 DNS容器可以直接用名字web互访这是它比默认 bridge 最大的优势。--network host让容器直接共享宿主机网络栈没有 NAT 转换性能最好但端口会冲突适合对网络延迟敏感且端口规划清晰的场景。Overlay 用于跨主机通信单机用不上等上 Swarm 或 K8s 再研究。6. Docker Compose 编排与常见问题排查6.1 用一份 YAML 管起 Web 加 DB单容器用docker run还行多容器手动敲命令就容易漏参数。Compose 把配置写进docker-compose.ymlversion: 3.8 services: web: image: nginx:alpine ports: - 80:80 volumes: - ./html:/usr/share/nginx/html depends_on: - db db: image: postgres:15 environment: POSTGRES_PASSWORD: example volumes: - pg-data:/var/lib/postgresql/data volumes: pg-data:depends_on只保证启动顺序先起 db 再起 web不保证 db 已经「就绪」所以应用层要有重试逻辑这是新手最容易误解的点。操作命令docker compose up -d # 后台启动所有服务 docker compose logs -f web # 跟踪某个服务日志 docker compose down --volumes # 停止并删除容器、网络、卷注意新版是docker compose空格作为 docker 子命令老版是docker-compose连字符独立二进制。如果报docker: unknown command: docker compose说明装的是老版或插件没装装docker-compose-plugin即可。6.2 排错清单端口、磁盘、启动失败、时区资料第七节的排错指南我按「现象 → 原因 → 解决」重写成可操作的清单端口冲突现象是docker run -p 8080:80报bind: address already in use。原因是宿主机 8080 被占。解决sudo lsof -i :8080找到 PID确认无用后kill -9 PID或换映射端口。磁盘空间不足现象是构建或拉取报no space left on device。原因是镜像层、停止的容器、悬空卷堆积。解决docker system prune -a --volumes清理所有未使用资源注意--volumes会删数据卷生产上先确认没有重要数据。容器启动即退出现象是docker ps看不到docker ps -a显示 Exited。原因是主进程执行完就退或配置错误。解决docker logs --tail 100 容器ID看最后日志docker inspect 容器ID看 State 和 Error 字段。时区不一致现象是容器内日志时间比本地少 8 小时。原因是容器默认 UTC。解决运行时加-e TZAsia/Shanghai或在 Dockerfile 里ENV TZAsia/Shanghai并装 tzdata。7. 进阶技巧把镜像体积和构建时间同时压下来前面几章把「能用」讲完了这一章讲「用得好」。我自己的习惯是每次写完 Dockerfile 先跑一遍docker build然后立刻docker history看层大小超过 200MB 的运行镜像就要问一句「多出来的是什么」。一个具体技巧是善用构建参数和缓存挂载。比如 Node 项目npm install是最慢也最占空间的一步可以这样写FROM node:18.17.0-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omitdev COPY . . CMD [node, server.js]关键在COPY package*.json ./和RUN npm ci放在COPY . .之前。这样只要依赖清单没变改业务代码时npm ci这层直接命中缓存构建从几分钟降到几秒。npm ci比npm install更适合 CI它严格按 lock 文件装且会先删 node_modules结果可复现。验证镜像是否真的瘦了除了docker history还可以用docker image inspect my-app:v1 --format {{.Size}}直接拿字节数或者dive my-app:v1这个第三方工具逐层看哪些文件被加进来又被删掉。另一个常被忽略的点是基础镜像选型能用 alpine 就用 alpine但要注意 alpine 用 musl libc某些依赖 glibc 的二进制比如部分预编译的 Java 原生库、Python 的 manylinux wheel跑不起来这时退回debian-slim更稳。我踩过一次坑一个 Python 服务在 alpine 上pip install某个包时编译失败折腾半天换python:3.11-slim五分钟解决所以选基础镜像前先确认依赖的 libc 要求。最后说验证方法镜像构建完不要只docker run看一眼就完事至少做三件事——用非 root 用户跑一遍确认权限没问题挂载数据卷重启容器确认数据还在用docker compose down docker compose up -d确认整套编排能从零拉起。从那以后我每次交付镜像前都强制走一遍这三步省下的返工时间远比这三分钟多。希望帮到你。本文还有配套的精品资源点击获取
返回列表