新闻详情

新闻详情

首页 / 资讯中心 / 详情

一套 Compose 搭起完整开发环境:MySQL + Redis + Nginx

发布时间:2026/10/1 20:44:25来源:尧图网络
一套 Compose 搭起完整开发环境:MySQL + Redis + Nginx
1. 引言这是系列实战的收官篇。前面几篇我们分别搞定了基础环境、后端服务、前端构建现在到了把它们串起来的时候。本篇文章的目标很简单用一套 Docker Compose 文件把 MySQL、Redis、后端、前端、Nginx 全部跑起来做到 clone 即跑。你将会得到一个完整可复制的 compose 栈数据库 缓存 后端 前端 反向代理初始化 SQL 注入、健康检查、热更新挂载、端口规划的全套实践配套 README启动 / 停止 / 重置 / 备份四个操作数据与配置的开发-生产双模式切换。前置依赖本系列第 03 篇Docker 基础、第 05 篇后端容器化、第 07 篇前端容器化。如果你还没看过建议先补上。2. 整体架构先看我们要搭什么。一个典型的全栈开发环境包含五个角色角色技术选型作用数据库MySQL 8持久化业务数据缓存Redis 7会话、热点数据、队列后端Spring Boot / Node按你的技术栈业务逻辑前端Vite / Webpack 构建产物静态页面反向代理Nginx统一入口、路由、静态资源它们之间的关系浏览器Nginx 反向代理 :80前端静态资源后端 API :8080MySQL :3306Redis :6379Nginx 是唯一对外暴露的端口浏览器只跟它打交道。前端静态资源由 Nginx 直接托管/api开头的请求反向代理到后端容器后端再访问 MySQL 和 Redis。3. 端口规划端口规划是 compose 栈最容易踩坑的地方。原则很简单宿主机端口尽量不暴露容器间用内部网络通信。3.1 开发模式端口服务容器内端口宿主机映射说明Nginx808080唯一对外入口后端8080不映射仅容器内访问MySQL33063306开发时方便用 Navicat 连接Redis63796379开发时方便用客户端查看3.2 生产模式端口生产模式只暴露 Nginx 的 443/80MySQL 和 Redis 完全不映射到宿主机避免数据库直接暴露公网。3.3 端口冲突排查如果你本机已经装了 MySQL 或 Redis3306/6379 很可能被占用。两个解决办法开发模式改映射端口比如3307:3306用docker compose ps查看占用情况先停掉冲突容器。坑位 1端口规划冲突。建议在 README 里明确写清楚每个端口的作用避免团队协作时互相踩。4. 目录结构先规划好工程目录这是clone 即跑的基础fullstack-demo/ ├── docker-compose.yml # 主编排文件 ├── docker-compose.prod.yml # 生产模式覆盖文件 ├── .env # 环境变量开发 ├── .env.prod # 环境变量生产 ├── README.md # 操作手册 ├── mysql/ │ ├── init/ │ │ └── 01-init.sql # 初始化 SQL首次启动自动执行 │ └── conf/ │ └── my.cnf # MySQL 自定义配置 ├── backend/ │ ├── Dockerfile │ └── src/ # 后端源码 ├── frontend/ │ ├── Dockerfile │ └── dist/ # 构建产物或源码构建 └── nginx/ ├── nginx.conf # 反向代理配置 └── conf.d/ └── default.conf5. docker-compose.yml 主文件下面给出完整可复制的 compose 文件。这是核心逐段解释。5.1 基础声明version:3.8name:fullstack-demoservices:# ... 各服务定义见下文5.2 MySQL 服务mysql:image:mysql:8.0container_name:demo-mysqlrestart:unless-stoppedenvironment:MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}MYSQL_DATABASE:${MYSQL_DATABASE}MYSQL_USER:${MYSQL_USER}MYSQL_PASSWORD:${MYSQL_PASSWORD}ports:-${MYSQL_PORT}:3306volumes:-mysql_data:/var/lib/mysql-./mysql/init:/docker-entrypoint-initdb.d-./mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnfhealthcheck:test:[CMD,mysqladmin,ping,-h,localhost]interval:10stimeout:5sretries:5start_period:30s几个要点初始化 SQL 注入/docker-entrypoint-initdb.d目录下的.sql文件会在首次启动时按文件名顺序自动执行。注意是首次数据卷已存在就不会再执行。健康检查mysqladmin ping是官方推荐方式start_period给足 MySQL 冷启动时间。数据持久化mysql_data命名卷保存数据容器删了数据还在。5.3 Redis 服务redis:image:redis:7-alpinecontainer_name:demo-redisrestart:unless-stoppedcommand:[redis-server,--appendonly,yes]ports:-${REDIS_PORT}:6379volumes:-redis_data:/datahealthcheck:test:[CMD,redis-cli,ping]interval:10stimeout:5sretries:5--appendonly yes开启 AOF 持久化开发环境足够用。redis-cli ping返回PONG即健康。5.4 后端服务backend:build:./backendcontainer_name:demo-backendrestart:unless-stoppeddepends_on:mysql:condition:service_healthyredis:condition:service_healthyenvironment:SPRING_DATASOURCE_URL:jdbc:mysql://mysql:3306/${MYSQL_DATABASE}?useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/ShanghaiSPRING_DATASOURCE_USERNAME:${MYSQL_USER}SPRING_DATASOURCE_PASSWORD:${MYSQL_PASSWORD}SPRING_DATA_REDIS_HOST:redisSPRING_DATA_REDIS_PORT:6379volumes:-./backend/src:/app/src# 开发模式热更新挂载生产模式由 prod 文件覆盖坑位 2容器内 localhost 误区。后端连接 MySQL 时绝对不能写localhost或127.0.0.1要写服务名mysql。因为容器内的 localhost 指向容器自己不是宿主机。Compose 会自动做 DNS 解析服务名即主机名。5.5 前端服务frontend:build:./frontendcontainer_name:demo-frontendrestart:unless-stoppedvolumes:-./frontend/dist:/usr/share/nginx/html:rodepends_on:-backend开发模式下前端构建产物通过挂载直接进 Nginx 的静态目录。改完前端代码重新构建刷新即生效。5.6 Nginx 反向代理nginx:image:nginx:1.25-alpinecontainer_name:demo-nginxrestart:unless-stoppedports:-${NGINX_PORT}:80volumes:-./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf:ro-frontend_dist:/usr/share/nginx/html:rodepends_on:-frontend-backend5.7 网络与卷声明networks:default:name:fullstack-demo-netvolumes:mysql_data:redis_data:frontend_dist:所有服务默认加入同一个网络容器间通过服务名互通无需额外配置。6. Nginx 反向代理配置nginx/conf.d/default.confserver { listen 80; server_name localhost; # 前端静态资源 root /usr/share/nginx/html; index index.html; # 前端路由SPA history 模式 location / { try_files $uri $uri/ /index.html; } # API 反向代理 location /api/ { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|svg|woff2?)$ { expires 7d; add_header Cache-Control public, immutable; } }注意proxy_pass http://backend:8080这里backend是 compose 服务名Nginx 容器通过内部网络解析到后端容器。7. 环境变量与双模式切换7.1 .env开发模式# 数据库MYSQL_ROOT_PASSWORDroot123456MYSQL_DATABASEdemoMYSQL_USERdemoMYSQL_PASSWORDdemo123456MYSQL_PORT3306# RedisREDIS_PORT6379# NginxNGINX_PORT80807.2 .env.prod生产模式# 数据库生产用强密码MYSQL_ROOT_PASSWORDChangeMe_Strong_PasswordMYSQL_DATABASEdemoMYSQL_USERdemoMYSQL_PASSWORDChangeMe_Strong_Password# 生产不映射数据库端口MYSQL_PORT127.0.0.1:3306REDIS_PORT127.0.0.1:6379# Nginx 对外端口NGINX_PORT807.3 docker-compose.prod.ymlservices:mysql:ports:-${MYSQL_PORT}:3306redis:ports:-${REDIS_PORT}:6379backend:build:context:./backenddockerfile:Dockerfile.prodvolumes:[]environment:SPRING_PROFILES_ACTIVE:prodfrontend:build:context:./frontenddockerfile:Dockerfile.prodvolumes:[]nginx:ports:-${NGINX_PORT}:80-443:443volumes:-./nginx/conf.d/prod.conf:/etc/nginx/conf.d/default.conf:ro7.4 切换命令# 开发模式dockercompose --env-file .env up-d# 生产模式dockercompose --env-file .env.prod-fdocker-compose.yml-fdocker-compose.prod.yml up-d--build坑位 3MySQL 8 认证插件兼容。MySQL 8 默认用caching_sha2_password老客户端如某些版本的 Navicat、旧版 JDBC 驱动会报Authentication plugin caching_sha2_password cannot be loaded。解决办法连接串加allowPublicKeyRetrievaltrue或建用户时指定mysql_native_password。8. 初始化 SQL 注入mysql/init/01-init.sql-- 创建业务表CREATETABLEIFNOTEXISTSuser(idBIGINTPRIMARYKEYAUTO_INCREMENT,usernameVARCHAR(50)NOTNULLUNIQUE,emailVARCHAR(100),created_atDATETIMEDEFAULTCURRENT_TIMESTAMP)ENGINEInnoDBDEFAULTCHARSETutf8mb4;-- 插入初始数据INSERTINTOuser(username,email)VALUES(admin,adminexample.com),(demo,demoexample.com);-- 创建索引CREATEINDEXidx_user_emailONuser(email);注意只有数据卷为空时才会执行。想重新执行需要先docker compose down -v清掉数据卷。9. 热更新挂载开发模式下源码目录直接挂载进容器改代码即时生效# 后端热更新以 Spring Boot DevTools 为例volumes:-./backend/src:/app/src# 前端热更新Vite 开发服务器volumes:-./frontend/src:/app/src后端配合 DevTools 自动重启前端配合 Vite HMR 秒级刷新。生产模式用volumes: []覆盖掉挂载改用镜像内构建产物。10. README四个核心操作配套 README 是clone 即跑的最后一块拼图。四个操作必须写清楚10.1 启动gitclonerepo-urlcdfullstack-democp.env.example .envdockercompose up-d首次启动会自动构建镜像、初始化数据库。等所有容器 healthy 后访问http://localhost:8080。10.2 停止# 停止但不删除容器dockercompose stop# 停止并删除容器保留数据卷dockercompose down10.3 重置# 彻底重置删除容器 数据卷下次启动重新初始化dockercompose down-vdockercompose up-d警告-v会删除数据库数据生产环境慎用。10.4 备份# 备份 MySQLdockerexecdemo-mysqlsh-cexec mysqldump -uroot -p$MYSQL_ROOT_PASSWORD demobackup_$(date%Y%m%d).sql# 备份 RedisRDB 文件dockercpdemo-redis:/data/dump.rdb ./redis_backup.rdb# 恢复 MySQLcatbackup.sql|dockerexec-idemo-mysqlsh-cexec mysql -uroot -p$MYSQL_ROOT_PASSWORD demo11. 验证与排错11.1 查看容器状态dockercomposeps所有服务应该是running (healthy)状态。11.2 查看日志dockercompose logs-fnginxdockercompose logs-fbackend11.3 常见问题速查症状原因解决后端连不上数据库用了 localhost改成服务名mysql初始化 SQL 没执行数据卷已存在docker compose down -v后重启Navicat 连不上 MySQL 8认证插件不兼容连接串加allowPublicKeyRetrievaltrue端口被占用本机已有服务改.env里的映射端口前端页面 404SPA 路由没配Nginx 加try_files回退12. 总结到这里一套完整的全栈开发环境就搭好了。回顾一下我们做了什么端口规划只暴露 Nginx容器间用内部网络通信初始化 SQL 注入首次启动自动建表、插数据健康检查depends_on配合condition: service_healthy保证启动顺序热更新挂载开发模式源码直挂改完即生效双模式切换一套 compose 文件.env 覆盖文件切换开发/生产README 四操作启动 / 停止 / 重置 / 备份clone 即跑。三个坑位也帮你提前踩平了端口规划冲突 → 统一在.env管理README 写清楚MySQL 8 认证插件兼容 → 连接串加allowPublicKeyRetrievaltrue容器内 localhost 误区 → 一律用服务名通信。现在把这份工程推到 GitHub任何人在任何机器上git clone加docker compose up -d三分钟就能跑起完整环境。这就是clone 即跑的最终形态。系列到此收官。从第一行的 Docker 命令到这一整套可复制的工程你已经拥有了独立搭建和交付全栈环境的能力。剩下的就是在真实项目里不断打磨了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

