ARTICLE DETAIL

建站实战干货

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

Docker容器化实战:从安装部署到Compose编排与排坑指南

2026/9/15 22:32:31 拓冰建站 浏览量
Docker容器化实战:从安装部署到Compose编排与排坑指南 先从一次真实的部署事故说起吧。上个月帮朋友把一个Spring Boot项目部署到新服务器他在本机跑得好好的接口一到服务器就报错查了半天发现是服务器上的JDK版本和MySQL编码跟本地不一致。类似的问题干了这么多年开发我遇到过太多次了。后来我把所有中间件、数据库、应用全部装进Docker容器里这种在我机器上能跑的尴尬就再也没出现过。Docker这个容器化工具说白了就是把你写的程序连同它依赖的运行环境、配置、数据存储方式打包成一个标准化单元扔到哪台机器上都能原样运行。这篇文章我想用一篇入门教程的体量把Docker怎么安装、怎么拉镜像、怎么启动容器、怎么用Compose编排以及那些最容易踩的坑一次讲透。不管你是刚接触容器的新手还是已经装了一半卡住的选手这文章都能帮上忙。1. 容器到底是什么先搞清楚你在折腾什么东西1.1 从环境不一致说起理解容器存在的意义开发环境、测试环境、生产环境三套环境配置不统一这是绝大多数项目事故的根源。你本地用的JDK 8服务器上是JDK 11某些API行为就不一样你本地MySQL是utf8mb4线上是utf8中文存储就乱码。传统解决方案是把配置文档写好让运维手工配但人总会犯错文档总会过期。容器化解决的思路是把应用本身和应用运行所需的操作系统级依赖打包在一起。Docker容器里的进程看到的世界是一个已经装好所有依赖的迷你Linux环境跟宿主机和其他容器互不干扰。这就相当于你搬家时不住别人布置好的出租屋而是直接把自己房间里的家居、电器、装修全部打包运过去放下就能住。那这个打包动作具体是怎么实现的Docker利用的是Linux内核的两个机制命名空间Namespace隔离进程、网络、文件系统的可见性Cgroups限制资源占用。容器里跑的还是宿主机内核只是通过隔离把进程装进了单独的盒子里。所以容器比虚拟机轻得多启动一个容器常常一秒钟都不到。1.2 Docker和虚拟机不是一个量级的选手很多人刚接触时会把Docker跟VMware、VirtualBox这类虚拟机软件放在一起比较。它们的核心目标确实有点像都是环境隔离但实现方式完全不同。虚拟机是虚拟出一套完整硬件然后在这套虚拟硬件上跑一个完整操作系统再在操作系统里跑应用。这一层层套下来镜像文件动辄几个GB启动时间按分钟算而且每一层都消耗真实的CPU、内存和磁盘资源。Docker容器直接共享宿主机内核不存在虚拟硬件层也不跑完整操作系统只打包系统里跟应用相关的那些库、二进制文件、配置文件。镜像体积小得多一个简单的Nginx镜像只有一百多MB启动时间毫秒级一台物理机能同时跑几十个容器没什么压力。对比项虚拟机Docker容器隔离级别硬件级虚拟化操作系统进程级隔离启动速度分钟级秒级以内镜像体积通常几个GB通常几十MB到几百MB资源占用每台虚拟机一套完整OS共享宿主机内核开销极小管理复杂度高需要各自维护OS低统一通过Docker命令管理从成本角度来看适合用虚拟机的是那些需要严格隔离内核、跑不同操作系统Windows和Linux并存的场景比如安全测试、多租户基础设施。而应用部署、中间件搭建、CI/CD流程容器化方案基本全面胜出。这也是为什么现在微服务架构几乎默认以容器作为交付载体。1.3 Docker仓库、镜像、容器三者之间的关系在我的实际使用经验里把这三个概念搞明白Docker就算入门了一半。镜像Image是一个只读的模板里面有操作系统基础层、运行环境、应用代码、环境变量、启动命令什么都定义好了。你可以把它理解成一套安装光盘内容固定不变。容器Container是镜像运行起来后的实例相当于你拿这套光盘装出来的一个正在运行的程序。一个镜像可以同时起多个容器每个容器里跑着互相隔离的进程数据互不可见。你在容器里做任何修改都不会影响原镜像除非你主动把这层改动提交成新镜像。仓库Registry就是存放镜像的云端仓库。最常用的是Docker Hub官方镜像源跟GitHub类似也有tag标签控制版本。你执行docker pull mysql:8.0就是从仓库里拉取镜像。实际使用中团队通常会搭建私有仓库比如Harbor或Docker Registry用于存放内部镜像避免直接依赖公共网络。这种仓库-镜像-容器的三层结构跟面向对象的类-实例概念非常相似镜像是类容器是用类创建出来的对象。类本身不占内存一旦被实例化就真正运行起来产生数据。2. 环境搭建装好Docker附赠一整套排坑指南2.1 Windows环境Docker Desktop WSL2的搭配Windows上装Docker绕不开Docker Desktop。它是Docker官方的图形化桌面工具集成了Docker引擎、命令行工具、Kubernetes集群也是目前Windows/macOS用户使用最丝滑的方式。安装前有一个前提条件要提前确认你的CPU必须支持硬件虚拟化并且BIOS里开启了VT-x/AMD-V。如果没开装完Docker Desktop启动时会直接报错。检查方法也很简单打开任务管理器点性能标签页右下角虚拟化一栏显示已启用就说明没问题。Docker Desktop安装完成后它会提示你启用WSL2Windows Subsystem for Linux 2。这里强烈建议直接同意因为新版Docker Desktop的后端就是跑在WSL2里的比旧版Hyper-V方案启动更快、内存占用更低。如果你电脑上已经有WSL2环境Docker Desktop会自动复用没有的话安装向导一般会自动帮你装好一个轻量的WSL2内核。安装包如果下载速度太慢可以考虑从Docker官网镜像仓库或者国内一些高校的镜像站下载安装包。装完后打开命令行输入docker version能看到客户端和服务端版本信息就表示环境已经就绪。很多人到这一步以为结束了其实还有一个重要操作就是给Docker配置镜像加速这点后面专门聊。2.2 Linux环境Ubuntu和CentOS的安装分歧Linux服务器上装Docker不建议用系统自带的包管理器直接装因为版本通常太旧。推荐使用Docker官方提供的安装脚本一条命令搞定curl -fsSL https://get.docker.com | bash这条脚本会自动检测你系统的发行版本添加Docker官方的apt或yum源装上最新稳定版引擎并配置开机自启。执行完记得把当前用户加到docker组不然每次执行docker命令都要加sudo很影响效率sudo usermod -aG docker $USER newgrp dockerCentOS用户如果系统版本较老7.x启动Docker时可能会遇到iptables或nftables的兼容性问题。比较常见的处理方式是升级内核到3.10以上或者在新版本Docker里调整存储驱动配置。这里我先卖个关子具体解决方案在第6章的常见问题排查里绝对是老CentOS用户经常会碰到的场景。2.3 Docker Desktop启动失败的经典报错一次完整的排查过程Docker Desktop failed to start because virtualisation support wasnt detected——这是Windows用户高频遇到的大坑几乎每个论坛都有人在问。出现这个报错按以下顺序排查准没错。第一步先确认虚拟化有没有在任务管理器里显示已启用。如果显示已禁用就去BIOS里找Intel Virtual Technology或SVM Mode改成Enabled重启电脑。笔记本用户还要注意一些虚拟化功能在插电和电池两种模式下可以分别配置别只设置了插电模式。第二步确认Windows功能面板里的适用于Linux的Windows子系统和虚拟机平台两个选项是否都勾选了。勾选后要重启电脑才生效。第三步如果上面都没问题打开管理员身份的PowerShell输入bcdedit /set hypervisorlaunchtype auto开启Windows Hypervisor加载。这个命令能解决一部分启动失败问题因为Docker Desktop需要Hypervisor层来运行WSL2后端。我印象很深的一次场景是用户电脑CPU型号是i7-12700BIOS里也开了VT但Docker Desktop就是起不来。最后发现是主板BIOS没更新CPU太新、微码版本不够Hyper-V无法正确识别。升级BIOS后问题消失。这种问题不一定每个人都能遇到但如果前面的常规方案都试过了还不行可以往这个方向排查。2.4 镜像加速一定要装的网络优化在国内网络环境下直接连Docker Hub拉镜像经常出现速度极慢或者拉到一半连接断开的情况。解决办法是给Docker配置镜像加速器。具体操作是打开Docker Desktop的Settings找到Docker Engine选项卡在配置文件里加上{ registry-mirrors: [ https://docker.1ms.run, https://docker.xuanyuan.me ] }保存后Docker会自动重启之后拉镜像速度会有质的提升。需要注意这些加速地址是社区维护的公共镜像代理稳定性会有波动如果哪天发现拉取又变慢了换一批可用的地址就行。生产环境的服务器建议优先搭建公司内部镜像仓库把基础镜像预先缓存到内网避免外部依赖。3. 核心命令实操手册从docker pull到docker compose3.1 镜像操作拉取、查看、删除镜像操作最常用的是这几个命令先做个速查# 拉取镜像格式为 仓库/镜像名:标签 docker pull nginx:latest docker pull mysql:8.0 # 查看本地已有的镜像列表 docker images # 删除镜像可以加多个镜像ID空格分隔 docker rmi nginx:latest # 查找Docker Hub上的镜像 docker search redis这里要重点提一下镜像标签的概念。mysql:8.0中间的8.0就是标签用来区分同一个镜像的不同版本官方镜像通常会有latest标签指向最新稳定版。我的建议是生产环境尽量指定精确版本不要用latest因为哪天执行docker pull时latest可能已经变成了一个新版本而你的应用并没有针对它做过测试。锁版本是可控性的一部分。如果镜像下载到一半断了重新执行docker pull会从断点处继续续传。实测下来大镜像的下载体验比HTTP下载好很多不用一遍遍从头拉。3.2 容器生命周期起停、进入、日志镜像拉下来之后真正的日常操作集中在容器生命周期管理上。先看几个最重要的# 基于镜像启动一个容器-d后台运行-p端口映射--name指定容器名 docker run -d --name mynginx -p 8080:80 nginx:latest # 查看正在运行的容器 docker ps # 查看所有容器含已停止的 docker ps -a # 停止/启动/重启容器 docker stop mynginx docker start mynginx docker restart mynginx # 进入容器内部打开一个交互式shell docker exec -it mynginx bash # 查看容器日志后面加 -f 可以持续跟踪输出 docker logs mynginx # 删除容器需要先停止 docker rm mynginxdocker run是最核心的命令参数比较多新手容易蒙圈。-p 8080:80表示把宿主机的8080端口映射到容器的80端口。宿主机端口可以随便选只要没被占用容器端口不能乱改因为是Nginx默认监听的端口。一旦你访问宿主机IP加8080端口Docker就会把流量转发到容器的80端口上。进入容器内部排查问题是我用得最多的场景。比如容器启动了但服务没起来第一件事就是docker exec -it 容器名 bash进去看看用ps aux看进程用cat看配置文件跟登录一台服务器没两样。3.3 数据卷容器删了数据还在用容器最大的坑之一就是容器一旦删除容器内部的所有数据也会跟着消失。如果你把MySQL直接跑在容器里哪天误执行了docker rm数据库里的数据就全没了。解决办法是数据卷Volume。数据卷是宿主机上的一块目录通过-v参数挂载到容器内部。容器往挂载目录里写的数据其实写到了宿主机上容器删除后数据依然保留。docker run -d --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -v /opt/mysql-data:/var/lib/mysql \ mysql:8.0这个命令把宿主机的/opt/mysql-data目录挂载到容器的/var/lib/mysql目录MySQL的数据文件就持久化在宿主机上了。下次想用新镜像版本升级MySQL只要把数据卷挂载到新容器数据不会丢。关于数据备份还有两种常见方式。一种是docker cp命令把容器内文件直接拷到宿主机另一种是docker run挂载一个目录后在宿主机上直接备份。实际生产运维中更推荐用专门的备份容器挂载同一个数据卷周期性执行数据库的mysqldump但这是后话入门阶段记住挂载数据卷这一条就够保命了。3.4 端口映射与Docker网络模式Docker默认创建三种网络模式bridge桥接模式、host主机模式、none无网络。默认是bridge容器分配一个内部IP通过NAT访问外网。端口映射就是在这个模式下工作的。host模式比较特殊容器不虚拟自己的网卡直接复用宿主机网络栈。好处是性能极高、没有端口映射的地址转换开销坏处是容易端口冲突。你跑了个监听8080的容器宿主机上的另一个程序就不能再用8080了。实际部署中用bridge模式加-p映射就够了。如果遇到容器之间要互相通信的场景比如后端容器要连接MySQL容器新手往往会去查MySQL容器的内部IP再写进配置里。这个方案能用但很脆弱容器重建后IP可能就变了。正确做法是创建一个自定义Docker网络让容器通过网络名互相访问# 创建自定义网络 docker network create myapp-network # 两个容器都加入这个网络 docker run -d --name mysql8 --network myapp-network -e MYSQL_ROOT_PASSWORD123456 mysql:8.0 docker run -d --name backend --network myapp-network -p 8080:8080 myapp:latest这样backend容器里直接访问mysql8:3306就能连上MySQL。Docker内置DNS会解析网络内的容器名。这个技巧在后面Docker Compose编排中会反复用到。4. 实操5分钟部署一个MySQL 8.0实例4.1 拉取镜像并启动容器现在我把前面讲的概念串起来做一次完整的MySQL部署。这是Docker入门最经典的一个实战项目搜索引擎上docker安装mysql8.0并使用的热度常年居高不下。第一步拉取MySQL 8.0镜像docker pull mysql:8.0第二步创建数据目录并启动容器mkdir -p /opt/mysql8/data /opt/mysql8/conf docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDRoot123456 \ -v /opt/mysql8/data:/var/lib/mysql \ -v /opt/mysql8/conf:/etc/mysql/conf.d \ --restart always \ mysql:8.0这里的--restart always值得重点讲。它表示容器退出或宿主机重启后Docker会自动把这个容器重新拉起来。生产服务器隔三差五会重启如果没有这个参数每次重启后都得手动docker start所有容器极其痛苦。添加这个参数后你部署的MySQL服务就跟宿主机开机自启的效果一样。MySQL 8.0的默认认证插件是caching_sha2_password如果你的客户端是旧版本的Navicat可能会连接时报认证失败。解决办法是在创建容器时加上参数docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDRoot123456 \ -e MYSQL_ROOT_HOST% \ -v /opt/mysql8/data:/var/lib/mysql \ mysql:8.0 --default-authentication-pluginmysql_native_password4.2 验证连接并配置编码容器起来后先确认一下MySQL是否正常在运行docker ps # 进入容器内部连接MySQL docker exec -it mysql8 mysql -uroot -p输入密码后就能进入MySQL命令行。这时可以执行几个SQL确认环境SELECT VERSION(); SHOW VARIABLES LIKE character_set_server;很多项目要求MySQL默认编码必须是utf8mb4否则遇到表情符号或部分中文生僻字会报错。Docker官方镜像的默认编码其实是utf8mb4但保险起见可以自定义配置文件。在刚才挂载的/opt/mysql8/conf目录下新建一个my.cnf[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci [client] default-character-setutf8mb4然后重启容器docker restart mysql8这个配置文件通过挂载目录直接生效不用进容器内修改维护起来非常清晰。以后想调max_connections、innodb_buffer_pool_size等参数直接改这个文件再重启容器就行。4.3 数据备份的两种方案数据备份是生产环境必须考虑的事情。第一种方案是进容器执行mysqldumpdocker exec mysql8 sh -c exec mysqldump -uroot -p$MYSQL_ROOT_PASSWORD mydb /opt/mysql8/backup.sql这里的$MYSQL_ROOT_PASSWORD是容器里的环境变量在容器启动时通过-e传入mysqldump可以自动读取。这种方式适合临时手动备份。第二种方案是写一个周期性的定时任务脚本放到宿主机的crontab里。辛苦活就不展开了但核心思路是备份命令要放到宿主机执行通过docker exec进容器备份备份文件写到宿主机挂载目录再同步到异地存储。5. 进阶一次搞定Docker Compose与微服务编排5.1 为什么要用Compose当你管理的容器从两三个变成七八个之后用docker run一条条去启动就变得很痛苦。每次都要记得完整的参数复制粘贴又容易出错容器之间的网络关系也要人工维护相当费劲。Docker Compose就是干这事的。它是Docker官方的容器编排工具用YAML格式的配置文件描述我要跑哪些容器、每个容器用什么镜像、怎么映射端口、挂载哪些卷、加入哪个网络然后一条docker compose up -d全部搞定。使用Docker Compose后项目的部署逻辑全部沉淀在docker-compose.yml这个文件里。换一台服务器只要把整个项目目录拷贝过去执行docker compose up -d所有服务就按配置跑起来了。这种一键部署体验对微服务项目价值尤其大因为微服务动辄十几个应用实例靠手工启动不现实。5.2 Compose文件语法深度解读先看一个包含Web应用和数据库的Compose文件示例这是最常见的组合模式version: 3.8 services: web: image: myapp:latest ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/mydb?useUnicodetruecharacterEncodingutf8 SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD} depends_on: - db restart: always db: image: mysql:8.0 ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: mydb volumes: - db-data:/var/lib/mysql restart: always volumes: db-data:几个关键点逐个说。services下面每个一级key就是一个容器名称可以随便取容器间用这个名称互相访问所以web应用里配置的数据库地址是db:3306而不是localhost:3306这个细节有太多人踩过坑。environment支持两种写法直接写值或者用${DB_PASSWORD}引用宿主机上的环境变量。好处是敏感信息不硬编码到配置文件里提交到Git仓库时不会泄露密码。实际项目中可以用.env文件统一管理这些环境变量Compose启动时会自动加载。depends_on表示服务依赖关系web服务会在db服务启动后再启动。但这里要特别说明它只保证容器启动顺序不保证服务真正就绪。MySQL容器起来了不代表MySQL进程已经准备好接受连接。如果web应用启动速度很快有时会遇到连接被拒绝的报错。解决方案是在应用代码里增加重试机制或者使用healthcheck健康检查但这些是进阶话题初学阶段先知道有这个问题存在就好。5.3 Redis主从架构的Compose实践最近热搜里redis docker compose 生产环境部署很火我就以Redis主从复制为例再走一遍Compose配置顺便演示一下多容器联动version: 3.8 services: redis-master: image: redis:7.0 container_name: redis-master ports: - 6379:6379 volumes: - ./redis-master-data:/data command: [redis-server, --appendonly, yes] restart: always redis-slave: image: redis:7.0 container_name: redis-slave ports: - 6380:6379 depends_on: - redis-master volumes: - ./redis-slave-data:/data command: [redis-server, --slaveof, redis-master, 6379, --appendonly, yes] restart: always这里slave容器通过--slaveof redis-master 6379自动识别主节点地址redis-master正是Compose网络里另一个容器的名称。执行docker compose up -d启动后用docker exec进入slave容器执行redis-cli info replication看到role:slave、master_link_status:up就说明主从复制已经建立。这套配置在单机开发环境模拟集群已经够用但如果真的要上生产还需要考虑Redis密码认证、持久化策略、哨兵高可用那是另一个重量级话题了。5.4 微服务项目如何用Compose落地微服务架构是Docker最典型的应用场景之一。一个标准微服务项目通常包含网关服务、若干个业务服务、注册中心Nacos/Eureka、配置中心、消息队列Kafka/RabbitMQ、缓存Redis、数据库MySQL/PostgreSQL。这些服务如果在同一台机器上手工部署每个都要安装对应的运行环境、配置依赖、管理启动脚本工作量巨大。而用Compose整个微服务生态可以统一管理。每个业务模块打成一个镜像统一在docker-compose.yml里定义服务关系一条命令启动所有依赖。给的配置思路是基础设施类的镜像直接用Docker Hub上的官方镜像应用类的镜像在自己的Dockerfile中构建。Compose支持build: ./backend语法可以在启动时自动构建镜像开发调试时尤其方便。当服务数量超过20个部署到多台服务器时就可以考虑Kubernetes了。Compose是Kubernetes的最佳前置技能把Compose玩熟理解K8s的Pod概念会容易很多。6. 高频问题排查实录收录那些最令人抓狂的报错6.1 镜像拉取慢不只是换源前面提到了配置镜像加速器这里再补充一个场景。有时候加速器也慢这时候可以检查是不是镜像本身特别大比如某些包含完整CUDA环境的AI镜像动辄好几个GB。网络稍有波动就很容易中断。我的建议是分两步走首先确认加速器配置没写错重启过Docker Desktop或Docker服务其次是拉取大镜像时不要干等可以用nohup后台拉取或者用screen/tmux挂一个会话避免SSH断开导致进程终止。实在不行就换一台网络条件好的机器把镜像拉下来用docker save导出成tar包再拷贝到目标服务器上用docker load导入。数据中心之间内网传输的速度通常比公网快几个数量级。6.2 docker需要sudo权限一条命令解决Linux上装完Docker后每次执行命令都提示权限不足这是新手期最容易烦躁的问题。报错信息一般是Got permission denied while trying to connect to the Docker daemon socket。原因很简单Docker守护进程的socket文件/var/run/docker.sock默认只允许root用户和docker组的用户访问。解决办法是把当前用户加到docker组sudo usermod -aG docker $USER newgrp docker执行完newgrp docker或者重新登录终端再执行docker ps就不会报错了。有些教程会告诉你用sudo chmod 777 /var/run/docker.sock千万别用这是把socket权限全部打开任何普通用户都能操作Docker本质上等于给了系统root权限安全风险极大。docker组方案才是官方推荐做法。6.3 Windows下连不上Docker API的npipe错误错误信息是Failed to connect to the Docker API at npipe:////./pipe/docker-desktop-linux-endpoint这是Windows环境特有的问题。核心原因是Docker Desktop客户端无法连接到Docker引擎常见于Docker Desktop没有正常运行、升级后卡住或WSL2子系统异常。排查思路按以下顺序来。第一检查Docker Desktop的鲸鱼图标状态如果是红色或黄色说明引擎没启动去Settings里检查WSL Integration确认本地的WSL发行版勾选了集成。第二如果图标正常但还是报npipe错误执行wsl --shutdown关闭WSL子系统再重新打开Docker Desktop这个操作能解决大量偶发性的API连接问题。第三检查防火墙或杀毒软件是否拦截了Docker Desktop的进程通信。6.4 容器启动后立即退出的通用排查法docker ps看不到容器docker ps -a能看到已退出的容器这是新手问得最多的问题之一。排查方法基本固定先看退出容器的日志。docker logs 容器名日志会直接告诉你崩溃原因。总结下来最常见的几类一是入口程序启动失败比如应用依赖的配置项没配、数据库连不上二是命令写错了比如command参数指定的程序路径不存在三是端口被占用容器启动时绑定宿主机端口失败四是启动命令在前台执行完直接退出比如Nginx没有加daemon off配置。最后一种情况很隐蔽。Docker要求容器至少有一个前台进程保持运行如果启动脚本执行完毕就退出容器就会自动停止。比如直接跑redis-server没问题因为它天然在前台运行但你写个shell脚本做了几个初始化动作后不加任何等待脚本结束容器就停了。解决方式是给命令加上前台运行参数或者用tail -f /dev/null挂住进程。6.5 磁盘空间被容器日志占满排障类问题里容器日志无限增长导致磁盘满是最容易被忽视的坑。每个容器的标准输出日志默认写到宿主机的/var/lib/docker/containers目录下不设上限的话一个高并发服务一天能写几个GB日志磁盘又被撑爆了。在daemon.json里给日志加个轮转限制{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }配置文件修改后重启Docker服务才会生效。对于已存在的容器这个配置不会自动回补需要重建容器才能应用新的日志策略。所以正确做法是先把配置写进daemon.json再启动所有容器。如果磁盘已经满了先把大日志文件清空再重启容器cat /dev/null 容器日志文件路径7. 我的Docker使用总结与建议7.1 学习路线从命令到编排到集群我见过太多人一上来就奔着Kubernetes去结果被一堆概念砸晕最后连Docker都没学明白。入门阶段把镜像、容器、数据卷、网络这几个概念吃透常用命令背完能把MySQL、Redis、Nginx这些中间件用Docker部署起来就已经解决了工作里的大部分实际问题。之后再去学Docker Compose理解服务编排的价值最后才是Kubernetes。7.2 生产环境使用Docker的经验与警示在实际生产环境中使用Docker有几点经验我觉得值得写在这里。第一镜像版本必须固定别用latest。生产环境要的是可复现latest每次拉取都可能不同出了问题很难回滚。第二不要在生产环境随意用docker exec改容器内部的东西。容器是不可变基础设施修改容器内部状态意味着你的环境漂移了下次重建容器这些修改会全部丢失。正确做法是修改Dockerfile或挂载的配置文件重新构建和启动。第三数据卷的备份和监控一定要做好。容器是可以随时删的但数据不行。数据库容器建议把数据卷放到独立的磁盘分区避免和系统日志、镜像文件争抢磁盘IO。第四记得给Docker配置日志轮转注意磁盘和内存监控。容器化之后进程统一由Docker管理监控也需要配套升级比如通过Prometheus和cAdvisor采集Docker的指标这样才能在磁盘被日志打爆之前收到告警。以上是我整理的全部内容。按照我个人的实际体会Docker的入门难度在同类工具里算是比较低的只要你理解了镜像-容器-仓库这个三元模型后面的操作基本都是命令的排列组合。真正有价值的是那些在排坑中总结出的经验——这也是我写这篇文章最想传达给大家的东西。