ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Docker入门实战:镜像、容器与Compose编排的核心要点

2026/9/18 23:04:43 拓冰建站 浏览量
Docker入门实战:镜像、容器与Compose编排的核心要点 简介面向Docker入门者与进阶开发者的万字级学习手册系统覆盖容器化技术从理论到实战的完整路径契合DevOps、微服务与自动化部署场景可为开发、运维、架构师快速搭建Docker知识体系。资源为单个PDF文档包大小约1004KBPDF格式便于跨设备阅读检索已有200人学习。全书按八大模块递进展开从容器与虚拟机本质差异入手说明镜像、容器、仓库三大核心概念随后针对Linux、Windows、macOS给出安装步骤、内核升级与镜像加速等避坑要点核心命令部分汇总容器生命周期、镜像管理及诊断调试的高频用法Dockerfile实践引入高效编写与多阶段构建思路数据卷与网络模式选择保障持久化与通信灵活性Compose编排用于多容器应用快速部署。文末的常见排错指南与进阶资源推荐让学习者既能查缺补漏也能规划后续学习路径是一份可反复查阅的实战型参考资料。1. 先把镜像和容器的边界想清楚再谈 Docker 入门真正卡住 Docker 新手的经常不是docker run的命令写不对而是镜像与容器这两个概念在脑子里揉成一团。有同事改了容器里的配置重启后改动全部消失原因就在容器的可写层太脆弱容器一删数据归零真正的持久化得靠数据卷或者把改动重新构建进镜像。这个场景背后是把「镜像、容器、仓库」三件事理解到位。这份指南从头到尾只围绕一条最短路径装好运行环境跑通 MySQL 与 Redis 主从把多个服务用 Compose 串起来再解决权限与日志这些必踩的坑。适合想快速上手又不愿意在概念上打太极的开发者与运维。2. 镜像、容器与仓库先把三层模型拆开Docker 和虚拟机最根本的分歧在边界上。虚拟机模拟了一整套硬件容器只是对操作系统内核能力的封装所以容器镜像小、启动快但也因此有了一个新手很难适应的特性容器不是用来「保存状态」的而是随时可以被销毁重建的。2.1 镜像的分层结构与容器可写层镜像内部由多个只读层叠加而成。Dockerfile 的每一条指令都可能生成一层FROM拉来的基础镜像是一组层RUN执行命令生成新层COPY和ENV也会参与。运行容器时Docker 在镜像之上追加一个可写层进程启动后只在这个薄层上写入。在容器内安装软件、改写配置写的就是这一层docker rm之后可写层连同数据一并销毁。这也是新手最常踩的第一个坑容器不是虚拟机重启容器不代表改动会保留。写一个最典型的 Node 应用 Dockerfile 来演示分层FROM node:20-alpine WORKDIR /app COPY package.json . RUN npm config set registry https://registry.npmjs.org npm install COPY . . CMD [node, server.js]这里COPY package.json .与RUN npm install的顺序很关键package.json先复制依赖安装独立成层业务代码后复制改动源码时npm install这层能直接命中镜像缓存。如果改成先把整个项目COPY . .再RUN npm install任何源码改动都会让这一层连带后面的依赖安装全部失效每次构建都要重新下载依赖。需要注意CMD只是默认启动命令它会被docker run后面追加的参数覆盖。例如docker run myapp node other.js执行的就不是server.js而是other.js。容器与虚拟机的差异直接决定资源规划和方案选型维度容器虚拟机隔离级别进程级硬件级镜像大小数十到数百 MB数 GB启动速度秒级分钟级可写层删除容器即销毁磁盘映射通常保留一台 2C4G 的机器可以跑十几个容器虚拟机则通常只能开两三台。这也是为什么微服务、CI 构建、本地开发环境都倾向于用容器编排。2.2 tag、仓库与版本漂移镜像仓库是镜像分发的中转站tag是仓库内镜像的版本标签。mysql:8.0.36里的8.0.36是具体版本不用 tag 只写mysql时Docker 默认补上latest。latest是个移动标签每次pull拿到的结果可能不一样生产环境一旦升级代码里连库的驱动行为就可能对不上。docker pull redis:7.2-alpine docker image inspect redis:7.2-alpine --format {{.Id}} {{.RepoDigests}}拉取时带alpine后缀镜像体积比完整版小一半以上适合测试环境inspect的--format只输出镜像 ID 和仓库摘要可以快速确认本地与远端是否一致。仓库地址的完整格式是registry.example.com/namespace/image:tag私有仓库会多出前缀pull时会拼接成完整地址。tag 的选择是稳定性问题不只影响体积。一个常见做法是开发环境用latest图方便测试与生产环境全部钉住具体版本号甚至钉住镜像摘要sha256:...从源头上切断版本漂移。3. 安装与初始化Windows、Linux 与镜像源加速安装工具本身不难难的是虚拟化环境识别、内核模块加载和镜像拉取速度。这几件事没理顺docker run前的最后一公里能卡上一整天。3.1 Windows 上 Docker Desktop 的三个前置条件Docker Desktop 依赖 WSL2 或 Hyper-V。安装器一般不失败常出问题的是启动时报virtualization support not detected或virtualisation support wasnt detected。这两个报错指向同一个问题BIOS 里的虚拟化没开或者 Windows 功能里的「适用于 Linux 的 Windows 子系统」与「虚拟机平台」没启用。用 PowerShell 检查当前环境systeminfo wsl --statussysteminfo输出里看到「虚拟化已在固件中启用」才算通过wsl --status确认默认版本是 2。排查顺序是开机进 BIOS打开 VT-x 或 AMD-V不同主板的选项名称不同常见叫 Intel Virtualization Technology 或 SVM Mode。在「启用或关闭 Windows 功能」里勾选「适用于 Linux 的 Windows 子系统」和「虚拟机平台」重启。重新打开 PowerShell 执行wsl --set-default-version 2再重启 Docker Desktop。提示Failed to start because virtualisation support wasnt detected多半是 BIOS 改动后没有彻底断电重启只点了 Windows 的重启不够部分主板需要关机再开机。WSL2 就绪后如果 Docker Desktop 还报failed to connect to the docker api at npipe:////./pipe/dockerDesktopLinuxEngine说明 Linux engine 没起来。先看系统托盘图标颜色再重启 Docker Desktop 服务还不行就打开 PowerShell 执行wsl --shutdown等几秒重新启动 Docker Desktop这个命令能清除 WSL2 的残留状态。3.2 Linux 安装apt 与 yum 两条路径Ubuntu/Debian 上安装 Docker Engine 的常见做法是先配置官方仓库再装软件包sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg这条命令的作用是下载 GPG 公钥并转成gpg格式-m 0755 -d创建 keyrings 目录是为了控制权限避免公钥文件被低权限用户覆盖。仓库加好之后安装sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin其中docker-ce是守护进程docker-ce-cli是命令行工具docker-compose-plugin提供docker compose子命令。CentOS/RHEL 上流程类似用yum-config-manager --add-repo加仓库然后安装同样的几个包。装好之后把普通用户加入 docker 组否则每条命令都要加sudosudo usermod -aG docker $USER newgrp docker docker versionnewgrp docker让当前终端立即生效但真正持久化要重新登录。如果已经加组还是报permission denied while trying to connect to the Docker daemon socket先确认两件事用户组有没有刷新以及systemctl status docker是否显示 failed。docker 组权限错误是入门阶段搜索量最高的报错之一多数情况不是权限配置错而是 daemon 压根没起来。3.3 镜像源加速镜像拉取慢主要是 Docker Hub 的连通性问题。Linux 上编辑/etc/docker/daemon.json{ registry-mirrors: [https://docker.mirrors.example.com] }保存后执行sudo systemctl restart docker。验证是否生效用docker info | grep -A 5 Registry Mirrors。不同网络环境下可用的镜像源不一样配置前先确认地址能访问填一个不通的加速地址会导致所有pull直接失败。Docker Desktop 在 Settings 里有图形化配置入口本质也是改同一个 daemon 配置。安装阶段最常见的三个问题汇总报错信息排查方向virtualisation support wasnt detectedBIOS 虚拟化开关、Windows 功能、WSL2failed to connect to the docker api at npipe://...Docker Engine 未启动、执行 wsl --shutdownpermission denied while trying to connect to the Docker daemon socket用户组未刷新、服务未启动4. 常用命令与实战从 MySQL 到 Redis 主从命令再多核心线索只有一条docker run把镜像变成容器exec进容器操作volume让数据留在宿主机。把这条线索走通剩下的都是参数排列。4.1 一个最小可复制的运行流程用 nginx 从拉取到清理走一遍docker run -d --name nginx-test -p 8080:80 nginx:alpine docker ps curl localhost:8080 docker exec -it nginx-test sh docker logs nginx-test docker rm -f nginx-test参数说明-d是后台运行--name给容器命名后续所有管理命令都靠这个名字定位-p 8080:80左侧是宿主机端口右侧是容器端口-it分配一个交互终端-f强制停止并删除容器。curl localhost:8080能返回 nginx 页面说明端口映射正常如果返回拒绝连接先看docker ps确认容器在不在再看 8080 端口有没有被防火墙挡住。4.2 持久化部署 MySQL 8.0数据库容器最忌讳可写层存数据所以数据卷是部署的重点docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDroot123 \ -e MYSQL_DATABASEapp \ -v mysql_data:/var/lib/mysql \ mysql:8.0-v mysql_data:/var/lib/mysql左侧mysql_data是命名卷数据由 Docker 管理右侧是容器内 MySQL 的数据目录。这样容器删除重建数据还在。MYSQL_DATABASEapp会在首次初始化时自动建库适合测试环境快速给应用接库。进入容器验证docker exec -it mysql8 mysql -uroot -proot123 SHOW DATABASES;如果是微服务连数据库应用容器里不要写localhost要用宿主机 IP 或host.docker.internal。生产环境建议把端口绑定收紧-p 127.0.0.1:3306:3306只暴露给本机避免数据库接口直接暴露在局域网。4.3 Redis 主从与 Compose 编排Redis 主从最容易踩的坑是--slaveof后面写宿主机 IP。容器有自己的网络命名空间从节点要连的是主节点的容器名docker run -d --name redis-master -p 6379:6379 redis:7.2-alpine docker run -d --name redis-slave -p 6380:6379 redis:7.2-alpine redis-server --slaveof redis-master 6379两个容器在同一个默认 bridge 网络里Docker 内置 DNS 能把redis-master解析成对应容器 IP所以--slaveof redis-master 6379里的主机名不需要改成本机 IP。-p 6380:6379依旧要映射端口不然宿主机访问不到从节点。多容器协作时推荐docker compose而不是手写一堆docker run。一个 mysql redis 应用的最小编排文件services: mysql8: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root123 volumes: - mysql_data:/var/lib/mysql ports: - 3306:3306 redis: image: redis:7.2-alpine ports: - 6379:6379 app: build: ./app depends_on: - mysql8 - redis ports: - 8080:8080 volumes: mysql_data:这里depends_on只保证容器启动顺序不保证服务就绪。mysql8 容器启动后 MySQL 可能还在初始化应用容器立刻去连数据库会失败。常见做法是在应用入口做重试连接或给 mysql8 配healthcheck后让app用condition: service_healthy。build: ./app会读取该目录下的 Dockerfile 构建镜像后端代码改动后只需docker compose build app docker compose up -d完成热更新。常用命令速查需求命令查看运行容器docker ps查看全部容器docker ps -a进容器docker exec -it 容器名 sh看实时日志docker logs -f 容器名删除容器docker rm -f 容器名清理悬空镜像docker image prune -f5. 收尾权限、健康检查与日志治理的三个技巧跑通基础流程之后剩下的都是「看起来能跑过几天出问题」的细节。这一章给三个高频场景的处理方式。第一个是权限问题。permission denied while trying to connect to the Docker daemon socket出现时先sudo usermod -aG docker $USER然后重新登录。只执行newgrp docker当前 shell 能生效但新开的终端可能仍然报错因为组信息还没刷新。挂载目录的权限问题则是另一类容器内进程的 uid 和宿主机目录属主不一致比如 MySQL 容器以 mysql 用户运行宿主机上的/data/mysql属主是 root写入时就会Permission denied。常见做法是-u $(id -u):$(id -g)覆盖容器用户或者把宿主机目录chown成对应 uid。第二个是健康检查。容器启动不等于服务就绪光靠depends_on不够。给 MySQL 加 healthcheck 的写法docker run -d --name mysql8 \ --health-cmdmysqladmin ping -h localhost -uroot -proot123 \ --health-interval5s \ --health-retries5 \ mysql:8.0--health-cmd在容器内执行返回 0 表示健康--health-interval是检查间隔--health-retries是连续失败几次后标记为 unhealthy。docker ps的 STATUS 列会显示healthy或unhealthy。这个状态在 compose 里也能用app服务加depends_on条件service_healthy就能真正等到 MySQL 就绪。第三个是日志治理。容器默认把所有 stdout 日志都写到宿主机跑久了可能占满磁盘。限制日志量的参数是--log-opt max-size10m --log-opt max-file3单个日志文件最大 10MB保留 3 份。容器部署到生产前的常用模板docker run -d --name app \ --log-opt max-size10m \ --log-opt max-file3 \ --health-cmdcurl -f http://localhost/health \ --restart unless-stopped \ -p 8080:80 \ app:1.0.0--restart unless-stopped表示机器重启后自动拉起容器但手动docker stop过的不会被拉起这比--restart always更适合带状态的容器。配合健康检查和日志上限一个容器就算在无人值守的机器上跑几个月也不用担心日志撑爆磁盘或服务静默挂掉。本文还有配套的精品资源点击获取