Docker 核心概念
Docker 基础概念理解:镜像、容器、仓库
1. 一句话概括主题
Docker 是一个把应用程序和它的运行环境打包在一起的工具,让你可以在任何地方都能用相同的方式运行程序。
2. 它是什么(口语化解释)
想象一下,你开发了一个网站,在你的电脑上运行得很好。但是当你要把它放到服务器上时,可能会遇到各种问题:服务器上的软件版本不一样、缺少某些依赖、配置不同等等。
Docker 就像是一个”打包盒”,它把你的应用程序和它需要的所有东西(比如操作系统、数据库、各种软件包)都打包在一起,形成一个”镜像”。这个镜像可以在任何安装了 Docker 的电脑上运行,而且运行效果完全一样。
简单来说:Docker 就像是一个”应用程序的集装箱”,一次打包,到处运行。
3. 能解决什么问题 + 为什么重要
解决的问题
-
“在我电脑上能跑”的问题
- 传统方式:开发环境、测试环境、生产环境可能不一样,导致程序在不同环境表现不同
- Docker 解决:打包后在任何环境运行都一样
-
环境配置复杂的问题
- 传统方式:每次部署都要手动安装各种软件、配置环境
- Docker 解决:一次配置,到处使用
-
资源浪费的问题
- 传统方式:每个应用需要独立的虚拟机,占用大量资源
- Docker 解决:多个容器共享操作系统,资源利用率高
-
部署速度慢的问题
- 传统方式:部署一个新环境可能需要几小时甚至几天
- Docker 解决:几秒钟就能启动一个容器
为什么重要
- 提高效率:开发、测试、部署更快
- 降低成本:更少的服务器资源,更低的运维成本
- 提高可靠性:环境一致,减少”在我电脑上能跑”的问题
- 便于扩展:可以轻松地启动多个相同的容器
4. 核心知识点拆解
4.1 镜像(Image)
镜像是什么:镜像就像是一个”模板”或者”快照”,包含了运行程序所需的一切。
类比理解:
- 镜像 = 安装光盘(只读的,不能修改)
- 一个镜像可以创建多个容器,就像一张光盘可以安装多台电脑
特点:
- 只读的:镜像本身不能被修改
- 分层的:镜像由多个层组成,可以复用
- 可复用的:一个镜像可以创建多个容器
示例:
# 查看本地有哪些镜像(就像查看你有哪些安装光盘)
docker images
# 从网上下载一个镜像(就像下载一个软件安装包)
docker pull nginx:latest4.2 容器(Container)
容器是什么:容器是镜像运行起来后的实例,就像用安装光盘安装好的系统。
类比理解:
- 镜像 = 安装光盘(模板)
- 容器 = 安装好的系统(实际运行的程序)
特点:
- 可运行的:容器是实际运行的程序
- 隔离的:每个容器都有自己独立的环境
- 轻量级的:多个容器共享操作系统内核
示例:
# 用镜像创建一个容器并运行(就像用光盘安装系统)
docker run -d nginx:latest
# 查看正在运行的容器(就像查看正在运行的程序)
docker ps4.3 仓库(Repository)
仓库是什么:仓库是存放镜像的地方,就像应用商店。
类比理解:
- Docker Hub = 官方应用商店(公共的,免费的)
- 私有仓库 = 公司内部的软件仓库(需要权限)
分类:
-
公共仓库(Docker Hub)
- 就像手机的应用商店,任何人都可以下载
- 例如:
nginx:latest、ubuntu:20.04
-
私有仓库
- 就像公司内部的软件仓库,只有公司员工可以访问
- 例如:
registry.company.com/myapp:latest
4.4 镜像与容器的关系
关系图:
镜像(Image)- 模板
├── 只读层 1
├── 只读层 2
└── 只读层 3
↓
容器(Container)- 运行实例
├── 只读层 1(来自镜像,不能修改)
├── 只读层 2(来自镜像,不能修改)
├── 只读层 3(来自镜像,不能修改)
└── 可写层(容器独有,可以修改)
关键点:
-
一个镜像可以创建多个容器
- 就像一张安装光盘可以安装多台电脑
- 每个容器都是独立的,互不影响
-
容器修改不影响镜像
- 容器中的修改只存在于可写层
- 删除容器后,修改会丢失
- 如果需要保存数据,需要使用数据卷
-
容器是镜像的运行实例
- 镜像 = 类(Class)
- 容器 = 对象(Object)
5. 示例代码(逐行注释)
示例 1:拉取并运行一个 Nginx 容器
# 第1步:从 Docker Hub 拉取 nginx 镜像
# 这就像从应用商店下载一个软件
docker pull nginx:latest
# 第2步:查看本地有哪些镜像
# 确认镜像已经下载成功
docker images
# 第3步:运行容器
# -d 表示在后台运行(detached mode)
# --name my-nginx 给容器起个名字,方便管理
# -p 8080:80 端口映射,把容器的80端口映射到主机的8080端口
# nginx:latest 使用的镜像名称
docker run -d --name my-nginx -p 8080:80 nginx:latest
# 第4步:查看运行中的容器
# 应该能看到 my-nginx 容器正在运行
docker ps
# 第5步:测试容器是否正常工作
# 在浏览器访问 http://localhost:8080
# 或者用 curl 命令测试
curl http://localhost:8080
# 第6步:查看容器日志
# 如果容器有问题,可以查看日志来排查
docker logs my-nginx
# 第7步:停止容器
# 停止运行中的容器
docker stop my-nginx
# 第8步:删除容器
# 删除已停止的容器
docker rm my-nginx示例 2:创建一个简单的 Web 应用容器
# 创建一个简单的 HTML 文件
echo "<h1>Hello Docker!</h1>" > index.html
# 运行一个 nginx 容器,并把当前目录挂载到容器中
# -v $(pwd):/usr/share/nginx/html 把当前目录挂载到容器的网页目录
# 这样修改 index.html 文件,容器中的网页也会更新
docker run -d \
--name my-web \
-p 8080:80 \
-v $(pwd):/usr/share/nginx/html \
nginx:latest
# 访问 http://localhost:8080 就能看到 "Hello Docker!"6. 常见错误与踩坑
错误 1:端口被占用
问题:运行容器时提示端口已被占用
Error: bind: address already in use
原因:主机的端口(如 8080)已经被其他程序占用
解决方法:
# 方法1:查看哪个程序占用了端口
lsof -i :8080
# 或者
netstat -tulpn | grep 8080
# 方法2:使用其他端口
docker run -d -p 8081:80 nginx:latest
# 方法3:停止占用端口的程序
# 根据 lsof 或 netstat 的结果,停止对应的程序错误 2:镜像不存在
问题:运行容器时提示找不到镜像
Error: Unable to find image 'myapp:latest' locally
原因:本地没有这个镜像,也没有自动拉取
解决方法:
# 方法1:先拉取镜像,再运行
docker pull myapp:latest
docker run myapp:latest
# 方法2:直接运行,Docker 会自动拉取(如果镜像存在)
docker run myapp:latest错误 3:容器名称冲突
问题:创建容器时提示名称已存在
Error: Conflict. The container name "/my-nginx" is already in use
原因:已经有一个同名的容器存在(可能是停止的)
解决方法:
# 方法1:删除旧的容器
docker rm my-nginx
# 然后再创建新容器
# 方法2:使用不同的名称
docker run -d --name my-nginx-2 nginx:latest
# 方法3:强制删除并重新创建
docker rm -f my-nginx
docker run -d --name my-nginx nginx:latest错误 4:忘记使用 -d 参数导致终端被占用
问题:运行容器后,终端被占用,无法输入其他命令
原因:没有使用 -d 参数,容器在前台运行
解决方法:
# 按 Ctrl+C 停止容器
# 或者新开一个终端窗口
# 下次运行时记得加 -d 参数
docker run -d nginx:latest错误 5:容器停止后数据丢失
问题:在容器中创建的文件,容器停止后就不见了
原因:容器中的数据存储在可写层,容器删除后数据就丢失了
解决方法:
# 使用数据卷来持久化数据
# 这样即使容器删除,数据也不会丢失
docker run -d \
-v my-data:/data \
nginx:latest
# 或者使用绑定挂载
docker run -d \
-v /host/path:/container/path \
nginx:latest7. 实际应用场景
场景 1:Web 应用部署
场景描述:部署一个 Node.js 开发的网站
传统方式:
- 在服务器上安装 Node.js
- 安装各种依赖包
- 配置环境变量
- 启动应用
- 配置 Nginx 反向代理
- 配置 SSL 证书
使用 Docker:
# 1. 编写 Dockerfile(定义如何构建镜像)
# 2. 构建镜像
docker build -t my-webapp:latest .
# 3. 运行容器
docker run -d -p 80:3000 my-webapp:latest
# 完成!就这么简单场景 2:数据库服务
场景描述:快速启动一个 MySQL 数据库用于开发测试
传统方式:
- 下载 MySQL 安装包
- 安装 MySQL
- 配置 MySQL
- 创建数据库和用户
- 配置防火墙
使用 Docker:
# 一条命令搞定
docker run -d \
--name mysql-dev \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=testdb \
-p 3306:3306 \
mysql:8.0
# 数据库就启动好了,可以直接连接使用场景 3:微服务架构
场景描述:运行多个相互关联的服务(前端、后端、数据库、Redis)
传统方式:
- 需要手动配置每个服务
- 需要手动配置服务之间的网络
- 部署复杂,容易出错
使用 Docker Compose:
# docker-compose.yml
version: '3.8'
services:
frontend:
image: nginx:latest
ports:
- "80:80"
backend:
build: ./backend
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
redis:
image: redis:latest# 一条命令启动所有服务
docker-compose up -d场景 4:CI/CD 流水线
场景描述:自动化构建、测试、部署
使用 Docker:
- 代码提交到 Git
- CI 系统自动构建 Docker 镜像
- 运行测试容器进行测试
- 测试通过后推送到镜像仓库
- 生产环境自动拉取新镜像并部署
8. 给新手的练习题(可立即实践)
练习 1:运行你的第一个容器
目标:运行一个 Nginx 容器,在浏览器中访问
步骤:
- 拉取 nginx 镜像:
docker pull nginx:latest - 运行容器:
docker run -d --name my-first-container -p 8080:80 nginx:latest - 在浏览器访问:
http://localhost:8080 - 查看容器状态:
docker ps - 查看容器日志:
docker logs my-first-container - 停止容器:
docker stop my-first-container - 删除容器:
docker rm my-first-container
预期结果:能看到 Nginx 的欢迎页面
练习 2:创建一个简单的网站
目标:创建一个 HTML 文件,用 Nginx 容器来展示
步骤:
- 创建一个
index.html文件,内容为<h1>我的第一个 Docker 网站</h1> - 运行容器并挂载当前目录:
docker run -d --name my-site -p 8080:80 -v $(pwd):/usr/share/nginx/html nginx:latest - 访问
http://localhost:8080查看你的网站 - 修改
index.html文件,刷新浏览器,看看变化
预期结果:能看到你创建的 HTML 内容,并且修改后能立即看到变化
练习 3:运行一个交互式容器
目标:进入一个 Ubuntu 容器,体验容器环境
步骤:
- 运行交互式容器:
docker run -it --name my-ubuntu ubuntu:20.04 /bin/bash20260130-运行交互式容器 - 在容器内执行命令:
ls- 查看文件列表pwd- 查看当前目录whoami- 查看当前用户apt update && apt install -y curl- 安装软件
- 退出容器:输入
exit - 查看容器:
docker ps -a(应该能看到已停止的容器)
预期结果:能够进入容器并执行命令,体验容器的隔离环境
练习 4:管理多个容器
目标:运行多个容器,练习容器的管理
步骤:
- 运行 3 个 nginx 容器,使用不同的端口:
docker run -d --name web1 -p 8081:80 nginx:latest docker run -d --name web2 -p 8082:80 nginx:latest docker run -d --name web3 -p 8083:80 nginx:latest - 查看所有运行中的容器:
docker ps - 分别访问
http://localhost:8081、8082、8083 - 停止所有容器:
docker stop web1 web2 web3 - 删除所有容器:
docker rm web1 web2 web3
预期结果:能够同时运行多个容器,并管理它们
9. 用更简单的语言再总结一遍(方便复习)
核心概念回顾
Docker 是什么:
- 就像是一个”应用程序的打包盒”
- 把你的程序和它需要的一切都打包在一起
- 打包后可以在任何地方运行,效果完全一样
三个核心概念:
-
镜像(Image)
- 就像”安装光盘”或”软件安装包”
- 是只读的模板,包含了运行程序所需的一切
- 一个镜像可以创建多个容器
-
容器(Container)
- 就像”安装好的系统”或”运行中的程序”
- 是镜像运行起来的实例
- 每个容器都是独立的,互不影响
-
仓库(Repository)
- 就像”应用商店”
- 是存放镜像的地方
- Docker Hub 是最大的公共仓库
关系:
- 镜像 → 容器:就像用光盘安装系统
- 一个镜像可以创建多个容器
- 容器删除后,数据会丢失(除非使用数据卷)
为什么重要:
- 解决了”在我电脑上能跑”的问题
- 部署更快、更简单
- 资源利用率更高
- 环境一致性更好
常用命令:
docker pull- 下载镜像(就像下载软件)docker run- 运行容器(就像启动程序)docker ps- 查看运行中的容器(就像查看运行的程序)docker stop- 停止容器(就像关闭程序)docker rm- 删除容器(就像卸载程序)
记住:
- 镜像 = 模板(不能修改)
- 容器 = 实例(可以运行和修改)
- 仓库 = 商店(存放镜像的地方)
📚 相关链接
- 03-基本命令.md - 学习更多 Docker 命令
- 01-容器基础操作.md - 学习如何管理容器
- 03-镜像基础操作.md - 学习如何管理镜像
- 05-Dockerfile编写指南.md - 学习如何创建自己的镜像