Docker
1. 核心概念
1.1 镜像(Image)= “安装包”
text
就像手机的 APK 安装包,或者游戏的安装光盘。
它是一份“模板”,包含了运行程序需要的所有东西(代码 + 环境 + 配置)。就像手机的 APK 安装包,或者游戏的安装光盘。
它是一份“模板”,包含了运行程序需要的所有东西(代码 + 环境 + 配置)。1.2 容器(Container)= “运行中的程序”
text
镜像安装后运行起来,就成了容器。
镜像 = 光盘(静态的)
容器 = 安装好的游戏正在运行(动态的)镜像安装后运行起来,就成了容器。
镜像 = 光盘(静态的)
容器 = 安装好的游戏正在运行(动态的)关系:
text
镜像(模板) --run--> 容器(实例)
↓
可以运行多个容器镜像(模板) --run--> 容器(实例)
↓
可以运行多个容器1.3 Docker = “一个管理工具”
text
帮你下载镜像、启动容器、管理容器的工具。
就像:
- 应用商店(下载镜像)
- 任务管理器(管理容器)帮你下载镜像、启动容器、管理容器的工具。
就像:
- 应用商店(下载镜像)
- 任务管理器(管理容器)1.4 Docker Hub = “镜像仓库”
text
类似 npm、Maven,存镜像的地方。
网址:https://hub.docker.com类似 npm、Maven,存镜像的地方。
网址:https://hub.docker.com1.5 生命周期图
text
┌─────────────────────────────────────┐
│ 镜像 (nginx:latest) │
│ 持久保存,不会自动删除 │
└─────────────────────────────────────┘
↓ docker run
┌─────────────────────────────────────┐
│ 容器 1 (my-nginx) │
│ 可以删除 │
└─────────────────────────────────────┘
↓ docker run
┌─────────────────────────────────────┐
│ 容器 2 (new-nginx) │
│ 可以删除 │
└─────────────────────────────────────┘
一个镜像 → 可以创建 N 个容器
删除所有容器 → 镜像依然存在┌─────────────────────────────────────┐
│ 镜像 (nginx:latest) │
│ 持久保存,不会自动删除 │
└─────────────────────────────────────┘
↓ docker run
┌─────────────────────────────────────┐
│ 容器 1 (my-nginx) │
│ 可以删除 │
└─────────────────────────────────────┘
↓ docker run
┌─────────────────────────────────────┐
│ 容器 2 (new-nginx) │
│ 可以删除 │
└─────────────────────────────────────┘
一个镜像 → 可以创建 N 个容器
删除所有容器 → 镜像依然存在2. 为什么需要 Docker
2.1 你肯定遇到过这些问题
text
❌ “在我电脑上能跑啊”
❌ “你这个 Node 版本不对”
❌ “缺少 xxx 依赖”
❌ “环境变量没配”
❌ “数据库连不上”❌ “在我电脑上能跑啊”
❌ “你这个 Node 版本不对”
❌ “缺少 xxx 依赖”
❌ “环境变量没配”
❌ “数据库连不上”2.2 Docker 的解决方案
text
✅ 把 代码 + 环境 + 配置 全部打包成一个镜像
✅ 任何人下载这个镜像,运行起来都一样
✅ 不管你是 Windows、Mac、Linux✅ 把 代码 + 环境 + 配置 全部打包成一个镜像
✅ 任何人下载这个镜像,运行起来都一样
✅ 不管你是 Windows、Mac、Linux类比:
text
没有 Docker:
你要自己装 Python → 装依赖 → 配数据库 → 调环境变量
(容易出错,每个人环境不一样)
有了 Docker:
别人打包好镜像 → 你一行命令运行
(开箱即用,100% 一样)没有 Docker:
你要自己装 Python → 装依赖 → 配数据库 → 调环境变量
(容易出错,每个人环境不一样)
有了 Docker:
别人打包好镜像 → 你一行命令运行
(开箱即用,100% 一样)3. 常用命令
3.1 下载镜像
bash
docker pull 镜像名:版本docker pull 镜像名:版本bash
# 下载 Node.js 镜像
docker pull node:18
# 下载 Nginx 镜像
docker pull nginx:latest# 下载 Node.js 镜像
docker pull node:18
# 下载 Nginx 镜像
docker pull nginx:latest3.2 运行容器
bash
docker run -d -p 本地端口:容器端口 --name 容器名 镜像名
``>
```bash
# 运行 Nginx,访问 http://localhost:8080 就能看到网页
docker run -d -p 8080:80 --name my-nginx nginxdocker run -d -p 本地端口:容器端口 --name 容器名 镜像名
``>
```bash
# 运行 Nginx,访问 http://localhost:8080 就能看到网页
docker run -d -p 8080:80 --name my-nginx nginx参数解释:
| 参数 | 含义 |
|---|---|
-d | 后台运行(不占终端) |
-p 8080:80 | 把容器的 80 端口映射到你电脑的 8080 端口 |
--name | 给容器起个名字 |
3.3 查看容器
bash
# 看正在运行的容器
docker ps
# 看所有容器(包括停止的)
docker ps -a# 看正在运行的容器
docker ps
# 看所有容器(包括停止的)
docker ps -a3.4 停止 / 删除容器
bash
# 停止
docker stop 容器名
# 删除
docker rm 容器名
# 一键停止并删除
docker rm -f 容器名# 停止
docker stop 容器名
# 删除
docker rm 容器名
# 一键停止并删除
docker rm -f 容器名重要区别:
| 命令 | 效果 | 类比 |
|---|---|---|
docker stop | 暂停(可恢复) | 关电脑 |
docker rm | 彻底删除(不可恢复) | 把电脑扔了 |
docker start | 重新启动 | 开电脑 |
3.5 查看镜像
bash
# 列出本地镜像
docker images
# 删除镜像
docker rmi 镜像名
# 清理所有悬空镜像(没用的)
docker image prune# 列出本地镜像
docker images
# 删除镜像
docker rmi 镜像名
# 清理所有悬空镜像(没用的)
docker image prune3.6 进入容器内部(调试用)
bash
# 进入容器的命令行
docker exec -it 容器名 bash# 进入容器的命令行
docker exec -it 容器名 bash3.7 文件操作
bash
# 容器 → 本地
docker cp 容器名:/容器内的文件路径 D:\本地路径
# 本地 → 容器
docker cp D:\本地文件 容器名:/容器内路径# 容器 → 本地
docker cp 容器名:/容器内的文件路径 D:\本地路径
# 本地 → 容器
docker cp D:\本地文件 容器名:/容器内路径3.8 清理命令
bash
# 清理所有停止的容器
docker container prune
# 清理所有悬空镜像
docker image prune
# 清理所有(容器 + 镜像 + 网络等)
docker system prune# 清理所有停止的容器
docker container prune
# 清理所有悬空镜像
docker image prune
# 清理所有(容器 + 镜像 + 网络等)
docker system prune4. Docker Compose
4.1 一句话理解
text
Docker = 管理单个容器
Docker Compose = 管理多个容器的编排工具Docker = 管理单个容器
Docker Compose = 管理多个容器的编排工具类比:
| 场景 | Docker | Docker Compose |
|---|---|---|
| 乐队 | 指挥一个乐手 | 指挥整个乐队 |
| 餐厅 | 管理一个厨师 | 管理整个后厨团队 |
| 足球 | 管理一个球员 | 管理整支球队 |
4.2 核心区别
| 维度 | Docker | Docker Compose |
|---|---|---|
| 管理对象 | 单个容器 | 多个容器(服务) |
| 命令 | docker run/build/stop | docker-compose up/down |
| 配置文件 | 无(命令行参数) | docker-compose.yml |
| 使用场景 | 简单应用 | 多服务应用 |
4.3 实际例子对比
用 Docker(每个单独启动):
bash
# 启动数据库
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123 mysql:8
# 启动 Redis
docker run -d --name redis redis:latest
# 启动 Web 应用
docker run -d --name web --link mysql --link redis myapp:latest# 启动数据库
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123 mysql:8
# 启动 Redis
docker run -d --name redis redis:latest
# 启动 Web 应用
docker run -d --name web --link mysql --link redis myapp:latest用 Docker Compose(一键启动):
yaml
# docker-compose.yml
version: "3"
services:
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: "123"
redis:
image: redis:latest
web:
image: myapp:latest
depends_on:
- mysql
- redis# docker-compose.yml
version: "3"
services:
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: "123"
redis:
image: redis:latest
web:
image: myapp:latest
depends_on:
- mysql
- redisbash
# 一键启动所有服务
docker-compose up -d
# 一键停止所有
docker-compose down# 一键启动所有服务
docker-compose up -d
# 一键停止所有
docker-compose down4.4 使用场景区分
| 场景 | 推荐工具 |
|---|---|
| 运行单个容器(如测试镜像) | Docker |
| 学习 Docker 基础 | Docker |
| 微服务架构(多个服务) | Docker Compose |
| 开发环境(数据库 + 缓存 + 应用) | Docker Compose |
| 生产环境大规模部署 | Kubernetes(更高级) |
5. 实战:运行 GitHub 项目
5.1 判断流程
text
┌─────────────────────────────────────┐
│ 看到 GitHub 项目 abc │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 看 README 有没有 docker run 命令 │
└─────────────────────────────────────┘
↓
有? 没有?
↓ ↓
直接 run 看有没有 Dockerfile
不用 clone ↓
有? 没有?
↓ ↓
clone 后 暂时没法用 Docker
自己构建 看其他安装方式┌─────────────────────────────────────┐
│ 看到 GitHub 项目 abc │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 看 README 有没有 docker run 命令 │
└─────────────────────────────────────┘
↓
有? 没有?
↓ ↓
直接 run 看有没有 Dockerfile
不用 clone ↓
有? 没有?
↓ ↓
clone 后 暂时没法用 Docker
自己构建 看其他安装方式5.2 情况 1:有现成镜像(直接 run)
bash
# 直接运行(会自动 pull 镜像)
docker run -d -p 3000:3000 作者名/abc
# 或者先 pull 再 run
docker pull 作者名/abc
docker run -d -p 3000:3000 作者名/abc# 直接运行(会自动 pull 镜像)
docker run -d -p 3000:3000 作者名/abc
# 或者先 pull 再 run
docker pull 作者名/abc
docker run -d -p 3000:3000 作者名/abc在任何目录都能执行!
bash
# 在桌面
cd C:\Users\19520\Desktop
docker run -d nginx
# 在 D 盘
cd D:\projects
docker run -d nginx# 在桌面
cd C:\Users\19520\Desktop
docker run -d nginx
# 在 D 盘
cd D:\projects
docker run -d nginx结果都一样! 因为容器运行在 Docker 的独立世界里。
5.3 情况 2:没有镜像(需要自己构建)
bash
# 1. clone 项目
git clone https://github.com/作者/abc.git
cd abc
# 2. 构建镜像
docker build -t abc .
# 3. 运行
docker run -d -p 3000:3000 abc# 1. clone 项目
git clone https://github.com/作者/abc.git
cd abc
# 2. 构建镜像
docker build -t abc .
# 3. 运行
docker run -d -p 3000:3000 abc5.4 快速判断表
| README 里有 | 操作 |
|---|---|
docker run 作者/xxx | 直接 run,不用 clone |
docker build -t xxx . | 需要 clone + 构建 |
docker-compose up | 需要 clone(因为有 yml 文件) |
| 只有源码,没提 Docker | 暂时没法用 Docker |
6. 前端常用场景
6.1 本地跑一个数据库测试
bash
# MySQL
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 --name mysql mysql:8
# Redis
docker run -d -p 6379:6379 --name redis redis
# MongoDB
docker run -d -p 27017:27017 --name mongo mongo# MySQL
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 --name mysql mysql:8
# Redis
docker run -d -p 6379:6379 --name redis redis
# MongoDB
docker run -d -p 27017:27017 --name mongo mongo6.2 快速搭建开发环境
yaml
# docker-compose.yml
version: "3"
services:
# 前端开发服务器
frontend:
image: node:18
command: npm run dev
ports:
- "3000:3000"
volumes:
- ./src:/app/src
# 后端 API
backend:
image: python:3.9
command: python app.py
ports:
- "8000:8000"
# 数据库
db:
image: mysql:8
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "123"# docker-compose.yml
version: "3"
services:
# 前端开发服务器
frontend:
image: node:18
command: npm run dev
ports:
- "3000:3000"
volumes:
- ./src:/app/src
# 后端 API
backend:
image: python:3.9
command: python app.py
ports:
- "8000:8000"
# 数据库
db:
image: mysql:8
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "123"bash
# 一键启动所有
docker-compose up -d# 一键启动所有
docker-compose up -d6.3 构建自己的前端项目
dockerfile
# Dockerfile(放在项目根目录)
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]# Dockerfile(放在项目根目录)
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]bash
# 构建镜像
docker build -t my-frontend .
# 运行
docker run -d -p 3000:3000 --name my-app my-frontend# 构建镜像
docker build -t my-frontend .
# 运行
docker run -d -p 3000:3000 --name my-app my-frontend6.4 用 Nginx 部署静态网站
bash
# 1. 把你的网页放在一个目录
mkdir D:\my-site
echo "<h1>Hello</h1>" > D:\my-site\index.html
# 2. 挂载这个目录到容器
docker run -d -p 8080:80 -v D:\my-site:/usr/share/nginx/html nginx
# 3. 浏览器访问 http://localhost:8080# 1. 把你的网页放在一个目录
mkdir D:\my-site
echo "<h1>Hello</h1>" > D:\my-site\index.html
# 2. 挂载这个目录到容器
docker run -d -p 8080:80 -v D:\my-site:/usr/share/nginx/html nginx
# 3. 浏览器访问 http://localhost:80807. 常见问题解答
7.1 容器运行在电脑的哪个目录?
答案: Docker 管理的专属目录。
Windows 上:
text
C:\ProgramData\Docker\windowsfilter\容器 ID\C:\ProgramData\Docker\windowsfilter\容器 ID\你不需要关心这个目录! Docker 帮你管理好了。
7.2 容器运行位置示意图
text
┌─────────────────────────────────────────────┐
│ 你的电脑 │
│ │
│ C:\Users\19520\Desktop ← 你的文件 │
│ D:\projects ← 你的文件 │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ Docker 的独立世界 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 容器 1 │ │ 容器 2 │ │ 容器 3 │ │ │
│ │ │ (Nginx) │ │ (MySQL) │ │ (Redis) │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │
│ │ 容器的文件存在: │ │
│ │ C:\ProgramData\Docker\... │ │
│ └───────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────┘┌─────────────────────────────────────────────┐
│ 你的电脑 │
│ │
│ C:\Users\19520\Desktop ← 你的文件 │
│ D:\projects ← 你的文件 │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ Docker 的独立世界 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 容器 1 │ │ 容器 2 │ │ 容器 3 │ │ │
│ │ │ (Nginx) │ │ (MySQL) │ │ (Redis) │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │
│ │ 容器的文件存在: │ │
│ │ C:\ProgramData\Docker\... │ │
│ └───────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────┘7.3 怎么访问容器里的内容?
方法 1:端口映射(最常用)
bash
docker run -d -p 8080:80 nginxdocker run -d -p 8080:80 nginxtext
容器内的 80 端口 → 你电脑的 8080 端口
↓
浏览器访问 http://localhost:8080容器内的 80 端口 → 你电脑的 8080 端口
↓
浏览器访问 http://localhost:8080方法 2:数据卷挂载(需要共享文件时)
bash
docker run -d -p 8080:80 -v D:\my-site:/usr/share/nginx/html nginxdocker run -d -p 8080:80 -v D:\my-site:/usr/share/nginx/html nginx方法 3:把文件复制出来
bash
docker cp 容器名:/容器内的文件路径 D:\本地路径docker cp 容器名:/容器内的文件路径 D:\本地路径7.4 删除容器会删除镜像吗?
不会!
text
✅ 删除容器不会删除镜像
✅ 镜像需要手动删除(docker rmi)
✅ 一个镜像可以创建无数个容器
✅ 容器是“消耗品”,镜像是“持久化”的✅ 删除容器不会删除镜像
✅ 镜像需要手动删除(docker rmi)
✅ 一个镜像可以创建无数个容器
✅ 容器是“消耗品”,镜像是“持久化”的类比:
| 概念 | 类比 | 删除后 |
|---|---|---|
| 镜像 | 游戏光盘 | 光盘还在,随时能安装 |
| 容器 | 安装好的游戏 | 游戏删了,重新安装就行 |
7.5 命令速查表
| 目的 | 命令 |
|---|---|
| 下载镜像 | docker pull 镜像名 |
| 运行容器 | docker run -d -p 端口:端口 --name 名字 镜像名 |
| 查看运行中容器 | docker ps |
| 查看所有容器 | docker ps -a |
| 停止容器 | docker stop 容器名 |
| 启动容器 | docker start 容器名 |
| 删除容器 | docker rm 容器名 |
| 强制停止并删除 | docker rm -f 容器名 |
| 查看镜像 | docker images |
| 删除镜像 | docker rmi 镜像名 |
| 进入容器 | docker exec -it 容器名 bash |
| 查看日志 | docker logs 容器名 |
| Compose 启动 | docker-compose up -d |
| Compose 停止 | docker-compose down |
8. 总结
text
核心概念:
✅ 镜像 = 安装包(持久化)
✅ 容器 = 运行中的程序(可删除)
✅ Docker = 管理工具
✅ Docker Compose = 批量管理多个容器
常用操作:
✅ docker run - 运行容器
✅ docker stop / rm - 停止 / 删除容器
✅ docker images / rmi - 查看 / 删除镜像
✅ docker-compose up/down - 一键启停多服务核心概念:
✅ 镜像 = 安装包(持久化)
✅ 容器 = 运行中的程序(可删除)
✅ Docker = 管理工具
✅ Docker Compose = 批量管理多个容器
常用操作:
✅ docker run - 运行容器
✅ docker stop / rm - 停止 / 删除容器
✅ docker images / rmi - 查看 / 删除镜像
✅ docker-compose up/down - 一键启停多服务
冷冷的火花