想象一下,Docker就像一个超级高效、标准化的“物流和仓储系统”。
- 镜像: 就像是产品的设计图纸或者模具。它本身不是一个正在运行的东西,但它包含了一切制造一个产品所需的信息(比如操作系统、软件、代码等)。比如,“Ubuntu操作系统+Ngix服务器+我的网站代码”这一整套东西可以打包成一个镜像。这个镜像是静态的、只读的。
- 容器: 就是根据镜像这个模具生产出来的一个实实在在的“产品”或“货箱”。这个货箱是正在运行的,你可以打开它,使用它,修改它里面的东西(但不会影响模具)。一个模具可以制造出无数个一模一样的货箱。
理解了这两个核心概念,我们再来看命令,就会非常清晰了。命令就是对这套“物流系统”的操作指令。
Docker 常见命令详解
1. 查看和管理镜像(管理“模具”)
docker images
- 通俗解释: 查看我本地仓库里有哪些模具(镜像)。
- 就像: 你去模具仓库里,看看都有哪些产品的设计图。
- 会显示的信息: 模具名称(REPOSITORY)、版本标签(TAG,比如最新版
latest)、模具ID(IMAGE ID)、创建时间、大小。
docker pull [镜像名]:[标签]
- 通俗解释: 从远程的“模具中心仓库”(Docker Hub)下载一个模具(镜像)到我的本地仓库。
- 就像: 你觉得某个模具(比如一个预装了Node.js的模具)很好,你下订单把它从总部仓库拉到你的本地仓库。
- 例子:
docker pull ubuntu:20.04(下载一个Ubuntu 20.04操作系统的模具)。如果不写:标签,默认下载latest(最新版)。
docker rmi [镜像名或ID]
- 通俗解释: 删除本地的一个模具(镜像)。
- 就像: 你觉得某个模具没用了,从本地仓库里把它扔掉,腾出空间。
- 注意: 如果这个模具正在被某个“货箱”(容器)使用,你是不能直接删除的。需要先停止并删除容器。
2. 运行和管理容器(操作“货箱”)
这是最核心、最常用的一组命令。 docker run [参数] [镜像名] [命令]
- 通俗解释: 根据一个模具(镜像),制造并启动一个全新的货箱(容器)。这是最强大的命令!
- 就像: 你拿着一个“Ubuntu操作系统”的模具,下令:“开工!给我造一个货箱出来,并且马上运行它!”
- 常用参数(给“货箱”加规格):
-it: 这是两个参数-i和-t的组合。意思是交互式地运行容器,并给你分配一个命令行终端(shell)。这是为了让你能“进入”这个货箱内部进行操作。- 例子:
docker run -it ubuntu:20.04 /bin/bash。这就像是,你造好货箱后,不是在外面看,而是直接打开门钻进去,在里面输入命令。
- 例子:
-d: 后台运行。让这个货箱在后台静静地运行,不占用你当前的命令行窗口。- 例子:
docker run -d nginx。造一个Nginx服务器的货箱,让它自己在后台运行,你还可以继续用命令行做别的事。
- 例子:
--name [自定义名字]: 给这个货箱起个名字,不然Docker会随机分配一个奇怪的名字(如angry_borg)。- 例子:
docker run -d --name my-web-server nginx。
- 例子:
-p [主机端口]:[容器端口]: 端口映射。这是最关键的概念之一!- 通俗解释: 你的电脑(主机)就像一个港口。容器(货箱)内部的服务(比如Nginx,默认在80端口工作)有自己的小港口(容器端口)。你需要把货箱的小港口,连接到主机的大港口上,外界才能访问。
- 例子:
docker run -d -p 8080:80 nginx。意思是:把容器内部的80端口,映射到我主机(你的电脑)的8080端口。这样,你在浏览器访问http://localhost:8080,就能看到容器里Nginx的欢迎页面了。
-v [主机目录]:[容器目录]: 数据卷挂载。把主机上的一个目录/文件夹,“插”到容器里的一个目录上。这样容器里的数据就能持久化保存在主机上,不会因为容器的删除而丢失。- 例子:
docker run -v /home/my_data:/app/data ...。这就像给货箱外接了一个移动硬盘,所有写到/app/data的数据,实际上都保存在你电脑的/home/my_data里。
- 例子:
docker ps
- 通俗解释: 查看当前正在运行的货箱(容器)列表。
- 就像: 去码头看看现在有哪些货箱正在作业。
docker ps -a: 查看所有的货箱,包括已经停止运行的。这很重要,因为停止的容器依然占着一点空间和名字。
docker stop [容器名或ID]
- 通俗解释: 优雅地停止一个正在运行的货箱。相当于给它时间完成手头的工作再关门。
- 就像: 对货箱的管理员说:“准备下班了,把手头工作收尾,然后关灯锁门。”
docker start [容器名或ID]
- 通俗解释: 重新启动一个已经停止的货箱。注意,是启动已有的容器,不是创建新的。
- 就像: 让一个已经下班的货箱重新开始工作。它里面的所有设置、文件都保持不变。
docker rm [容器名或ID]
- 通俗解释: 删除一个已经停止的货箱。
- 就像: 把一个没用的空货箱拆解掉,腾出地方。
- 强力删除运行中的容器:
docker rm -f [容器名](不推荐初学者常用,除非卡死了)。
3. 与运行中的容器交互
docker exec -it [容器名] [命令]
- 通俗解释: 在一个正在运行的货箱(容器)里,执行一个命令。通常用
-it来启动一个交互式shell,从而“进入”容器。 - 和
docker run -it的区别:run是创建一个新容器并进入。exec是进入一个已经存在且在运行的容器。 - 例子: 我们的Nginx服务器在后台运行(
-d),我们想看看它内部的配置文件。docker exec -it my-web-server /bin/bash(进入这个名为my-web-server的容器内部)- 现在你会看到一个类似
root@容器ID:/#的提示符,说明你已经在容器里面了!可以执行ls,cat等命令。 - 输入
exit可以退出容器,回到主机 shell。
docker logs [容器名]
- 通俗解释: 查看这个货箱(容器)的“工作日志”。比如它启动时有没有报错,访问记录等。
- 就像: 调取货箱的监控录像和工作记录。
- 常用参数:
-f可以实时跟踪日志输出,就像tail -f命令一样。
总结一下工作流程
对于一个初学者,典型的Docker使用流程是这样的:
- 拉取镜像(获取模具):
docker pull nginx - 运行容器(制造货箱):
docker run -d --name my-nginx -p 8080:80 nginx - 检查状态(看看货箱):
docker ps - 访问测试(使用货箱服务): 浏览器打开
http://localhost:8080 - 查看日志(看看记录):
docker logs my-nginx - 进入容器(钻进货箱):
docker exec -it my-nginx /bin/bash - 停止容器(下班):
docker stop my-nginx - 再次启动(上班):
docker start my-nginx - 删除容器(拆解货箱):
docker stop my-nginx->docker rm my-nginx - 删除镜像(扔掉模具):
docker rmi nginx(确保没有容器用它)
继续用“物流系统”的比喻,来深入讲解Docker中数据卷挂载这个非常重要但又容易让人困惑的概念。
数据卷挂载的核心问题
还记得我们之前说的吗?
- 容器就像是一个个“货箱”,它是临时、可丢弃的。
- 镜像是“模具”,是只读的。
这就带来一个问题:如果我运行了一个MySQL数据库在容器里,往里面存了很多重要数据。当我删除这个MySQL容器(货箱)时,里面的所有数据就永远丢失了!这太可怕了! 数据卷挂载,就是为了解决这个“数据持久化”的问题。
生动的比喻:外接移动硬盘
你可以把数据卷挂载理解为:给临时货箱(容器)外接了一个移动硬盘。
- 没有数据卷挂载(危险!):
- 你的数据直接写在货箱(容器)内部。
- 结果: 货箱被拆(容器被删),数据就没了。
- 使用数据卷挂载(安全!):
- 你告诉Docker:“嘿,把这个货箱里的
/data文件夹,跟我主机上的/home/my_data文件夹连接起来(挂载)。” - 结果: 容器里的程序以为自己是在向内部的
/data写数据,但实际上,数据被实时同步地写到了你主机上那个实实在在的/home/my_data文件夹里。 - 好处:
- 数据持久化: 即使你把容器删了100遍,你主机上
/home/my_data里的数据都安然无恙。 - 方便备份: 你直接备份主机上的文件夹就行了,非常简单。
- 方便共享: 多个容器可以挂载同一个主机目录,共享数据。
- 数据持久化: 即使你把容器删了100遍,你主机上
- 你告诉Docker:“嘿,把这个货箱里的
两种主要的“外接硬盘”方式
Docker提供了两种主要的方式来实现这种“外接”,一种更直接,一种更专业。
方式一:绑定挂载 – “直接指定文件夹”
这就像你直接对Docker说:“把我电脑上这个明确的文件夹,挂载到容器里的那个文件夹。”
- 命令语法:
-v /主机/的/路径:/容器/内的/路径 - 比喻: 你拿着一个具体的U盘(比如
D:\my-mysql-data),插到了货箱上。 - 例子:
# 运行一个MySQL容器,并把主机的 /home/my-mysql-data 目录挂载到容器的 /var/lib/mysql(MySQL默认存数据的地方) docker run -d --name my-db \ -v /home/my-mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0 - 发生了什么?
- MySQL容器启动后,所有数据库文件都会写入
/var/lib/mysql。 - 因为这些写入操作被“重定向”了,所以数据实际上安全地存储在你主机的
/home/my-mysql-data目录下。 - 现在,你可以大胆地执行
docker rm -f my-db删除容器。然后重新用上面的docker run命令创建一个新容器,并挂载同一个目录。你会发现,你的数据库、表、数据全都恢复了!
- MySQL容器启动后,所有数据库文件都会写入
- 优点: 直观,你清楚地知道数据存在主机的哪个地方,方便直接查看和修改。
- 缺点: 依赖主机上特定的路径,移植性稍差。
方式二:命名卷 – “让Docker帮你管理”
这就像你对Docker说:“给我一个移动硬盘,挂到容器里的那个文件夹。至于这个硬盘在你电脑上的具体位置,你帮我管,我不关心。”
- 命令语法:
-v 卷名:/容器/内的/路径 - 比喻: 你向Docker物流系统申请一个“编号为mysql-data的专用移动硬盘”,然后让系统自动把它挂到货箱上。你不需要知道这个硬盘在仓库(你的电脑)里的实际位置。
- 例子:
# 运行一个MySQL容器,并使用一个名为“mysql-data”的命名卷 docker run -d --name my-db \ -v mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0 - 发生了什么?
- Docker会自动在它管理的特定区域(比如Linux下通常是
/var/lib/docker/volumes/)创建一个名为mysql-data的卷,并挂载到容器。 - 你对数据的管理通过卷名而不是路径来进行。
- Docker会自动在它管理的特定区域(比如Linux下通常是
- 如何管理这种卷?
docker volume ls:查看所有由Docker管理的“移动硬盘”(命名卷)。docker volume create my-vol:手动创建一个名为my-vol的卷。docker volume inspect mysql-data:查看mysql-data这个卷的详细信息,包括它在主机上的实际路径。docker volume rm mysql-data:删除一个卷。
- 优点:
- 移植性好: 你不需要关心主机路径,命令更通用。
- 备份和迁移方便: Docker提供了专门命令来管理卷。
- 更安全: 是Docker推荐的最佳实践。
总结与对比
| 特性 | 绑定挂载 | 命名卷 |
|---|---|---|
| 比喻 | 指定一个明确的U盘 | 申请一个编号的专用移动硬盘 |
| 主机位置 | 由用户指定明确路径 | 由Docker自动管理在特定区域 |
| 可移植性 | 差(依赖主机路径) | 好(只用卷名) |
| 备份/迁移 | 直接操作文件系统 | 使用docker volume命令 |
| 使用场景 | 开发环境(需要直接修改主机文件,如代码) | 生产环境(数据库数据、配置文件等) |
给你的实践建议
- 新手入门: 先从绑定挂载开始,因为它最直观。你能在主机上直接看到文件变化,有助于理解挂载的原理。
- 生产环境: 强烈推荐使用命名卷,这是更专业、更安全的方式。
- 核心原则: 任何你不想丢失的数据(数据库文件、用户上传的图片、日志文件等),一定要通过数据卷挂载的方式存到容器外部。
一句话记住数据卷挂载:它就是给容易消失的容器接上一个持久的外接硬盘,保证你的重要数据永不丢失! 现在,你可以试着运行一个MySQL或Nginx容器,用 -v参数体验一下数据卷挂载的神奇之处了!




