docker 作者: typecho 时间: 2026-05-22 分类: 默认分类 # Docker 视频教程学习讲义 本讲义根据项目文件夹 `ed_videos/` 下的 Docker 视频教程整理,顺序对应本地视频文件: ```text 01 课程简介 Docker 02 基础 Docker 架构与容器化 05 基础 安装 Docker 06 命令 镜像操作 07 命令 容器操作 08 命令 run 细节 09 命令 保存镜像 10 命令 分享镜像 11 命令 实验小结 12 存储 目录挂载 13 存储 卷映射 14 网络 自定义网络 15 网络 Redis 主从集群 16 最佳实践 17 Docker Compose 安装 WordPress 18 Docker Compose 语法 19 Docker Compose 其他 20 Dockerfile 制作镜像 21 Dockerfile 镜像分层机制 22 一键启动所有中间件 23 访问测试全部通过 24 销毁实例 25 结束语 ``` 这套视频不是在讲“云原生全家桶”,而是在讲你当前路线最需要的能力: > 能用 Docker 把服务快速部署起来,能管理镜像、容器、端口、数据和网络。 > 能用 Docker Compose 一键启动多个中间件,也能写 Dockerfile 制作自己的应用镜像。 --- ## 0. 学 Docker 前先明确目标 你现在学 Docker,不是为了背命令,也不是为了马上搞 Kubernetes。你的目标应该是: - 会安装 Docker。 - 会拉取镜像。 - 会启动、停止、删除容器。 - 会把容器端口映射到宿主机。 - 会把宿主机目录挂载到容器。 - 会创建自定义网络,让容器之间用名字互相访问。 - 会用 Docker Compose 管理多个服务。 - 会写 Dockerfile,把自己的项目打成镜像。 - 会用日志和端口命令排查容器服务为什么访问不了。 结合你的学习路线,Docker 最终要服务于这些项目: - 个人 Web 服务部署。 - Nginx 反向代理。 - FastAPI 数据分析平台。 - WordPress 或博客系统部署。 - Redis/MySQL/MinIO 等中间件部署。 - Ollama + OpenWebUI 私有化部署。 - 射频测试数据自动化分析平台部署。 --- ## 1. 课程简介:Docker 到底解决什么问题 对应视频:`01.课程简介_Docker` Docker 解决的核心问题是: > 让应用和它的运行环境一起打包、一起交付、一起启动。 以前部署一个项目,经常会遇到这些问题: - 开发电脑能跑,服务器跑不起来。 - Python、Java、Node 版本不一致。 - 依赖库版本冲突。 - 安装 MySQL、Redis、Nginx 很麻烦。 - 换一台服务器要重新搭环境。 - 多个服务部署步骤难以复现。 Docker 的思路是: - 把应用运行所需环境做成镜像。 - 用镜像启动容器。 - 容器之间相互隔离。 - 容器可以快速创建、删除、迁移和重启。 - 配合 Compose 可以一键启动一组服务。 你可以这样理解: ```text 镜像 image = 软件安装包 + 运行环境模板 容器 container = 镜像运行起来后的实例 仓库 registry = 存放镜像的地方 Dockerfile = 制作镜像的说明书 Compose = 一键启动多容器项目的配置文件 ``` 工程上你最常说的一句话是: > 我用 Docker Compose 把 Nginx、后端服务、数据库和 Redis 统一编排起来,部署时只需要执行 `docker compose up -d`。 --- ## 2. Docker 架构与容器化 对应视频:`02.基础_Docker架构与容器化` ### 2.1 Docker 的基本架构 Docker 主要由几部分组成: ```text Docker Client -> Docker Daemon -> Images / Containers / Networks / Volumes | v Docker Registry ``` 常见组件: - Docker Client:你在命令行输入的 `docker` 命令。 - Docker Daemon:后台服务,真正负责创建容器、拉镜像、管理网络和存储。 - Image:镜像,是只读模板。 - Container:容器,是镜像运行后的实例。 - Registry:镜像仓库,如 Docker Hub、阿里云镜像仓库、私有仓库。 - Volume:Docker 管理的数据卷。 - Network:Docker 管理的容器网络。 当你执行: ```bash docker run nginx ``` 背后发生的事情大致是: 1. Docker Client 把命令发给 Docker Daemon。 2. Daemon 检查本地有没有 `nginx` 镜像。 3. 如果没有,就从镜像仓库拉取。 4. 用镜像创建容器。 5. 给容器分配文件系统、网络、进程空间。 6. 启动容器里的 Nginx 主进程。 ### 2.2 容器不是虚拟机 虚拟机通常包含完整操作系统: ```text 物理机 -> 宿主机操作系统 -> 虚拟化软件 -> 虚拟机操作系统 -> 应用 ``` 容器共享宿主机内核: ```text 物理机 -> 宿主机操作系统 -> Docker -> 容器 -> 应用 ``` 所以容器通常更轻: - 启动快。 - 占用资源少。 - 适合快速部署服务。 - 适合统一环境。 但容器也不是万能的: - 它不是完整虚拟机。 - 它依赖宿主机内核。 - 数据默认不应该只放在容器内部。 - 安全隔离不等于绝对隔离。 ### 2.3 镜像和容器的关系 镜像像“类”,容器像“对象”。 ```text nginx 镜像 -> nginx 容器 A -> nginx 容器 B -> nginx 容器 C ``` 同一个镜像可以启动多个容器。每个容器有自己的进程、网络、文件系统变化层。 --- ## 3. 安装 Docker 对应视频:`05.基础_安装Docker` ### 3.1 Linux 上安装 Docker Ubuntu 常见安装方式: ```bash sudo apt update sudo apt install -y ca-certificates curl gnupg ``` 如果使用官方仓库,通常还会添加 GPG key 和 Docker 软件源。学习阶段也可以直接使用发行版仓库: ```bash sudo apt install -y docker.io docker-compose-plugin ``` 启动 Docker: ```bash sudo systemctl start docker sudo systemctl enable docker ``` 查看状态: ```bash systemctl status docker ``` 检查版本: ```bash docker version docker compose version ``` 运行测试容器: ```bash sudo docker run hello-world ``` ### 3.2 让普通用户执行 docker 如果每次都要 `sudo docker`,可以把当前用户加入 docker 组: ```bash sudo usermod -aG docker $USER ``` 然后退出 SSH,重新登录。 验证: ```bash docker ps ``` 注意: > 加入 docker 组后,这个用户基本拥有接近 root 的能力。自己的学习服务器可以这样做,生产环境要按公司规范来。 ### 3.3 常见安装问题 #### Docker 服务没启动 现象: ```text Cannot connect to the Docker daemon ``` 排查: ```bash systemctl status docker sudo systemctl start docker ``` #### 权限不足 现象: ```text permission denied while trying to connect to the Docker daemon socket ``` 处理: ```bash sudo usermod -aG docker $USER ``` 重新登录后再试。 #### 拉镜像很慢 可能是网络或镜像源问题。可以配置国内镜像加速器,或者使用云服务器所在厂商提供的加速地址。 --- ## 4. 镜像操作 对应视频:`06.命令_镜像操作` 镜像是启动容器的模板。你要先会找镜像、拉镜像、看镜像、删镜像。 ### 4.1 搜索镜像 ```bash docker search nginx docker search redis docker search mysql ``` 学习时可以搜索,实际部署更建议去 Docker Hub 或官方文档确认镜像名和版本。 ### 4.2 拉取镜像 ```bash docker pull nginx docker pull redis docker pull mysql:8.0 docker pull python:3.11-slim ``` 镜像名后面的 `:8.0`、`:3.11-slim` 是 tag。 如果不写 tag,默认是: ```text latest ``` 不建议正式项目长期使用 `latest`,因为它会变化。更推荐固定版本: ```bash docker pull redis:7.2 docker pull nginx:1.25 ``` ### 4.3 查看本地镜像 ```bash docker images ``` 或: ```bash docker image ls ``` 你会看到: ```text REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest xxxxxxxx ... ... ``` 字段含义: - REPOSITORY:镜像仓库名。 - TAG:版本标签。 - IMAGE ID:镜像 ID。 - SIZE:镜像大小。 ### 4.4 删除镜像 ```bash docker rmi nginx docker rmi nginx:latest docker rmi 镜像ID ``` 如果镜像正在被容器使用,删除会失败。要先删除相关容器。 查看所有容器: ```bash docker ps -a ``` 删除容器: ```bash docker rm 容器名或容器ID ``` 再删镜像。 ### 4.5 查看镜像详情 ```bash docker inspect nginx docker history nginx ``` `docker inspect` 看完整元数据。 `docker history` 看镜像分层历史,这在 Dockerfile 和镜像分层机制里会用到。 --- ## 5. 容器操作 对应视频:`07.命令_容器操作` 容器是镜像运行起来后的实例。 ### 5.1 启动一个容器 最简单: ```bash docker run nginx ``` 这会占住当前终端。更常用后台启动: ```bash docker run -d nginx ``` `-d` 表示 detached,后台运行。 ### 5.2 查看运行中的容器 ```bash docker ps ``` 查看所有容器,包括已经停止的: ```bash docker ps -a ``` 常见字段: - CONTAINER ID:容器 ID。 - IMAGE:使用的镜像。 - COMMAND:容器启动命令。 - STATUS:运行状态。 - PORTS:端口映射。 - NAMES:容器名称。 ### 5.3 停止、启动、重启容器 ```bash docker stop 容器名 docker start 容器名 docker restart 容器名 ``` 例如: ```bash docker stop my-nginx docker start my-nginx docker restart my-nginx ``` ### 5.4 删除容器 删除已经停止的容器: ```bash docker rm 容器名 ``` 强制删除运行中的容器: ```bash docker rm -f 容器名 ``` 学习环境可以用 `-f`,正式环境先确认容器是否承载重要服务。 ### 5.5 查看日志 ```bash docker logs 容器名 docker logs -f 容器名 docker logs --tail 100 容器名 ``` 常用组合: ```bash docker logs -f --tail 100 my-nginx ``` ### 5.6 进入容器 ```bash docker exec -it 容器名 bash ``` 如果容器里没有 bash: ```bash docker exec -it 容器名 sh ``` 参数含义: - `exec`:在运行中的容器里执行命令。 - `-i`:保持输入。 - `-t`:分配终端。 ### 5.7 查看容器资源 ```bash docker stats ``` 可以看到 CPU、内存、网络、磁盘 IO 等。 --- ## 6. docker run 细节 对应视频:`08.命令_run细节` `docker run` 是最核心的命令之一。它不是单纯“启动”,而是: ```text 拉镜像,如果本地没有 -> 创建容器 -> 设置名称、端口、环境变量、挂载、网络等参数 -> 启动容器 ``` ### 6.1 给容器命名 ```bash docker run -d --name my-nginx nginx ``` 好处: - 后续不用记容器 ID。 - 日志、停止、删除更方便。 ```bash docker logs my-nginx docker stop my-nginx docker rm my-nginx ``` ### 6.2 端口映射 容器里的 Nginx 默认监听 80,但外部不能直接访问容器内部端口。需要映射到宿主机。 ```bash docker run -d --name my-nginx -p 8080:80 nginx ``` 含义: ```text 宿主机 8080 -> 容器 80 ``` 访问: ```bash curl http://127.0.0.1:8080 ``` 如果云服务器要让外网访问,还要放行安全组端口。 ### 6.3 后台运行 ```bash docker run -d nginx ``` 如果不加 `-d`,容器前台输出会占住终端。 ### 6.4 容器自动删除 ```bash docker run --rm hello-world ``` 容器退出后自动删除。适合临时测试,不适合有状态服务。 ### 6.5 环境变量 ```bash docker run -d --name mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0 ``` 很多官方镜像都用环境变量做初始化配置,比如 MySQL 密码、Redis 配置、应用运行模式。 ### 6.6 重启策略 ```bash docker run -d --restart always --name my-nginx nginx ``` 常见策略: - `no`:默认,不自动重启。 - `always`:总是自动重启。 - `unless-stopped`:除非手动停止,否则自动重启。 - `on-failure`:异常退出时重启。 服务器部署常用: ```bash --restart unless-stopped ``` ### 6.7 一个完整 run 示例 ```bash docker run -d \ --name my-nginx \ --restart unless-stopped \ -p 8080:80 \ nginx:1.25 ``` 检查: ```bash docker ps docker logs --tail 50 my-nginx curl -I http://127.0.0.1:8080 ``` --- ## 7. 保存镜像 对应视频:`09.命令_保存镜像` 保存镜像常见有两类含义: - 把本地镜像导出成文件,方便离线传输。 - 基于容器当前状态提交成新镜像。 ### 7.1 docker save:导出镜像 导出镜像: ```bash docker save nginx:1.25 -o nginx-1.25.tar ``` 导入镜像: ```bash docker load -i nginx-1.25.tar ``` 适用场景: - 服务器不能访问外网。 - 需要把镜像拷贝到另一台机器。 - 内网部署交付。 ### 7.2 docker commit:从容器提交镜像 假设你进入容器改了一些内容: ```bash docker exec -it my-nginx bash ``` 然后可以提交成镜像: ```bash docker commit my-nginx my-nginx-custom:1.0 ``` 查看: ```bash docker images ``` 但是注意: > 正式项目不推荐依赖 `docker commit` 制作镜像。更推荐写 Dockerfile,因为 Dockerfile 可复现、可维护、可交给别人重新构建。 `docker commit` 适合学习、临时保存实验结果。 --- ## 8. 分享镜像 对应视频:`10.命令_分享镜像` 分享镜像主要有两种方式: - 文件方式:`docker save` + `docker load`。 - 仓库方式:`docker tag` + `docker push`。 ### 8.1 文件分享 导出: ```bash docker save my-app:1.0 -o my-app-1.0.tar ``` 传到服务器: ```bash scp my-app-1.0.tar 用户名@服务器IP:/opt/ ``` 服务器导入: ```bash docker load -i /opt/my-app-1.0.tar ``` 启动: ```bash docker run -d --name my-app -p 8000:8000 my-app:1.0 ``` ### 8.2 推送到镜像仓库 登录: ```bash docker login ``` 给镜像打标签: ```bash docker tag my-app:1.0 用户名/my-app:1.0 ``` 推送: ```bash docker push 用户名/my-app:1.0 ``` 别人拉取: ```bash docker pull 用户名/my-app:1.0 ``` ### 8.3 版本命名建议 不要只用: ```text latest ``` 建议: ```text my-app:1.0.0 my-app:2026-05-19 my-app:dev my-app:prod ``` 项目交付时写清楚镜像版本,避免“昨天能跑,今天拉了 latest 跑不起来”。 --- ## 9. 命令实验小结 对应视频:`11.命令_实验小结` 这一阶段你要把 Docker 的基础命令串起来。 ### 9.1 镜像命令 ```bash docker search nginx docker pull nginx:1.25 docker images docker inspect nginx:1.25 docker history nginx:1.25 docker rmi nginx:1.25 ``` ### 9.2 容器命令 ```bash docker run -d --name my-nginx -p 8080:80 nginx:1.25 docker ps docker ps -a docker logs my-nginx docker exec -it my-nginx sh docker stop my-nginx docker start my-nginx docker restart my-nginx docker rm -f my-nginx ``` ### 9.3 排障命令 ```bash docker logs --tail 100 容器名 docker inspect 容器名 docker stats ss -tunlp | grep 端口 curl -v http://127.0.0.1:端口 ``` 如果一个容器服务访问不了,先问四个问题: 1. 容器是否正在运行? 2. 容器内部服务是否启动成功? 3. 端口是否映射正确? 4. 宿主机防火墙或云安全组是否放行? --- ## 10. 存储:目录挂载 对应视频:`12.存储_目录挂载` 容器默认是临时的。容器删除后,容器内部新增的数据也可能随之消失。 所以正式部署必须考虑数据持久化。 目录挂载的意思是: ```text 宿主机目录 <-> 容器内部目录 ``` ### 10.1 Nginx 静态目录挂载 创建宿主机目录: ```bash mkdir -p /opt/nginx-demo/html ``` 写一个页面: ```bash echo "hello docker nginx" > /opt/nginx-demo/html/index.html ``` 启动容器: ```bash docker run -d \ --name nginx-demo \ -p 8080:80 \ -v /opt/nginx-demo/html:/usr/share/nginx/html \ nginx:1.25 ``` 访问: ```bash curl http://127.0.0.1:8080 ``` 你改宿主机的 `/opt/nginx-demo/html/index.html`,容器里看到的内容也会变化。 ### 10.2 挂载配置文件 例如挂载 Nginx 配置: ```bash docker run -d \ --name nginx-conf-demo \ -p 8080:80 \ -v /opt/nginx-demo/nginx.conf:/etc/nginx/nginx.conf:ro \ nginx:1.25 ``` 末尾 `:ro` 表示只读挂载。 ### 10.3 目录挂载常见问题 #### 宿主机目录不存在 Docker 可能会自动创建目录,但不一定符合你的预期。建议先手动创建。 ```bash mkdir -p /opt/project/data ``` #### 权限不足 容器内进程可能无法写宿主机目录。 排查: ```bash ls -ld /opt/project/data docker logs 容器名 ``` #### 路径写错 挂载路径写错会导致容器内看不到期望文件。 检查: ```bash docker inspect 容器名 docker exec -it 容器名 sh ``` --- ## 11. 存储:卷映射 对应视频:`13.存储_卷映射` Docker Volume 是 Docker 自己管理的数据卷。 目录挂载由你指定宿主机路径: ```bash -v /opt/mysql-data:/var/lib/mysql ``` Volume 由 Docker 管理: ```bash -v mysql-data:/var/lib/mysql ``` ### 11.1 创建卷 ```bash docker volume create mysql-data docker volume ls docker volume inspect mysql-data ``` ### 11.2 使用卷 ```bash docker run -d \ --name mysql-demo \ -e MYSQL_ROOT_PASSWORD=123456 \ -v mysql-data:/var/lib/mysql \ mysql:8.0 ``` 删除容器后,卷还在: ```bash docker rm -f mysql-demo docker volume ls ``` 重新启动一个 MySQL 容器,仍可复用这个数据卷。 ### 11.3 删除卷 ```bash docker volume rm mysql-data ``` 清理未使用卷: ```bash docker volume prune ``` 注意: > 删除卷可能意味着删除数据库数据。不要在不确认的情况下执行 `docker volume prune`。 ### 11.4 目录挂载和卷的选择 适合目录挂载: - 你需要直接编辑配置文件。 - 你需要清楚知道数据在宿主机哪个目录。 - 项目 README 要写明确路径。 适合 volume: - 数据由 Docker 管理即可。 - 不想关心宿主机具体路径。 - 数据库类服务。 学习和交付项目里,推荐你把重要数据目录写清楚,例如: ```text /opt/rf-platform/data /opt/rf-platform/uploads /opt/rf-platform/logs ``` 这样更容易排障和备份。 --- ## 12. 网络:自定义网络 对应视频:`14.网络_自定义网络` 容器之间通信,最推荐使用自定义网络。 ### 12.1 查看网络 ```bash docker network ls ``` 常见默认网络: - bridge - host - none 大多数普通容器默认使用 bridge。 ### 12.2 创建自定义网络 ```bash docker network create app-net ``` 查看: ```bash docker network ls docker network inspect app-net ``` ### 12.3 在同一网络启动两个容器 启动 Redis: ```bash docker run -d \ --name redis \ --network app-net \ redis:7.2 ``` 启动一个临时容器测试: ```bash docker run --rm -it \ --network app-net \ redis:7.2 \ redis-cli -h redis ping ``` 如果返回: ```text PONG ``` 说明容器可以通过名字 `redis` 访问 Redis 容器。 ### 12.4 为什么不要依赖容器 IP 容器 IP 可能变化。容器删除重建后,IP 不一定相同。 自定义网络里可以用容器名当域名: ```text redis mysql backend nginx ``` 这就是 Compose 里服务名互通的基础。 --- ## 13. 网络:Redis 主从集群 对应视频:`15.网络_Redis主从集群` 这一集的重点不是让你成为 Redis 专家,而是通过 Redis 主从理解: > 多个容器如何在同一个 Docker 网络里互相访问,并通过容器名组成一个小型服务集群。 ### 13.1 创建网络 ```bash docker network create redis-net ``` ### 13.2 启动 Redis 主节点 ```bash docker run -d \ --name redis-master \ --network redis-net \ redis:7.2 ``` ### 13.3 启动 Redis 从节点 ```bash docker run -d \ --name redis-slave-1 \ --network redis-net \ redis:7.2 \ redis-server --replicaof redis-master 6379 ``` 再启动一个: ```bash docker run -d \ --name redis-slave-2 \ --network redis-net \ redis:7.2 \ redis-server --replicaof redis-master 6379 ``` ### 13.4 验证主从 进入主节点: ```bash docker exec -it redis-master redis-cli ``` 写入: ```redis set name docker ``` 进入从节点: ```bash docker exec -it redis-slave-1 redis-cli ``` 读取: ```redis get name ``` 查看复制信息: ```redis info replication ``` ### 13.5 你真正要掌握的点 - 容器名可以作为网络地址。 - 多个容器要放到同一个自定义网络。 - 数据库、中间件、后端服务之间不一定要暴露到宿主机。 - 对外访问通常只暴露 Nginx 或网关。 --- ## 14. Docker 最佳实践 对应视频:`16.最佳实践` ### 14.1 不要把重要数据只放容器里 错误做法: ```bash docker run -d --name mysql mysql:8.0 ``` 容器删了,数据很容易一起没了。 更好的做法: ```bash docker run -d \ --name mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ -v mysql-data:/var/lib/mysql \ mysql:8.0 ``` 或挂载宿主机目录: ```bash -v /opt/mysql-data:/var/lib/mysql ``` ### 14.2 不要乱用 latest 建议固定版本: ```yaml image: mysql:8.0 image: redis:7.2 image: nginx:1.25 ``` ### 14.3 容器要有清晰命名 ```bash --name rf-platform-api --name rf-platform-nginx --name rf-platform-redis ``` ### 14.4 配置和数据分开 推荐目录: ```text /opt/rf-platform/ docker-compose.yml .env nginx/ data/ logs/ uploads/ ``` ### 14.5 对外只暴露必要端口 推荐: ```text 外部 -> Nginx 80/443 Nginx -> API 8000 API -> Redis/MySQL ``` 数据库和 Redis 不一定要对外暴露。 ### 14.6 先看日志再猜问题 ```bash docker logs --tail 100 服务名 docker compose logs -f 服务名 ``` 日志是排障第一证据。 --- ## 15. Docker Compose 安装 WordPress 对应视频:`17.DockerCompose_安装wordpress` Compose 用一个 YAML 文件描述多个容器。 WordPress 需要: - WordPress 应用容器。 - MySQL 数据库容器。 - 数据卷保存数据库。 - 端口映射访问 WordPress。 - 网络让 WordPress 访问 MySQL。 ### 15.1 创建目录 ```bash mkdir -p /opt/wordpress-demo cd /opt/wordpress-demo ``` ### 15.2 编写 docker-compose.yml ```yaml services: db: image: mysql:8.0 container_name: wordpress-db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpresspass volumes: - db_data:/var/lib/mysql wordpress: image: wordpress:latest container_name: wordpress-web restart: unless-stopped depends_on: - db ports: - "8080:80" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpresspass WORDPRESS_DB_NAME: wordpress volumes: - wordpress_data:/var/www/html volumes: db_data: wordpress_data: ``` ### 15.3 启动 ```bash docker compose up -d ``` 查看: ```bash docker compose ps docker compose logs -f ``` 访问: ```bash curl -I http://127.0.0.1:8080 ``` 浏览器打开: ```text http://服务器IP:8080 ``` ### 15.4 停止和删除 停止: ```bash docker compose stop ``` 启动: ```bash docker compose start ``` 删除容器和网络: ```bash docker compose down ``` 连数据卷一起删除: ```bash docker compose down -v ``` 注意: > `down -v` 会删除数据库数据。学习环境可以用,真实项目要小心。 --- ## 16. Docker Compose 语法 对应视频:`18.DockerCompose_语法` Compose 的核心是 `services`。 ### 16.1 最小结构 ```yaml services: nginx: image: nginx:1.25 ports: - "8080:80" ``` 启动: ```bash docker compose up -d ``` ### 16.2 image 直接使用现成镜像: ```yaml services: redis: image: redis:7.2 ``` ### 16.3 build 使用 Dockerfile 构建镜像: ```yaml services: api: build: . image: rf-platform-api:1.0 ``` ### 16.4 container_name ```yaml container_name: rf-platform-api ``` 学习环境方便查看。但大型项目里有时不建议固定 container_name,因为可能影响扩容。 ### 16.5 ports ```yaml ports: - "8080:80" ``` 含义: ```text 宿主机端口:容器端口 ``` 如果只给内部服务用,可以不写 `ports`,只用 `expose` 或默认网络通信。 ### 16.6 environment ```yaml environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: app ``` 也可以使用 `.env` 文件: ```yaml environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} ``` `.env`: ```env MYSQL_ROOT_PASSWORD=123456 ``` ### 16.7 volumes 目录挂载: ```yaml volumes: - ./html:/usr/share/nginx/html ``` 命名卷: ```yaml volumes: - db_data:/var/lib/mysql volumes: db_data: ``` ### 16.8 networks ```yaml services: api: networks: - app-net redis: networks: - app-net networks: app-net: ``` 同一 Compose 项目默认会创建网络,很多简单项目不用手写 networks。 ### 16.9 depends_on ```yaml depends_on: - db ``` 含义是启动顺序依赖,不等于数据库已经完全可用。应用还应该有重试机制。 ### 16.10 restart ```yaml restart: unless-stopped ``` 服务器部署建议加上。 ### 16.11 常用 Compose 命令 ```bash docker compose up -d docker compose down docker compose ps docker compose logs -f docker compose logs --tail 100 api docker compose restart docker compose pull docker compose build docker compose up -d --build ``` --- ## 17. Docker Compose 其他 对应视频:`19.DockerCompose_其他` ### 17.1 查看项目状态 ```bash docker compose ps ``` ### 17.2 查看日志 全部服务: ```bash docker compose logs -f ``` 单个服务: ```bash docker compose logs -f api ``` 最近 100 行: ```bash docker compose logs --tail 100 api ``` ### 17.3 进入服务容器 ```bash docker compose exec api sh docker compose exec db mysql -uroot -p docker compose exec redis redis-cli ``` ### 17.4 重建服务 ```bash docker compose up -d --build ``` 适合 Dockerfile 或代码变化后重新构建。 ### 17.5 清理项目 ```bash docker compose down ``` 如果要删除数据卷: ```bash docker compose down -v ``` 再次提醒:`-v` 会删除 Compose 创建的命名卷,数据库数据可能消失。 --- ## 18. Dockerfile 制作镜像 对应视频:`20.Dockerfile_制作镜像` Dockerfile 是制作镜像的说明书。 ### 18.1 一个最小 Python FastAPI Dockerfile 项目结构: ```text rf-platform/ app/ main.py requirements.txt Dockerfile ``` `requirements.txt`: ```text fastapi uvicorn[standard] pandas matplotlib ``` `Dockerfile`: ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` 构建: ```bash docker build -t rf-platform-api:1.0 . ``` 运行: ```bash docker run -d \ --name rf-platform-api \ -p 8000:8000 \ rf-platform-api:1.0 ``` 测试: ```bash curl -v http://127.0.0.1:8000 ``` ### 18.2 常用 Dockerfile 指令 ```dockerfile FROM WORKDIR COPY RUN ENV EXPOSE CMD ENTRYPOINT ``` 解释: - `FROM`:基础镜像。 - `WORKDIR`:工作目录。 - `COPY`:复制文件到镜像。 - `RUN`:构建镜像时执行命令。 - `ENV`:设置环境变量。 - `EXPOSE`:声明容器内服务端口。 - `CMD`:容器启动时默认执行的命令。 - `ENTRYPOINT`:容器入口命令。 ### 18.3 CMD 和 RUN 的区别 `RUN` 是构建镜像时执行: ```dockerfile RUN pip install -r requirements.txt ``` `CMD` 是容器启动时执行: ```dockerfile CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` ### 18.4 .dockerignore 不要把无关文件复制进镜像。 `.dockerignore`: ```text .git __pycache__ .venv *.log data uploads outputs ``` 好处: - 构建更快。 - 镜像更小。 - 避免把本地数据、日志、密钥打进镜像。 --- ## 19. 镜像分层机制 对应视频:`21.Dockerfile_镜像分层机制` Docker 镜像是分层的。Dockerfile 里的很多指令都会产生层。 例如: ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` 可以看历史: ```bash docker history rf-platform-api:1.0 ``` ### 19.1 为什么先 COPY requirements.txt 推荐: ```dockerfile COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ ``` 不要一开始就: ```dockerfile COPY . . RUN pip install --no-cache-dir -r requirements.txt ``` 原因: - Docker 构建有缓存。 - 依赖文件不变时,安装依赖这一层可以复用。 - 代码变化时,只重新复制代码层。 - 构建速度更快。 ### 19.2 减小镜像体积 建议: - 使用 `python:3.11-slim` 而不是完整大镜像。 - 使用 `.dockerignore`。 - 安装依赖时加 `--no-cache-dir`。 - 不把数据、日志、临时文件复制进镜像。 ### 19.3 镜像不是数据仓库 不要把上传文件、数据库数据、分析结果写死进镜像。镜像应该保存程序和运行环境,数据应该用 volume 或目录挂载。 --- ## 20. 一键启动所有中间件 对应视频:`22.超酷_一键启动所有中间件` 这一集的核心是: > 用 Docker Compose 把一组常用中间件一次性启动起来。 中间件可以包括: - MySQL - Redis - Nginx - MinIO - PostgreSQL - RabbitMQ - Elasticsearch 你不一定都要学深入,但要会用 Compose 管理。 ### 20.1 示例:MySQL + Redis + Nginx ```yaml services: mysql: image: mysql:8.0 container_name: demo-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: demo volumes: - mysql_data:/var/lib/mysql redis: image: redis:7.2 container_name: demo-redis restart: unless-stopped volumes: - redis_data:/data nginx: image: nginx:1.25 container_name: demo-nginx restart: unless-stopped ports: - "8080:80" volumes: - ./nginx/html:/usr/share/nginx/html:ro volumes: mysql_data: redis_data: ``` 启动: ```bash docker compose up -d ``` 查看: ```bash docker compose ps ``` 日志: ```bash docker compose logs -f ``` ### 20.2 为什么这很重要 以后你做项目时,不应该手动一条条 `docker run` 启动一堆服务。 更好的方式是: ```text docker-compose.yml -> 记录服务、版本、端口、环境变量、挂载、网络 -> 一条命令启动 -> 一条命令停止 -> README 可复现 ``` --- ## 21. 访问测试全部通过 对应视频:`23.超酷_访问测试全部通过` 启动一组服务后,不等于部署成功。你要会测试。 ### 21.1 看容器是否运行 ```bash docker compose ps ``` 关注: - STATUS 是否 Up。 - PORTS 是否有映射。 - 是否反复 Restarting。 ### 21.2 看日志是否报错 ```bash docker compose logs --tail 100 docker compose logs -f mysql docker compose logs -f redis docker compose logs -f nginx ``` ### 21.3 测试端口 宿主机查看端口: ```bash ss -tunlp ``` 测试 HTTP: ```bash curl -I http://127.0.0.1:8080 ``` 测试 Redis: ```bash docker compose exec redis redis-cli ping ``` 测试 MySQL: ```bash docker compose exec mysql mysql -uroot -p ``` ### 21.4 排查访问失败 如果浏览器打不开: ```bash docker compose ps docker compose logs --tail 100 nginx ss -tunlp | grep 8080 curl -v http://127.0.0.1:8080 ``` 如果容器内服务访问不了另一个服务: ```bash docker compose exec api sh ping redis ``` 有些镜像没有 `ping`,可以用对应客户端测试,例如 `redis-cli`、`mysql`、`curl`。 --- ## 22. 销毁实例 对应视频:`24.销毁实例` 学习和实验结束后,要会清理。 ### 22.1 停止项目 ```bash docker compose stop ``` 只是停止,不删除容器。 ### 22.2 删除项目容器和网络 ```bash docker compose down ``` 会删除 Compose 创建的容器和网络,但默认不删除命名卷。 ### 22.3 连数据卷一起删 ```bash docker compose down -v ``` 这会删除数据卷。数据库、上传文件等可能丢失。 ### 22.4 删除镜像 ```bash docker rmi 镜像名:标签 ``` ### 22.5 清理未使用资源 查看占用: ```bash docker system df ``` 清理停止容器: ```bash docker container prune ``` 清理无用镜像: ```bash docker image prune ``` 清理无用卷: ```bash docker volume prune ``` 清理全部未使用资源: ```bash docker system prune ``` 谨慎使用: ```bash docker system prune -a ``` 它会清理更多未使用镜像,可能导致下次重新拉取很慢。 --- ## 23. 结束语:你应该学到什么程度 对应视频:`25.结束语` 你不需要现在就学 Kubernetes。先把 Docker 基础练扎实。 最低验收标准: - 能用 Docker 部署 Nginx。 - 能用 Docker 部署 Redis/MySQL。 - 能用 `docker logs` 看日志。 - 能用 `-p` 映射端口。 - 能用 `-v` 挂载目录或 volume。 - 能创建自定义网络。 - 能用 Compose 启动 WordPress 或一组中间件。 - 能写 Dockerfile 打包自己的 FastAPI 项目。 - 能解释镜像、容器、仓库、网络、卷的区别。 --- ## 24. 按视频顺序的练习任务 ### 任务 1:跑通 Nginx ```bash docker pull nginx:1.25 docker run -d --name nginx-demo -p 8080:80 nginx:1.25 docker ps curl -I http://127.0.0.1:8080 docker logs nginx-demo ``` 验收: - `docker ps` 能看到 nginx-demo。 - `curl` 返回 HTTP 响应头。 - 浏览器能访问 8080。 ### 任务 2:目录挂载 ```bash mkdir -p /opt/nginx-demo/html echo "hello docker" > /opt/nginx-demo/html/index.html docker rm -f nginx-demo docker run -d --name nginx-demo -p 8080:80 \ -v /opt/nginx-demo/html:/usr/share/nginx/html \ nginx:1.25 curl http://127.0.0.1:8080 ``` 验收: - 修改宿主机 `index.html` 后,访问内容同步变化。 ### 任务 3:Redis 自定义网络 ```bash docker network create app-net docker run -d --name redis --network app-net redis:7.2 docker run --rm -it --network app-net redis:7.2 redis-cli -h redis ping ``` 验收: ```text PONG ``` ### 任务 4:Compose 部署 WordPress 创建 `docker-compose.yml`,使用 WordPress + MySQL,然后: ```bash docker compose up -d docker compose ps docker compose logs --tail 100 curl -I http://127.0.0.1:8080 ``` 验收: - WordPress 初始化页面能打开。 - MySQL 数据使用 volume 保存。 ### 任务 5:Dockerfile 打包 FastAPI 构建: ```bash docker build -t rf-platform-api:1.0 . ``` 运行: ```bash docker run -d --name rf-platform-api -p 8000:8000 rf-platform-api:1.0 ``` 测试: ```bash curl -v http://127.0.0.1:8000 ``` 验收: - 能解释 Dockerfile 每一行。 - 能通过日志排查启动失败原因。 --- ## 25. Docker 常见问题排查表 ### 容器启动后马上退出 查看: ```bash docker ps -a docker logs 容器名 ``` 常见原因: - 启动命令错。 - 配置文件错。 - 环境变量缺失。 - 应用启动时报错。 ### 端口访问不了 查看: ```bash docker ps ss -tunlp | grep 端口 curl -v http://127.0.0.1:端口 ``` 常见原因: - `-p` 没写。 - 端口写反。 - 容器内服务没监听。 - 云安全组没放行。 端口映射别写反: ```text -p 宿主机端口:容器端口 ``` ### 数据丢失 常见原因: - 数据写在容器内部。 - 删除容器后没有 volume。 - 执行了 `docker compose down -v`。 解决: - 使用 volume。 - 使用宿主机目录挂载。 - 写清楚备份目录。 ### 容器之间互相访问失败 查看: ```bash docker network ls docker network inspect 网络名 docker inspect 容器名 ``` 解决: - 放到同一个自定义网络。 - 用容器名或 Compose 服务名访问。 - 不依赖容器 IP。 ### 镜像构建很慢 优化: - 使用 `.dockerignore`。 - 先复制依赖文件,再安装依赖。 - 固定基础镜像版本。 - 复用构建缓存。 --- ## 26. 你可以写进简历的 Docker 表达 技能栏: ```text Docker:熟悉镜像、容器、端口映射、目录挂载、数据卷、自定义网络、Dockerfile 与 Docker Compose,能够完成 Web 服务和常用中间件的容器化部署与日志排障。 ``` 项目描述: ```text 使用 Docker Compose 编排 Nginx、FastAPI、Redis/MySQL 等服务,配置端口映射、数据卷持久化和自定义网络;通过 docker logs、docker compose logs、ss、curl 等命令排查容器启动失败、端口不通和服务访问异常问题。 ``` 结合射频测试平台: ```text 将射频测试数据分析平台容器化,编写 Dockerfile 构建 FastAPI 应用镜像,使用 Docker Compose 管理后端服务、Nginx 反向代理和数据目录挂载,实现服务器一键部署与快速恢复。 ``` --- ## 27. 进阶:把 Docker 用到真实项目里 前面的视频内容已经够你入门。进阶阶段要从“能启动容器”升级到“能稳定部署项目”。 真实项目里 Docker 要解决这些问题: - 服务如何自动重启。 - 配置如何管理。 - 数据如何持久化和备份。 - 日志如何查看和限制大小。 - 服务之间如何通信。 - 镜像如何构建得更小更快。 - 部署失败后如何定位。 - 更新版本时如何减少中断。 你可以用下面这条主线学习进阶 Docker: ```text Dockerfile 优化 -> Compose 工程化 -> 数据卷和备份 -> 网络隔离 -> 健康检查 -> 日志和资源限制 -> Nginx 反向代理 -> 项目部署与回滚 ``` --- ## 28. 进阶 Dockerfile:写得像工程项目 基础 Dockerfile 能跑就行,进阶 Dockerfile 要考虑: - 构建速度。 - 镜像大小。 - 安全性。 - 可维护性。 - 缓存利用。 ### 28.1 更完整的 FastAPI Dockerfile ```dockerfile FROM python:3.11-slim ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app RUN apt-get update \ && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ RUN useradd -m appuser USER appuser EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` 这里比基础版多了几个点: - `PYTHONDONTWRITEBYTECODE=1`:不生成 `.pyc` 文件。 - `PYTHONUNBUFFERED=1`:日志更及时输出到控制台。 - `--no-install-recommends`:减少不必要系统包。 - `rm -rf /var/lib/apt/lists/*`:清理 apt 缓存,减小镜像。 - `USER appuser`:不用 root 运行应用,安全性更好。 ### 28.2 构建缓存技巧 推荐顺序: ```dockerfile COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ ``` 原因: - 依赖文件没变时,`pip install` 那一层可以复用。 - 只改业务代码时,构建速度会快很多。 ### 28.3 不要把密钥写进镜像 错误示例: ```dockerfile ENV MYSQL_PASSWORD=123456 COPY id_rsa /root/.ssh/id_rsa ``` 正确思路: - 密码放 `.env`,不要提交到公开仓库。 - 生产密钥用服务器环境变量、CI/CD Secret 或专门的密钥管理。 - 镜像只保存程序和运行环境。 ### 28.4 镜像构建常用命令 ```bash docker build -t rf-platform-api:1.0 . docker build --no-cache -t rf-platform-api:1.0 . docker history rf-platform-api:1.0 docker image inspect rf-platform-api:1.0 ``` `--no-cache` 适合排查缓存导致的构建异常,但平时不要滥用。 --- ## 29. 进阶:多阶段构建 多阶段构建适合前端、Go、Java 等需要先编译再运行的项目。核心思想是: > 构建阶段用完整工具链,运行阶段只保留运行所需文件。 ### 29.1 前端项目多阶段构建示例 ```dockerfile FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM nginx:1.25-alpine COPY --from=builder /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` 优点: - 最终镜像不包含 Node 构建工具。 - 镜像更小。 - 运行环境更干净。 ### 29.2 Go 项目多阶段构建示例 ```dockerfile FROM golang:1.22-alpine AS builder WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o app ./cmd/server FROM alpine:3.20 WORKDIR /app COPY --from=builder /src/app /app/app EXPOSE 8080 CMD ["/app/app"] ``` 你现在主要学 Python/FastAPI,多阶段构建不是必须,但理解它会让你看懂更多真实项目的 Dockerfile。 --- ## 30. 进阶 Compose:生产感更强的写法 基础 Compose 只要能启动。进阶 Compose 要考虑: - `.env` 管理配置。 - 健康检查。 - 日志大小限制。 - 资源限制。 - 网络隔离。 - 数据卷明确。 - 服务依赖和重启策略。 ### 30.1 一个更完整的项目结构 ```text rf-platform/ docker-compose.yml .env Dockerfile app/ nginx/ default.conf data/ uploads/ logs/ ``` ### 30.2 .env 示例 ```env APP_PORT=8000 NGINX_PORT=80 MYSQL_ROOT_PASSWORD=change-me MYSQL_DATABASE=rf_platform MYSQL_USER=rf_user MYSQL_PASSWORD=rf_pass ``` 注意: - `.env` 可以放学习项目里。 - 真正公开仓库不要提交真实密码。 - 可以提交 `.env.example`,让别人照着复制。 ### 30.3 Compose 示例:Nginx + API + MySQL + Redis ```yaml services: api: build: . image: rf-platform-api:1.0 container_name: rf-platform-api restart: unless-stopped env_file: - .env volumes: - ./uploads:/app/uploads - ./logs:/app/logs expose: - "8000" depends_on: - mysql - redis networks: - backend healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"] interval: 30s timeout: 5s retries: 3 start_period: 20s logging: driver: json-file options: max-size: "10m" max-file: "3" nginx: image: nginx:1.25 container_name: rf-platform-nginx restart: unless-stopped ports: - "${NGINX_PORT}:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - api networks: - frontend - backend mysql: image: mysql:8.0 container_name: rf-platform-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - mysql_data:/var/lib/mysql networks: - backend logging: driver: json-file options: max-size: "10m" max-file: "3" redis: image: redis:7.2 container_name: rf-platform-redis restart: unless-stopped volumes: - redis_data:/data networks: - backend networks: frontend: backend: volumes: mysql_data: redis_data: ``` 这个例子体现了真实部署思路: - 只有 Nginx 对外暴露端口。 - API、MySQL、Redis 都在后端网络里。 - 数据库使用 volume 持久化。 - API 上传文件和日志挂载到宿主机目录。 - 日志做大小限制。 - API 增加健康检查。 --- ## 31. 健康检查 healthcheck 健康检查用于判断容器内服务是否真的可用。 容器运行中,不代表应用可用。比如: - 进程还在,但接口卡死。 - Web 服务启动了,但数据库连不上。 - 服务端口监听了,但返回 500。 ### 31.1 Dockerfile 里写健康检查 ```dockerfile HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl -f http://127.0.0.1:8000/health || exit 1 ``` ### 31.2 Compose 里写健康检查 ```yaml healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"] interval: 30s timeout: 5s retries: 3 start_period: 20s ``` 查看健康状态: ```bash docker ps docker inspect 容器名 ``` 建议你的 FastAPI 项目提供一个接口: ```python @app.get("/health") def health(): return {"status": "ok"} ``` --- ## 32. 日志管理:别让 Docker 日志撑爆磁盘 Docker 默认使用 `json-file` 保存容器日志。如果不限制大小,长期运行可能撑爆磁盘。 查看 Docker 占用: ```bash docker system df du -sh /var/lib/docker ``` Compose 中限制日志: ```yaml logging: driver: json-file options: max-size: "10m" max-file: "3" ``` 含义: - 单个日志文件最大 10MB。 - 最多保留 3 个文件。 查看日志仍然用: ```bash docker logs --tail 100 容器名 docker compose logs -f api ``` 项目建议: - 应用日志输出到标准输出,方便 `docker logs` 查看。 - 关键业务日志也可以挂载到 `./logs`。 - Compose 里限制 Docker 日志大小。 --- ## 33. 资源限制:防止一个容器拖垮服务器 学习阶段通常不用限制资源,但真实服务器上建议知道这些参数。 ### 33.1 docker run 限制资源 限制内存: ```bash docker run -d --name api --memory 512m rf-platform-api:1.0 ``` 限制 CPU: ```bash docker run -d --name api --cpus 1.0 rf-platform-api:1.0 ``` ### 33.2 Compose 限制资源 普通 Compose 可以写: ```yaml services: api: image: rf-platform-api:1.0 mem_limit: 512m cpus: 1.0 ``` 查看实时资源: ```bash docker stats ``` 如果服务器只有 2C2G,不要一口气启动太多中间件。MySQL、Elasticsearch、OpenWebUI、Ollama 都可能吃资源。 --- ## 34. Compose profiles:按需启动服务 有些服务不是每次都要启动,比如管理后台、调试工具、一次性任务。 可以用 profiles: ```yaml services: api: image: rf-platform-api:1.0 redis: image: redis:7.2 adminer: image: adminer ports: - "8081:8080" profiles: - tools ``` 默认启动: ```bash docker compose up -d ``` 不会启动 `adminer`。 启动 tools: ```bash docker compose --profile tools up -d ``` 适合: - 数据库管理工具。 - 临时调试服务。 - 本地开发辅助容器。 --- ## 35. Nginx + Docker 的反向代理写法 你路线里 Docker 经常要和 Nginx 一起用。 ### 35.1 Nginx 在宿主机上 如果 Nginx 装在宿主机,后端容器映射到本机端口: ```yaml services: api: image: rf-platform-api:1.0 ports: - "127.0.0.1:8000:8000" ``` Nginx 配置: ```nginx server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 优点: - 宿主机 Nginx 管理多个项目方便。 - 后端端口只绑定 `127.0.0.1`,外部不能直接访问。 ### 35.2 Nginx 也在容器里 Compose: ```yaml services: nginx: image: nginx:1.25 ports: - "80:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - api api: image: rf-platform-api:1.0 expose: - "8000" ``` Nginx 配置: ```nginx server { listen 80; location / { proxy_pass http://api:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 注意: > Nginx 容器代理 API 容器时,地址用 Compose 服务名 `api`,不是 `127.0.0.1`。 这是很多 Docker 新手最容易错的地方。 --- ## 36. 部署更新和回滚 真实项目会不断更新。你要会更新,也要会回滚。 ### 36.1 更新镜像版本 假设当前: ```yaml image: rf-platform-api:1.0 ``` 更新为: ```yaml image: rf-platform-api:1.1 ``` 执行: ```bash docker compose pull docker compose up -d docker compose ps docker compose logs --tail 100 api ``` 如果是本地构建: ```bash docker compose build api docker compose up -d api ``` ### 36.2 回滚 把 Compose 里的版本改回: ```yaml image: rf-platform-api:1.0 ``` 执行: ```bash docker compose up -d api docker compose logs --tail 100 api ``` 所以镜像版本一定要固定,不要只写 `latest`。 ### 36.3 更新前备份 数据库类服务更新前先备份。 MySQL 备份示例: ```bash docker compose exec mysql \ mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} rf_platform > backup.sql ``` 也可以进入容器执行,或写专门的备份脚本。 --- ## 37. Docker 安全基础 你现在不需要学很深,但这些底线要知道。 ### 37.1 不要随便暴露数据库端口 不推荐: ```yaml mysql: ports: - "3306:3306" ``` 除非你明确需要外部访问数据库。更推荐只在 Docker 网络内部访问。 ### 37.2 不要把密码写进公开仓库 不要提交真实 `.env`。 可以提交: ```text .env.example ``` 内容: ```env MYSQL_ROOT_PASSWORD=please-change-me MYSQL_DATABASE=rf_platform MYSQL_USER=rf_user MYSQL_PASSWORD=please-change-me ``` ### 37.3 不要长期用 root 跑应用 Dockerfile 里尽量: ```dockerfile RUN useradd -m appuser USER appuser ``` ### 37.4 不要滥用 privileged 危险参数: ```bash --privileged ``` 它会给容器很高权限。除非你明确知道为什么需要,否则不要用。 ### 37.5 镜像来源要可靠 优先使用: - 官方镜像。 - 大厂维护镜像。 - 自己构建的镜像。 不要随便拉不明来源镜像跑在服务器上。 --- ## 38. 面向你的进阶实战项目 你可以做一个完整项目: > 射频测试数据分析平台 Docker 化部署 ### 38.1 项目功能 - 上传 `.csv` 或 `.s2p` 文件。 - FastAPI 解析文件。 - pandas 处理数据。 - matplotlib 生成曲线图。 - 页面展示 S11/S21 曲线。 - Redis 缓存任务状态。 - MySQL 保存上传记录。 - Nginx 对外提供访问。 ### 38.2 推荐架构 ```text 浏览器 -> Nginx 容器 80/443 -> FastAPI 容器 8000 -> Redis 容器 -> MySQL 容器 -> uploads/logs 挂载目录 ``` ### 38.3 你要交付的文件 ```text Dockerfile docker-compose.yml .env.example nginx/default.conf README.md ``` README 要包含: - 环境要求。 - 启动命令。 - 停止命令。 - 日志查看。 - 数据目录。 - 常见问题排查。 ### 38.4 面试时的讲法 ```text 我将 FastAPI 射频测试数据分析平台容器化,使用 Dockerfile 构建应用镜像,并通过 Docker Compose 编排 Nginx、API、Redis 和 MySQL。部署中我配置了数据卷持久化、容器自定义网络、日志大小限制和健康检查;排障时主要使用 docker compose ps、docker compose logs、ss、curl 等命令定位容器状态、端口映射、服务健康和反向代理问题。 ``` 这比单纯说“我学过 Docker”强很多。 --- ## 39. 进阶排障清单 当 Docker 项目访问不了时,按这个顺序查。 ### 39.1 看容器状态 ```bash docker compose ps docker ps -a ``` 重点看: - 是否 Up。 - 是否 Restarting。 - 是否 Exited。 - 端口是否映射。 ### 39.2 看日志 ```bash docker compose logs --tail 100 docker compose logs -f api docker compose logs -f nginx ``` 重点搜: - error - failed - permission denied - connection refused - no such file or directory - address already in use ### 39.3 看端口 ```bash ss -tunlp | grep 80 ss -tunlp | grep 8000 curl -v http://127.0.0.1 curl -v http://127.0.0.1:8000 ``` 如果 API 没有映射到宿主机,只能从同一 Docker 网络或 Nginx 容器里访问。 ### 39.4 进容器内部查 ```bash docker compose exec api sh docker compose exec nginx sh ``` 在 Nginx 容器里测试 API: ```bash curl -v http://api:8000/health ``` 如果这里不通,说明 Docker 网络、服务名、API 监听地址或 API 本身有问题。 ### 39.5 查挂载 ```bash docker inspect 容器名 ls -la ./uploads ls -la ./logs ``` 重点看: - 宿主机目录是否存在。 - 容器内路径是否正确。 - 权限是否允许写入。 ### 39.6 查 Docker 资源 ```bash docker system df docker stats df -h free -h ``` 磁盘满、内存不足都会让容器异常。 --- ## 40. 最终总结 这套视频的主线可以浓缩成一条工程链路: ```text 理解 Docker 架构 -> 安装 Docker -> 操作镜像 -> 操作容器 -> 掌握 docker run 参数 -> 保存和分享镜像 -> 做数据持久化 -> 建自定义网络 -> 用 Compose 编排多服务 -> 用 Dockerfile 制作自己的镜像 -> 一键启动中间件 -> 测试访问 -> 销毁和清理资源 ``` 你学完后最应该具备的能力不是“我看过 Docker 视频”,而是: > 给我一台 Linux 服务器和一个项目,我能用 Docker/Compose 把它部署起来,并且能定位端口、日志、挂载、网络和镜像构建相关的问题。 这正好对应你的路线:Linux 是服务器基础,Docker 是部署能力核心,Nginx 是对外入口,Python/FastAPI 是你的项目载体,射频测试数据平台是你的差异化方向。 标签: none