“互联网+”打车APP补贴策略:供需匹配、规则引擎与AB测试避坑指南 2026/10/1 22:27:10

“互联网+”打车APP补贴策略:供需匹配、规则引擎与AB测试避坑指南

简介:《互联网打车APP补贴策略研究与分析》是一份聚焦移动出行领域市场策略的PDF文献,面向APP产品运营、数据分析人员及互联网商业模式研究者,适合作为参考文献或专业指导材料。文档以传统出租车行业信息不对称为切入点,梳理了打车…

阅读更多 →
西门子PLC云端遥控实战:从网关选型到S7-200 SMART远程控制 2026/10/1 22:27:10

西门子PLC云端遥控实战:从网关选型到S7-200 SMART远程控制

1. 先从半夜那个电话说起:云端遥控解决的是什么问题做工业自动化这些年,我遇到过太多类似场景:设备半夜报警,现场停机,人在外地出差,电话打了一圈,最后只能让值班人员先去现场按一下复位按钮。运…

阅读更多 →
Hindsight:LLM 请求观测与诊断系统 2026/10/1 22:26:56

Hindsight:LLM 请求观测与诊断系统

1. 项目概述:Hindsight 不是“事后诸葛亮”,而是一套可落地的 LLM 接口观测与诊断系统你有没有遇到过这样的场景:一个刚写好的 Python 脚本,调用 OpenAI API 时突然返回401 Unauthorized: incorrect api key provided,…

