docker 和 Kubernetes 已经成为后端开发和运维绕不开的两个词。我见过太多人单独学 docker 时觉得挺简单,不就是 build、run、push 嘛;单独看 K8s 文档时也觉得自己懂了,Pod、Deployment、Service 概念能背得滚瓜烂熟。可真到要把一个项目从 docker 搬到 K8s 上跑起来,或者排查一个“容器启动失败”的问题时,就卡住了。这篇总结我打算换个思路,不讲那些谁都能查到的命令大全,而是把 docker 和 Kubernetes 这条学习路径上的核心痛点、常见误区和落地经验串起来讲,重点解决“为什么这么用”和“出问题了怎么查”这两个更实际的问题。不管你是刚接触容器化的新手,还是已经写了 Dockerfile 但还没搞懂 K8s 的开发者,这篇应该都能帮你把知识体系补完整。
1. Docker:搞懂镜像、容器与数据,才算真正入门
很多人学 docker 第一个动作就是执行 docker run nginx,看到能访问页面就觉得入门了。这其实只是“会用”,离“理解”还差得远。Docker 的底层逻辑其实就三件事:镜像怎么构建、容器怎么运行、数据怎么持久化。把这三点串起来,你才能理解为什么后来 K8s 里那么多设计都是围绕这些来做的。
1.1 镜像与容器:不是一回事
先说镜像和容器的关系。我经常拿“程序与进程”来打比方:镜像就是一个静态的、只读的模板,它包含了运行某个应用所需的操作系统层、依赖库、环境变量和启动命令;容器则是这个模板运行起来后的实例。同一个镜像可以同时跑出多个容器,每个容器之间相互隔离,但又共享同一个宿主机内核。
这个设计带来的好处是巨大的。以前部署一个 Java 应用,需要先在服务器上装 JDK、配环境变量、处理依赖冲突,换一台机器就要重复一遍;现在只需要把镜像 build 好,任何装了 Docker 的机器上都能 docker run 直接跑起来,行为完全一致。这也是为什么容器化能成为交付标准——它把“环境一致性”这个老大难问题直接解决了。
这里有一个新手很容易踩的坑:不要在容器里跑“需要长期保持状态的进程”却不做任何持久化处理。比如你用 docker 跑一个 MySQL,如果没挂载数据卷,容器一删,数据全部灰飞烟灭。后面专门有一节讲数据卷,这里先记住这句话:容器是“牲口”,不是“宠物”,随时可以杀掉重建,数据必须放外面。
1.2 数据卷与持久化:容器重启后数据还在吗
Docker 里面的数据持久化主要靠 Volume(数据卷)和 Bind Mount(绑定挂载)两种方式。Volume 是 Docker 管理的目录,适合存放数据库文件、应用上传的附件等;Bind Mount 则是把宿主机的一个目录直接映射进容器,适合开发环境改代码实时生效。
拿实际场景来说,用 Docker 跑 Redis 主从复制时,主节点和从节点都要挂载数据卷,否则容器重建后内存里的数据就丢了。我见过有人配置 redis 主从,明明命令都没写错,但每次重启容器后数据就没,折腾了半天才发现是没挂载持久化目录。如果你用 docker-compose 编排,volume 段的写法就是类似下面这样的:
yaml复制services:
redis-master:
image: redis:7
volumes:
- redis-master-data:/data
redis-slave:
image: redis:7
command: redis-server --slaveof redis-master 6379
volumes:
- redis-slave-data:/data
volumes:
redis-master-data:
redis-slave-data:
关键点在于:容器本身是无状态的,所有需要保留的数据必须写到挂载的卷里。这个思维转变特别重要,因为你一旦上到 Kubernetes,Pod 里的容器更是随时可能被重新调度到别的节点上,如果数据没有放到外部存储,Pod 重建后数据就没了。
1.3 容器网络:端口映射与通信
网络是 docker 里很容易让人懵的一部分。容器默认跑在一个隔离的网络命名空间里,宿主机直接访问不到容器的 IP。你需要用 -p 宿主机端口:容器端口 做端口映射,外部才能访问到容器内的服务。
比如 docker run -p 8080:80 nginx,意思就是访问宿主机的 8080 端口,流量会被转发到容器内的 80 端口。这个映射关系在单机环境下很直观,但到了 Kubernetes 里就会变成一个更复杂的网络模型。K8s 里每个 Pod 有自己的 IP,并且集群内所有 Pod 之间默认可以互相通信,不需要额外的端口映射。这个思路上的转变,是理解 K8s 网络的一个分水岭。
再说一个常见问题:如果同一个宿主机上要跑多个容器,它们之间怎么通信?最简单的办法是用 docker-compose 创建一个自定义网络,服务名就是域名,比如服务名叫 db,其他容器里直接用 db:3306 就能连上。这个设计到了 K8s 里变成了 Service 和 DNS 解析,原理相通,但抽象层次更高。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Docker 的日常操作:从镜像构建到部署的完整链路
上节讲了核心概念,这节我挑几个日常高频操作展开,包括提取镜像、构建镜像、青龙面板这类脚本依赖管理场景,以及用 IDEA 打包 Docker 镜像。这些都是我在实操中反复用到、且容易出错的地方。
2.1 镜像获取与加速:docker pull 也有讲究
docker pull 看起来只是拉取镜像,但很多人没意识到它背后有一整套缓存和分层机制。镜像是由多个只读层叠加而成的,pull 的时候只会拉取本地不存在的层,所以多次拉取同一镜像的不同版本时,公共层可以直接复用,省时省流量。
实操中比较棘手的是镜像源不稳定。如果你在国内网络环境下直接 docker pull,经常会出现超时或者下载缓
