Docker——终于搞懂了
用了大半年的Docker,说实话,我一直没太搞懂。
不是不会用命令——docker run、docker ps、docker exec这些我早就背熟了。但每次用的时候总有一种不踏实的感觉:容器为什么会退出?数据到底存哪了?为什么我的镜像越来越大?这些问题一直悬在那里,像家里那个发出异响的空调——你知道它迟早会出问题,但不想去细想。能跑就行,别问那么多。
直到前不久项目部署出了一个问题,逼着我不得不把Docker从头理了一遍。折腾了几天之后,我终于可以摸着良心说一句:这次是真的懂了。
一、我理解Docker的方式
Docker最难搞懂的地方,我觉得不是命令,是它的概念模型。网络上有很多关于Docker的比喻,什么集装箱、标准化、轻量级虚拟机……但我总觉得那些比喻离我太远了,像隔着一层玻璃在看一个正在运转的码头,看不清细节,也不知道集装箱里的东西跟我有什么关系。
直到有一次,我想起以前租房子的时候签过一份租赁合同——把Docker想象成一套”移动公寓”,似乎就通顺了。
镜像(Image) 是一份公寓的蓝图。
你去宜家看了一个样板间,拍了很多照片,记住了布局、家具的位置、墙的颜色。有了这份蓝图,你可以在任何地方复刻出完全一样的房间。镜像就是你搭建容器的蓝图。
容器(Container) 是用那份蓝图搭出来的房间。
你拿到蓝图之后,在某一个地址(这台服务器上)把房间搭了出来。房间里有床、有桌子、有书柜——这些就是你的应用环境和依赖。你可以在这个房间里做任何事,但记住,你只是在”住”这个房间,不是在”搭建”它。这个区别很重要。
镜像仓库(Registry) 是一个样板间展示中心。
你可以在那里看到别人做好的各种风格的房间——有的适合做网站(Nginx镜像),有的适合做书房(MySQL镜像),有的自带工作区(Node.js镜像)。你不需要自己从零设计,只需要找到合适的样板,复制一份蓝图,然后在你自己的服务器上把房间搭出来。
数据卷(Volume) 是你自己带的行李箱。
房间是临时的,你可以搬进去住,也可以随时退租走人。但你的行李箱是你自己的,你带走它,里面的东西不会丢。Docker Volume做的就是这件事——把容器产生的数据挂载到宿主机上,容器可以销毁重建,数据还在。
这个比喻帮我解决了一个很大的困惑:容器不是虚拟机。它只是一个运行着的”房间”,和你的宿主机共用同一个”地基”(Linux内核)。它轻、快、随时可以拆掉重盖,所以不要往里面放重要的东西——要用数据卷。
二、搭建一个WordPress开发环境
拿我自己最熟悉的场景来说吧:我想在本地跑一个WordPress站点,方便开发主题和插件。
以前的做法是在电脑上装一套XAMPP或者MAMP,Apache、MySQL、PHP全装一遍。麻烦的是,万一你同时要维护两个不同PHP版本的项目,就得来回切换环境,还容易出问题。
用Docker之后,这件事变成了几条命令的事。
创建一个docker-compose.yml文件:
version: '3'
services:
db:
image: mysql:8.0
container_name: wp_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- db_data:/var/lib/mysql
ports:
- "3307:3306"
wordpress:
depends_on:
- db
image: wordpress:latest
container_name: wp_site
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wordpress
volumes:
- ./wp-content:/var/www/html/wp-content
- ./themes:/var/www/html/wp-content/themes
- ./plugins:/var/www/html/wp-content/plugins
volumes:
db_data:然后在终端里跑一句:
docker-compose up -d等一两分钟,在浏览器打开http://localhost:8080,WordPress安装界面已经在那里了。
更妙的是,我把主题的代码放在./themes文件夹里,修改之后不需要重建容器,刷新浏览器就能看到变化。插件同理。数据库存在db_data这个卷里,容器删了重建,数据还在。
这一下让我彻底明白了:Docker的真正价值,不是”容器”本身,而是”环境标准化”。
三、常用命令速查
记几个最常用的就够了,其他的遇到再查。
# 查看所有容器(包括停止的)
docker ps -a
# 查看所有镜像
docker images
# 进入容器内部(调试用)
docker exec -it 容器名 /bin/bash
# 查看容器日志
docker logs 容器名
# 停止并删除所有容器(慎用)
docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
# 清理所有未使用的镜像、容器、卷、网络
docker system prune -a
# 查看磁盘占用
docker system df四、遇到的坑和解决
坑一:端口被占用
启动容器的时候报port is already allocated。检查一下是不是有另一个容器占用了同一个端口,用docker ps看看。
坑二:容器一直重启
用docker logs 容器名看日志,大多数问题都能在这里找到线索。
坑三:镜像太大
尽量用官方镜像的alpine版本,体积小很多,比如node:18-alpine、python:3.11-alpine。
坑四:Windows下文件挂载慢
如果在WSL2环境下,把项目代码放在WSL的文件系统里,不要放在Windows的/mnt/c/路径下,I/O性能会提升不少。
五、写在最后
Docker这个东西,刚接触的时候会觉得有点绕,但一旦理解了它那几个核心概念,剩下的就顺了。它最大的好处,是把你从”配环境”这件事里解放了出来。
以前最怕换电脑,因为每次都要重新装一遍开发环境,还总有一些地方和以前不一样。现在所有的配置都在docker-compose.yml里,一台新电脑装上Docker,执行一条命令,整个环境就回来了。
不过也别把Docker神话了。它不是万能药,不适合所有场景。但如果你需要快速搭建开发环境、需要和团队保持一致的运行环境、需要把应用打包部署到不同的服务器上——那Docker确实很好用。
最后,如果你刚开始接触Docker,我建议你不要一开始就盯着那些复杂的集群编排(Kubernetes、Swarm)。先把单机版的docker-compose用好,把镜像、容器、卷这几个概念摸熟,就足以应付绝大多数日常开发了。
其他的,等遇到了再说。
2026年8月16日