阅读更多 →
空间代谢组驱动的AI原生药物发现:从分子定位到功能解码 2026/10/1 22:26:56

空间代谢组驱动的AI原生药物发现:从分子定位到功能解码

1. 这不是又一家“AI生物”的概念公司,而是一次对药物发现底层逻辑的重写最近看到Enveda融资3.11亿美元、估值冲到20亿美元的消息,朋友圈里不少做计算化学的朋友第一反应是:“又一家AI制药公司融大钱?”——但如果你真去扒它的技术…

阅读更多 →
强化学习稀疏奖励难题:HER事后经验回放原理与实战 2026/10/1 22:26:49

强化学习稀疏奖励难题:HER事后经验回放原理与实战

如果你训练过一个机械臂抓取任务,大概率经历过这种绝望:智能体在环境里乱动了几万个step,reward始终是-1,没有任何一个动作能碰到目标物体。不是网络容量不够,也不是学习率调错,而是奖励函数给的有效信号太…

阅读更多 →
Spring Boot用户增删查改实战:三层架构从入门到规范 2026/10/1 22:26:42

Spring Boot用户增删查改实战:三层架构从入门到规范

刚学 Spring Boot 的时候,我也是从“用户增删查改”起步的。这个功能看起来简单——无非就是对着数据库做四次操作——但把这四个操作写得规范、写得有章法,却难倒了不少人。后台私信里问得最多的不是“Mapper 里 SQL 怎么写”,而是“Control…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