前言:为什么你需要学习Docker?
想象一下,你开发了一个应用程序,在你的电脑上运行完美,但当你把它交给同事或部署到服务器时,却出现了各种奇怪的问题。这就是著名的"在我机器上能运行"问题。
Docker就是解决这个问题的神器!它能确保你的应用在任何地方都能一致地运行,无论是在你的笔记本电脑、数据中心的服务器,还是在云平台上。
学习路径图:
#mermaid-svg-UV87x2eTQ78POaRx {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-UV87x2eTQ78POaRx .error-icon{fill:#552222;}#mermaid-svg-UV87x2eTQ78POaRx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UV87x2eTQ78POaRx .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-UV87x2eTQ78POaRx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UV87x2eTQ78POaRx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UV87x2eTQ78POaRx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UV87x2eTQ78POaRx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UV87x2eTQ78POaRx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UV87x2eTQ78POaRx .marker.cross{stroke:#333333;}#mermaid-svg-UV87x2eTQ78POaRx svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UV87x2eTQ78POaRx .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-UV87x2eTQ78POaRx .cluster-label text{fill:#333;}#mermaid-svg-UV87x2eTQ78POaRx .cluster-label span{color:#333;}#mermaid-svg-UV87x2eTQ78POaRx .label text,#mermaid-svg-UV87x2eTQ78POaRx span{fill:#333;color:#333;}#mermaid-svg-UV87x2eTQ78POaRx .node rect,#mermaid-svg-UV87x2eTQ78POaRx .node circle,#mermaid-svg-UV87x2eTQ78POaRx .node ellipse,#mermaid-svg-UV87x2eTQ78POaRx .node polygon,#mermaid-svg-UV87x2eTQ78POaRx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UV87x2eTQ78POaRx .node .label{text-align:center;}#mermaid-svg-UV87x2eTQ78POaRx .node.clickable{cursor:pointer;}#mermaid-svg-UV87x2eTQ78POaRx .arrowheadPath{fill:#333333;}#mermaid-svg-UV87x2eTQ78POaRx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UV87x2eTQ78POaRx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UV87x2eTQ78POaRx .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-UV87x2eTQ78POaRx .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-UV87x2eTQ78POaRx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UV87x2eTQ78POaRx .cluster text{fill:#333;}#mermaid-svg-UV87x2eTQ78POaRx .cluster span{color:#333;}#mermaid-svg-UV87x2eTQ78POaRx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UV87x2eTQ78POaRx :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
安装Docker
基础操作
Dockerfile
Docker Compose
网络与存储
实战项目
生产部署
本手册专为零基础小白设计,通过简单易懂的语言、实用示例和互动练习,带你从Docker小白成长为能够熟练使用Docker的开发者。
第一章:Docker基础概念
1.1 什么是Docker?
Docker是一种容器化技术,它允许你将应用程序及其所有依赖(代码、库、环境变量等)打包到一个轻量级、可移植的"容器"中。
类比理解:
┌──────────────────────────────────────┐
│ 宿主机操作系统 │
├───────────┬───────────┬──────────────┤
│ 容器1 │ 容器2 │ 容器3 │
│ (应用A) │ (应用B) │ (应用C) │
│ ┌─────┐ │ ┌─────┐ │ ┌─────┐ │
│ │应用 │ │ │应用 │ │ │应用 │ │
│ │代码 │ │ │代码 │ │ │代码 │ │
│ └─────┘ │ └─────┘ │ └─────┘ │
│ ┌─────┐ │ ┌─────┐ │ ┌─────┐ │
│ │依赖 │ │ │依赖 │ │ │依赖 │ │
│ │库 │ │ │库 │ │ │库 │ │
│ └─────┘ │ └─────┘ │ └─────┘ │
└───────────┴───────────┴──────────────┘
- 每个容器就像一艘集装箱船上的标准集装箱
- 每个集装箱(容器)都包含特定的货物(应用程序)
- 无论船(服务器)是什么类型,集装箱都能被正确装卸和运输
- 集装箱之间相互隔离,互不影响
💡 小贴士:Docker容器共享宿主机的操作系统内核,而虚拟机需要运行完整的操作系统,因此容器更轻量、启动更快。
1.2 Docker架构
Docker采用客户端-服务端架构,主要组件包括:
┌───────────────────────────────────────────────────────────────┐
│ 宿主机 │
├───────────────────┬───────────────────────────┬───────────────┤
│ Client │ Docker Daemon │ Registry │
│ (docker命令行) │ (dockerd, containerd) │ (Docker Hub) │
└─────────┬─────────┴─────────────────┬───────┴───────┬───────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Docker CLI │ │ Container Runtime│ │ Image Store │
└─────────────────┘ └──────────────────┘ └──────────────┘
- Docker CLI:命令行界面,用于向Docker守护进程发送命令
- Docker Daemon:Docker守护进程,负责管理镜像、容器、网络和卷等
- Container Runtime:容器运行时(如containerd),负责运行容器
- Registry:镜像仓库,用于存储和分发Docker镜像
1.3 Docker vs 虚拟机
| 架构 | 直接运行在宿主机操作系统上 | 运行在Hypervisor上 |
| 资源占用 | 轻量级(MB级别) | 重量级(GB级别) |
| 启动速度 | 秒级 | 分钟级 |
| 隔离性 | 进程级隔离 | 完整操作系统隔离 |
| 性能 | 几乎无损耗 | 有性能损耗 |
关键区别:
┌───────────────────┐ ┌───────────────────┐
│ 虚拟机 │ │ Docker │
├─────────┬─────────┤ ├─────────┬─────────┤
│ Guest OS│ 应用 │ │ 应用 │ 依赖 │
├─────────┼─────────┤ ├─────────┼─────────┤
│ Hypervisor │ │ Docker │ │
├─────────┼─────────┤ ├─────────┼─────────┤
│ Host OS │ │ │ Host OS │ │
└─────────┴─────────┘ └─────────┴─────────┘
1.4 Docker核心概念
镜像(Image)
- Docker的"蓝图"或"模板"
- 包含运行应用程序所需的一切
- 只读层,不可修改
容器(Container)
- 镜像的运行实例
- 镜像 + 可写层
- 应用程序实际运行的地方
仓库(Repository)
- 存储Docker镜像的地方
- 最常用的公共仓库:Docker Hub
Docker Hub上最受欢迎的镜像:
- 数据库:
- PostgreSQL(1B+ pulls,14502 stars)
- MySQL(1B+ pulls,15899 stars)
- MongoDB(1B+ pulls,10623 stars)
- 开发环境:
- Node.js(1B+ pulls,13983 stars)
- OpenJDK(1B+ pulls,4067 stars)
- Golang(1B+ pulls,5063 stars)
- PHP(1B+ pulls,7790 stars)
Dockerfile
- 创建Docker镜像的"配方"
- 包含一系列指令
💡 避坑指南:镜像是静态的,容器是动态的。你可以从同一个镜像启动多个容器实例。
1.5 Docker Engine更新渠道
Docker Engine提供两种更新渠道:
- Stable(稳定版):经过充分测试的正式发布版本
- Test(测试版):预发布版本,用于测试新功能
生产环境建议使用Stable渠道,开发环境可考虑使用Test渠道体验新功能。
第二章:安装Docker
2.1 Windows系统安装
下载Docker Desktop:
- 访问 Docker官网
- 点击"Download for Windows"
安装过程:
- 双击下载的安装文件
- 按照向导提示进行安装
- 建议勾选"Install required Windows components for WSL 2"
启动Docker:
- 安装完成后,Docker会自动启动
- 检查系统托盘,看到鲸鱼图标表示Docker正在运行
验证安装:
在命令提示符或PowerShell中输入:
> docker –version
Docker version 24.0.7, build afdd53b
💡 小贴士:Windows 10家庭版需要额外安装WSL 2(Windows Subsystem for Linux 2)。安装后可能需要重启电脑。
许可说明:Docker Desktop 对于个人用户、教育机构和中小型企业是免费的。大型企业(超过250名员工或年收入超过1000万美元)需要购买商业许可。
2.2 macOS系统安装
下载Docker Desktop:
- 访问 Docker官网
- 点击"Download for Mac"
安装过程:
- 双击下载的.dmg文件
- 将Docker图标拖到Applications文件夹
- 在Applications中双击Docker.app启动
验证安装:
在终端中输入:
> docker –version
Docker version 24.0.7, build afdd53b
2.3 Linux系统安装(Ubuntu 22.04示例)
# 1. 更新软件包索引
sudo apt update
# 2. 安装必要的软件包
sudo apt install -y docker.io
# 3.启动 Docker 服务
sudo service docker start
# 6. 验证Docker是否正确安装
> sudo docker run hello-world
配置国内镜像加速器
sudo mkdir –p /etc/docker
sudo nano /etc/docker/daemon.json
插入内容
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}
保存并退出编辑器(在 nano 中按 Ctrl+O 回车保存,Ctrl+X 退出)。 重启 Docker 服务,使配置生效:
sudo service docker restart
查看 Docker 信息,确认镜像加速器是否生效:
docker info
输出中应包含:
127.0.0.0/8
Registry Mirrors:
https://docker.1ms.run/
https://docker.xuanyuan.me/
Live Restore Enabled: false
测试拉取镜像:
docker pull hello–world
如果成功,会显示拉取镜像及运行容器的相关信息运行docker:
sudo docker run hello–world
显示信息
Hello from Docker!
This message shows that your installation appears to be working correctly.
💡 避坑指南:安装后,普通用户无法直接运行Docker命令。解决方法:
> sudo usermod -aG docker $USER
> newgrp docker # 或者重启终端
注意:以上以Ubuntu为例,其他Linux发行版的安装命令请参考Docker官方安装文档。
2.4 Docker Desktop功能详解
Docker Desktop不仅包含Docker Engine,还提供了一系列增强功能:
- Docker Engine:强大的容器运行时,提供高性能和可靠的容器化应用支持
- Docker CLI:灵活的命令行界面,提供精确的容器控制
- Docker Compose:简化多容器应用的管理
- Docker Build:简化容器镜像构建过程
- Docker Kubernetes:内置Kubernetes支持,无需外部集群即可本地开发
- Volume Management:有效的数据管理解决方案
- Synchronized File Shares:实时同步主机和容器间的文件
- Docker Debug:高级故障排除工具
- Hardened Docker Desktop:增强的容器隔离和安全性
- VDI Support:虚拟桌面基础设施集成
- Docker Private Extensions Marketplace:定制化扩展功能
2.5 验证安装
无论哪个平台,安装完成后运行以下命令:
> docker run hello-world
如果看到类似以下输出,说明Docker安装成功:
Hello from Docker!
This message shows that your installation appears to be working correctly.
💡 小贴士:docker –version 只验证了客户端。docker run hello-world 验证整个Docker引擎(客户端+守护进程)都已正确安装并运行。
第三章:Docker基础操作
3.1 第一个Docker容器
让我们运行一个简单的Nginx Web服务器:
> docker run -d -p 8080:80 –name my-nginx nginx
参数解释:
- -d:后台运行容器(detached模式)
- -p 8080:80:将宿主机的8080端口映射到容器的80端口
- –name my-nginx:给容器命名
- nginx:要使用的镜像名称(如果本地不存在,Docker会自动从Docker Hub拉取官方nginx镜像)
💡 小贴士:docker run 命令实际上融合了 docker pull(如果镜像不存在)、docker create、docker start 三个步骤。
验证:
3.2 常用Docker命令
容器管理
# 列出正在运行的容器
> docker ps
# 列出所有容器(包括停止的)
> docker ps -a
# 停止一个容器
> docker stop my-nginx
# 启动一个已停止的容器
> docker start my-nginx
# 重启容器
> docker restart my-nginx
# 删除容器
> docker rm my-nginx
# 查看容器日志
> docker logs my-nginx
# 进入正在运行的容器
> docker exec -it my-nginx bash
# 查看Docker磁盘使用情况
> docker system df
镜像管理
# 列出本地镜像
> docker images
# 拉取镜像(从Docker Hub)
> docker pull ubuntu:22.04
# 删除镜像
> docker rmi nginx
# 构建镜像(基于Dockerfile)
> docker build -t my-app:1.0 .
💡 避坑指南:删除正在运行的容器前,需要先停止它:docker stop container_id && docker rm container_id,或者直接使用docker rm -f container_id强制删除。
3.3 实战练习:运行Python应用
创建一个简单的Python应用:
> mkdir python-app
> cd python-app
> echo "from http.server import HTTPServer, BaseHTTPRequestHandler
class SimpleHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b'Hello from Docker!')
if __name__ == '__main__':
server = HTTPServer(('0.0.0.0', 8000), SimpleHandler)
server.serve_forever()" > app.py
运行Python应用容器:
> docker run -d -p 8000:8000 -v $(pwd):/app -w /app python:3.11 python app.py
访问 http://localhost:8000 查看结果
命令解释:
- -v $(pwd):/app:将当前目录挂载到容器的/app目录
- -w /app:设置工作目录为/app
- python:3.11:使用Python 3.11官方镜像
💡 小贴士:在Windows PowerShell中,$(pwd)应替换为${PWD}。
📝 本章练习
第四章:Dockerfile详解
4.1 什么是Dockerfile?
Dockerfile是一个文本文件,包含了一系列指令,告诉Docker如何构建一个镜像。
4.2 基本Dockerfile结构
让我们创建一个简单的Node.js应用Dockerfile:
# 1. 基础镜像
FROM node:18
# 2. 设置工作目录
WORKDIR /app
# 3. 复制package.json(先单独复制,利用Docker缓存)
COPY package.json .
# 4. 安装依赖
RUN npm install
# 5. 复制应用代码
COPY . .
# 6. 暴露端口
EXPOSE 3000
# 7. 定义启动命令
CMD ["npm", "start"]
4.3 关键指令详解
| FROM | 指定基础镜像 | FROM ubuntu:22.04 |
| ARG | 定义构建参数 | ARG NODE_VERSION=18FROM node:${NODE_VERSION} |
| RUN | 在镜像中执行命令 | RUN apt-get update && apt-get install -y python3 |
| COPY | 复制文件到镜像 | COPY app.py /app/ |
| ADD | 类似COPY,但支持URL和自动解压 | ADD https://example.com/file.tar.gz /app/ |
| WORKDIR | 设置工作目录 | WORKDIR /app |
| ENV | 设置环境变量 | ENV NODE_ENV=production |
| EXPOSE | 声明容器运行时监听的端口 | EXPOSE 80 |
| CMD | 容器启动时执行的命令 | CMD ["python", "app.py"] |
| ENTRYPOINT | 容器启动时执行的命令(不可覆盖) | ENTRYPOINT ["java", "-jar", "/app.jar"] |
4.4 构建和运行自定义镜像
创建Node.js应用:
> mkdir node-app
> cd node-app
> npm init -y
> echo 'const express = require("express");
const app = express();
app.get("/", (req, res) => res.send("Hello from Docker!"));
app.listen(3000, () => console.log("Server running on port 3000"));' > index.js
创建Dockerfile(内容如上所述)
构建镜像:
> docker build -t my-node-app:1.0 .
运行容器:
> docker run -d -p 3000:3000 –name node-app my-node-app:1.0
访问 http://localhost:3000
💡 避坑指南:Docker构建时,默认使用当前目录作为上下文。确保Dockerfile在项目根目录,且不包含不必要的大文件(使用.dockerignore)。
4.5 Docker BuildKit详解
Docker BuildKit是Docker 18.09+引入的下一代构建系统,提供了显著的性能改进和新功能:
启用BuildKit:
# 临时启用
> DOCKER_BUILDKIT=1 docker build .
# 永久启用(修改daemon.json)
{
"features": {
"buildkit": true
}
}
BuildKit优势:
- 更快的构建速度:并行构建和缓存优化
- 更好的安全性:隔离的构建环境
- 高级功能:# 语法声明(使用BuildKit特有功能)
# syntax=docker/dockerfile:1.3# SSH转发
FROM alpine
RUN –mount=type=ssh ssh example.com ls# 构建时缓存
RUN –mount=type=cache,target=/root/.cache/go-build go build .# 秘密管理
RUN –mount=type=secret,id=mysecret cat /run/secrets/mysecret
💡 小贴士:Docker 23.0+默认启用BuildKit,可以自动清理中间层,进一步减小镜像大小。
4.6 优化Docker镜像大小
1. 使用合适的基镜像
- 优先使用alpine版本(更小)
- 例如:node:18-alpine 比 node:18 小约200MB
2. 多阶段构建
# 构建阶段
FROM node:18 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci –only=production # 使用ci确保依赖版本确定性
COPY . .
RUN npm run build
# 运行阶段
FROM node:18-alpine
WORKDIR /app
COPY –from=builder /app/dist ./dist
COPY package.json .
RUN npm ci –only=production
EXPOSE 3000
CMD ["node", "dist/index.js"]
3. 减少镜像层数
# 不推荐
RUN apt-get update
RUN apt-get install -y package1 package2
# 推荐(合并为一条命令)
RUN apt-get update && apt-get install -y \\
package1 \\
package2 \\
&& rm -rf /var/lib/apt/lists/*
4. 清理不必要的文件
RUN npm install && npm cache clean –force
5. 使用.dockerignore文件
创建.dockerignore文件,排除不需要的文件:
node_modules
.git
*.log
.env
Dockerfile
.dockerignore
📝 本章练习
第五章:Docker Compose
5.1 什么是Docker Compose?
Docker Compose是用于定义和运行多容器Docker应用程序的工具。通过一个YAML文件配置应用程序服务,然后使用一个命令创建并启动所有服务。
5.2 安装Docker Compose
- Windows/macOS:Docker Desktop已包含Compose
- Linux:Docker 20.10+已内置Compose插件,无需单独安装
💡 小贴士:在Linux上,旧版Docker需要单独安装Compose:
> sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)–$(uname -m)" -o /usr/local/bin/docker-compose
> sudo chmod +x /usr/local/bin/docker-compose
5.3 Docker Compose Specification
Docker Compose已发展为Compose Specification,这是云原生计算基金会(CNCF)的项目,旨在标准化多容器应用的定义。最新版本已移除version字段要求:
services:
web:
image: nginx
ports:
– "8080:80"
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
这种格式与Docker Compose、Podman Compose和Kubernetes的Kompose兼容,提供更广泛的互操作性。
5.4 docker-compose.yml结构
version: '3.8' # 指定Compose文件格式版本
services: # 定义所有服务
web: # 服务名称
image: nginx:latest # 使用的镜像
ports:
– "8080:80" # 端口映射
volumes:
– ./html:/usr/share/nginx/html # 卷挂载
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example # 设置环境变量
MYSQL_DATABASE: mydb
volumes:
– db_data:/var/lib/mysql # 命名卷
volumes: # 定义卷
db_data:
💡 小贴士:对于新项目,可以直接使用Compose Specification(即直接写 services:),这代表最新标准。工具会自动兼容。
5.5 实战:部署WordPress应用
创建项目目录:
> mkdir wordpress-app
> cd wordpress-app
创建docker-compose.yml文件:
version: '3.8'
services:
db:
image: mysql:8.0
volumes:
– db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
healthcheck: # 添加健康检查
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u$$MYSQL_USER", "-p$$MYSQL_PASSWORD"]
interval: 10s
timeout: 5s
retries: 5
wordpress:
depends_on:
db:
condition: service_healthy # 确保数据库真正就绪
image: wordpress:latest
ports:
– "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data:
启动应用:
> docker-compose up -d
访问 http://localhost:8000 开始WordPress安装
常用Compose命令:
# 启动所有服务
> docker-compose up -d
# 停止所有服务
> docker-compose down
# 查看服务日志
> docker-compose logs -f
# 重启服务
> docker-compose restart wordpress
# 构建/重新构建服务
> docker-compose build
⚠️ 重要提示:depends_on只控制启动顺序,不等待服务真正就绪。对于需要等待数据库初始化的应用,必须实现健康检查并使用condition: service_healthy,这是生产环境的最佳实践。
📝 本章练习
第六章:Docker网络
6.1 Docker网络模式
| bridge | 默认模式,容器通过虚拟网桥连接 | 单机上多个容器通信 |
| host | 容器直接使用宿主机网络 | 需要高性能网络的应用 |
| none | 容器没有网络 | 完全隔离的容器 |
| overlay | 跨多个Docker守护进程的网络 | Docker Swarm集群 |
6.2 创建自定义网络
# 创建自定义桥接网络
> docker network create my-network
# 在自定义网络中运行容器
> docker run -d –name web –network my-network nginx
> docker run -it –name alpine –network my-network alpine sh
# 在alpine容器中测试与web容器的连接
/ # ping web
6.3 容器间通信
场景:前端应用需要连接后端API
创建自定义网络:
> docker network create app-network
启动后端服务:
> docker run -d –name backend –network app-network -p 5000:5000 my-backend-image
启动前端服务:
> docker run -d –name frontend –network app-network -p 3000:3000 \\
-e API_URL=http://backend:5000 my-frontend-image
前端容器可以通过http://backend:5000访问后端服务
6.4 网络排查
# 查看所有网络
> docker network ls
# 查看特定网络的详细信息
> docker network inspect app-network
# 查看容器的网络配置
> docker inspect frontend | grep IPAddress
💡 避坑指南:Docker容器使用服务名称作为主机名进行通信。确保在代码中使用服务名称(如http://backend:5000)而不是IP地址。
📝 本章练习
第七章:数据持久化
7.1 为什么需要数据持久化?
默认情况下,容器停止后,容器内的所有数据都会丢失。对于数据库等需要持久存储的应用,我们需要将数据存储在容器外部。
7.2 三种数据管理方式
| 数据卷(Volumes) | 由Docker管理的存储区域 | 生产环境,最佳实践 |
| 绑定挂载(Bind Mounts) | 将宿主机目录直接挂载到容器 | 开发环境,需要实时编辑文件 |
| tmpfs挂载 | 仅存储在内存中 | 临时数据,敏感数据 |
7.3 使用数据卷
# 创建命名卷
> docker volume create my-volume
# 查看所有卷
> docker volume ls
# 使用卷运行容器
> docker run -d -v my-volume:/app/data –name my-container nginx
# 查看卷详情
> docker volume inspect my-volume
# 清理未使用的卷
> docker volume prune
7.4 数据卷备份与恢复
数据卷备份:
# 创建备份容器
> docker run –rm -v my-volume:/volume -v $(pwd):/backup alpine \\
tar cvf /backup/backup.tar -C /volume .
数据卷恢复:
# 创建新卷
> docker volume create restore-volume
# 恢复数据
> docker run –rm -v restore-volume:/volume -v $(pwd):/backup alpine \\
tar xvf /backup/backup.tar -C /volume
生产环境建议:
- 使用定时任务定期备份关键数据卷
- 将备份存储到安全位置(如云存储)
- 测试恢复流程,确保备份有效
- 考虑使用专业备份工具如Velero(Kubernetes环境)
7.5 实战:MySQL数据持久化
# 创建数据卷
> docker volume create mysql-data
# 运行MySQL容器
> docker run -d \\
-v mysql-data:/var/lib/mysql \\
-e MYSQL_ROOT_PASSWORD=my-secret-pw \\
–name mysql \\
mysql:8.0
即使容器被删除,数据仍然保留在mysql-data卷中。
💡 避坑指南:数据卷的路径在宿主机上通常是/var/lib/docker/volumes/,但不应直接操作这些文件,应通过Docker命令管理。
7.6 使用绑定挂载进行开发
# 将当前目录挂载到容器的/app目录
> docker run -d \\
-v $(pwd):/app \\
-w /app \\
node:18 \\
npm start
开发优势:
- 代码修改后无需重新构建镜像
- 实时看到更改效果
- 适合前端开发和热重载
📝 本章练习
第八章:实战项目 – 部署一个完整的Web应用
8.1 项目结构
my-app/
├── frontend/ # 前端代码(React)
├── backend/ # 吘端代码(Node.js)
├── docker-compose.yml
└── README.md
8.2 前端Dockerfile
# frontend/Dockerfile
# 构建阶段
FROM node:18 as build
WORKDIR /app
COPY package*.json ./
RUN npm ci # 使用ci确保依赖版本确定性
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY –from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
8.3 后端Dockerfile
# backend/Dockerfile
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci –only=production # 生产环境只安装生产依赖
COPY . .
EXPOSE 5000
CMD ["node", "server.js"]
8.4 docker-compose.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend
labels:
– "org.opencontainers.image.revision=${GIT_COMMIT:-latest}" # 注入git commit信息
ports:
– "3000:80"
depends_on:
backend:
condition: service_healthy
networks:
– app–network
backend:
build:
context: ./backend
labels:
– "org.opencontainers.image.revision=${GIT_COMMIT:-latest}"
ports:
– "5000:5000"
environment:
DB_HOST: db
DB_USER: user
DB_PASS: password
depends_on:
db:
condition: service_healthy
networks:
– app–network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
– pgdata:/var/lib/postgresql/data
networks:
– app–network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
networks:
app-network:
driver: bridge
volumes:
pgdata:
💡 小贴士:condition: service_healthy确保服务真正就绪后再启动依赖服务,避免启动顺序问题。通过labels注入git commit信息便于镜像追踪。
8.5 部署步骤
克隆项目:
> git clone https://github.com/yourusername/my-app.git
> cd my-app
启动应用:
> docker-compose up -d –build
访问应用:
- 前端:http://localhost:3000
- 后端API:http://localhost:5000/api
查看日志:
> docker-compose logs -f
停止应用:
> docker-compose down
📝 本章练习
第九章:常见问题与解决方案
9.1 容器无法启动
问题:容器启动后立即退出 原因:主进程执行完毕退出 解决方案:
- 确保CMD或ENTRYPOINT指定的是长期运行的进程
- 使用-it参数运行容器进行调试:> docker run -it –rm my-image sh
💡 避坑指南:容器必须有一个前台进程才能保持运行。如果运行的是后台服务,需要使用-d参数或确保命令保持前台运行。
9.2 端口冲突
问题:
Error response from daemon: driver failed programming external connectivity on endpoint…:
bind: address already in use.
解决方案:
- 更换宿主机端口:> docker run -p 8081:80 nginx
- 停止占用端口的进程:# Linux/Mac
> lsof -i :8080# Windows
> netstat -ano | findstr :8080
9.3 镜像拉取失败
问题:
Error response from daemon: Get https://registry-1.docker.io/v2/:
net/http: request canceled while waiting for connection
解决方案:
- 检查网络连接
- 配置Docker镜像加速器(针对中国用户):
- 创建或修改 /etc/docker/daemon.json
- 添加:{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
} - 重启Docker:sudo systemctl restart docker
💡 小贴士:Docker Desktop用户可以在设置中直接配置镜像加速器。常用的镜像加速器包括:
- 阿里云容器镜像服务(需登录获取个人加速地址)
- 网易云:https://hub-mirror.c.163.com
- 中国科学技术大学:https://docker.mirrors.ustc.edu.cn
9.4 容器内无法访问网络
问题:容器内无法ping通外部网络 解决方案:
- 检查DNS配置:> docker run –dns=8.8.8.8 -it ubuntu ping google.com
- 检查防火墙设置
- 重置Docker网络:> docker network prune
9.5 清理磁盘空间
问题:Docker占用大量磁盘空间 解决方案:
# 清理停止的容器
> docker container prune
# 清理未使用的镜像
> docker image prune
# 清理未使用的网络
> docker network prune
# 清理所有未使用的资源(包括构建缓存)
> docker system prune -a
# 查看磁盘使用情况
> docker system df
💡 避坑指南:定期清理可以避免磁盘空间不足问题。建议在CI/CD管道中添加清理步骤。
📝 本章练习
第十章:最佳实践与安全建议
10.1 镜像构建最佳实践
使用.dockerignore文件:
node_modules
.git
*.log
.env
Dockerfile
.dockerignore
合理排序Dockerfile指令:
- 将变化较少的指令放在前面
- 例如:先COPY package.json,再RUN npm install,最后COPY其他文件
使用多阶段构建:
- 减小最终镜像大小
- 避免将构建工具包含在生产镜像中
指定软件包版本:
RUN apt-get install -y python3=3.10.6-1ubuntu0.1
镜像分层原理:
- Docker镜像由多层只读层组成
- 每条Dockerfile指令创建一个新层
- 利用缓存机制:当某一层发生变化时,其后的所有层都需要重新构建
- 合并相关操作到同一层可减少镜像层数
10.2 安全最佳实践
不要以root用户运行容器:
FROM node:18
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
定期更新基础镜像:
> docker pull node:18
> docker build -t my-app:latest .
扫描镜像漏洞:
# 需要先登录Docker Hub
> docker login
> docker scan my-app:latest
# 或者使用开源工具如Trivy
> trivy image –severity CRITICAL,HIGH my-app:latest
限制容器资源:
> docker run -d \\
–memory=512m \\
–cpus=1.5 \\
my-app
不要在镜像中存储敏感信息:
- 使用环境变量或Docker secrets
- 通过docker run -e或docker-compose的environment设置
使用非最新版本的具体标签:
- 使用node:18.18.0-alpine 而不是 node:18-alpine 或 node:latest
- 确保部署的确定性和安全性
最小权限原则:
> docker run –cap-drop ALL –cap-add NET_BIND_SERVICE my-app
Docker内容信任(Docker Content Trust):
# 启用内容信任
> export DOCKER_CONTENT_TRUST=1
# 签名并推送镜像
> docker trust sign myimage:tag
# 验证签名
> docker trust inspect myimage:tag
安全上下文配置:
services:
app:
# …
security_opt:
– no–new–privileges:true
read_only: true
cap_drop:
– ALL
cap_add:
– NET_BIND_SERVICE
10.3 生产环境部署建议
使用编排工具:
- Docker Swarm(内置)
- Kubernetes(更强大,适合大型部署)
实现健康检查:
HEALTHCHECK –interval=30s –timeout=3s \\
CMD curl -f http://localhost/ || exit 1
集中式日志管理:
- 使用ELK栈(Elasticsearch, Logstash, Kibana)
- 或Docker日志驱动:docker run –log-driver=json-file …
监控与告警:
- Prometheus + Grafana
- cAdvisor(容器资源监控)
Docker Desktop的Kubernetes集成: Docker Desktop内置了Kubernetes支持,无需额外安装即可在本地开发环境中使用Kubernetes:
启用Kubernetes:
- Windows/macOS:Docker Desktop设置 → Kubernetes → 勾选"Enable Kubernetes"
- Linux:需单独安装
验证安装:
> kubectl cluster-info
Kubernetes control plane is running at https://kubernetes.docker.internal:6443
使用Kubernetes:
> kubectl create deployment nginx –image=nginx
> kubectl expose deployment nginx –port=80
> kubectl get pods
Docker Desktop的Kubernetes支持包括:
- 单节点集群(开发使用)
- 与Docker Compose的集成
- 简单的UI管理
- 本地开发的理想环境
💡 避坑指南:生产环境应避免使用latest标签,而应使用具体的版本号,确保可重复部署。
📝 本章练习
第十一章:进阶主题
11.1 Docker Swarm简介
Docker Swarm是Docker原生的集群管理和编排工具。
基本概念:
- Node:集群中的Docker主机
- Manager:管理集群的节点
- Worker:执行任务的节点
- Service:在集群中运行的应用
创建Swarm集群:
# 初始化Swarm(作为Manager)
> docker swarm init
# 获取加入令牌
> docker swarm join-token worker
# 在其他节点上加入Swarm
> docker swarm join –token <token> <manager-ip>:2377
部署服务:
> docker service create –replicas 3 -p 80:80 –name my-web nginx
11.2 Kubernetes简介
Kubernetes(简称K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。
核心概念:
- Pod:Kubernetes中最小的部署单元,可包含一个或多个容器
- Deployment:管理Pod的声明式更新
- Service:定义Pod的访问策略
- Namespace:资源的虚拟集群
简单示例:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx–deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx:1.14.2
ports:
– containerPort: 80
应用配置:
> kubectl apply -f deployment.yaml
11.3 CI/CD集成
GitHub Actions示例:
name: Docker Image CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu–latest
steps:
– uses: actions/checkout@v4
with:
fetch-depth: 0 # 获取所有历史记录,便于生成标签
– name: Set up Docker Buildx
uses: docker/setup–buildx–action@v3
– name: Login to DockerHub
uses: docker/login–action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
– name: Extract metadata for Docker
id: meta
uses: docker/metadata–action@v5
with:
images: user/app
tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
– name: Build and push
uses: docker/build–push–action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
💡 小贴士:Docker 23.0+引入了Buildx Build Cache,可以显著加速CI/CD中的镜像构建过程。使用GitHub Actions的缓存功能可以进一步提升构建效率。
11.4 Docker Swarm和Kubernetes对比
| 学习曲线 | 简单,易于上手 | 陡峭,需要更多学习 |
| 安装配置 | 简单,Docker内置 | 复杂,需要单独安装 |
| 功能丰富度 | 基础功能 | 非常丰富,功能全面 |
| 社区支持 | 中等 | 非常活跃 |
| 适用场景 | 中小型应用,简单部署 | 大型应用,复杂部署 |
| 扩展性 | 有限 | 非常强大 |
| 自动伸缩 | 基础支持 | 高级支持 |
| 滚动更新 | 支持 | 高级支持 |
| 健康检查 | 基础支持 | 高级支持 |
| 网络策略 | 基础支持 | 高级支持 |
选择建议:
- 如果是小型团队或简单应用,Docker Swarm足够使用
- 如果需要高级功能或大规模部署,Kubernetes是更好的选择
- 对于本地开发,Docker Desktop内置的Kubernetes支持是理想选择
📝 本章练习
附录A:Docker命令速查表
基础命令
| docker ps | 列出正在运行的容器 |
| docker ps -a | 列出所有容器 |
| docker images | 列出本地镜像 |
| docker run [OPTIONS] IMAGE [COMMAND] | 运行容器 |
| docker stop CONTAINER | 停止容器 |
| docker start CONTAINER | 启动容器 |
| docker rm CONTAINER | 删除容器 |
| docker rmi IMAGE | 删除镜像 |
| docker logs CONTAINER | 查看容器日志 |
| docker exec -it CONTAINER COMMAND | 在运行的容器中执行命令 |
高级命令
| docker build -t TAG . | 构建镜像 |
| docker-compose up | 启动Compose服务 |
| docker network ls | 列出网络 |
| docker volume ls | 列出数据卷 |
| docker system df | 查看Docker磁盘使用 |
| docker system prune | 清理未使用的资源 |
| docker inspect CONTAINER | 查看容器详细信息 |
| docker stats | 实时资源使用情况 |
| docker events | 监听Docker事件 |
| docker diff CONTAINER | 查看容器文件系统变化 |
附录B:推荐学习资源
📚 官方文档:
- Docker官方文档
- Docker Hub
- Compose Specification
📺 视频教程:
- Docker入门教程(B站)
- Docker & Kubernetes: The Practical Guide (Udemy)
💻 实践平台:
- Play with Docker
- Katacoda Docker场景
📖 书籍推荐:
- 《Docker技术入门与实战》
- 《Kubernetes权威指南》
🔧 实用工具:
- Trivy – 容器漏洞扫描工具
- Dive – 镜像层分析工具
- Lens – Kubernetes IDE
- Portainer – Docker管理UI
结语:继续你的Docker之旅
恭喜你完成了Docker入门学习!现在你已经掌握了Docker的核心概念和实用技能,可以开始在自己的项目中应用Docker了。
下一步建议:
- 阅读Docker官方文档
- 学习Kubernetes基础知识
- Docker官方论坛
- Stack Overflow的docker标签
- 本地Docker/Kubernetes用户组
记住,最好的学习方式是动手实践!从简单开始,逐步增加复杂度,很快你就会成为Docker高手。
祝你在容器化旅程中一切顺利! 🐳
📝 附:学习进度检查表
| 安装Docker | ||
| 运行第一个容器 | ||
| 理解Dockerfile | ||
| 使用Docker Compose | ||
| 配置Docker网络 | ||
| 实现数据持久化 | ||
| 部署完整Web应用 | ||
| 解决常见问题 | ||
| 应用最佳实践 | ||
| 探索进阶主题 |
填写你的学习计划,跟踪进度!


