别再手动一个个启动容器了!用Docker Compose编排一个Web+MySQL+Redis的完整项目(附yml文件详解)

张开发
2026/4/21 12:19:51 15 分钟阅读

分享文章

别再手动一个个启动容器了!用Docker Compose编排一个Web+MySQL+Redis的完整项目(附yml文件详解)
别再手动一个个启动容器了用Docker Compose编排一个WebMySQLRedis的完整项目附yml文件详解每次部署多容器项目时最头疼的就是手动启动每个服务、配置网络、挂载数据卷。想象一下先启动MySQL容器设置root密码和存储卷再启动Redis配置持久化最后部署Web应用确保能连接到数据库和缓存。这种重复劳动不仅低效还容易出错。而Docker Compose正是解决这一痛点的利器——它允许你用一份YAML文件定义整个应用栈然后通过一条命令启动所有服务。1. 为什么需要Docker Compose在真实开发场景中几乎没有应用是单一容器能支撑的。以典型的Web项目为例核心服务应用服务器如Spring Boot、数据库MySQL、缓存Redis辅助服务消息队列RabbitMQ、搜索引擎Elasticsearch基础设施负载均衡Nginx、监控Prometheus手动管理这些容器的痛点包括启动顺序依赖数据库必须先于应用启动网络配置复杂容器间需要互通但又要隔离外部访问环境变量传递数据库连接字符串需要注入到Web容器数据持久化数据库文件、缓存数据需要挂载到宿主机Docker Compose通过声明式配置解决这些问题。下面是一个对比传统方式和Compose方式的典型流程操作步骤手动操作命令示例Compose方式创建网络docker network create app_net在yml中定义networks块启动MySQLdocker run --name mysql -e MYSQL_ROOT_PASSWORD123456...services.mysql.environment启动Redisdocker run --name redis -v redis_data:/data...services.redis.volumes启动Web应用docker run --name web --link mysql --link redis...services.web.depends_on提示Compose的depends_on只能控制启动顺序不能确保服务已就绪。对于数据库这类需要等待初始化完成的服务建议结合健康检查使用。2. 实战编写docker-compose.yml让我们构建一个Spring Boot MySQL Redis的完整项目。假设项目结构如下myapp/ ├── docker-compose.yml ├── backend/ │ ├── Dockerfile │ └── target/app.jar # Spring Boot打包结果 ├── mysql/ │ └── init.sql # 数据库初始化脚本 └── redis/ └── redis.conf # Redis自定义配置2.1 基础结构解析每个Compose文件包含三个核心部分version: 3.8 # 指定Compose语法版本 services: # 定义所有服务容器 web: build: ./backend ports: - 8080:8080 volumes: # 声明数据卷 db_data: networks: # 定义网络 app_net: driver: bridge关键版本选择建议3.x版本支持Swarm模式扩展生产环境建议使用3.8以获得最新功能不同Docker Engine版本有兼容性要求2.2 完整配置详解以下是带详细注释的yml文件version: 3.8 services: # Spring Boot应用服务 webapp: build: context: ./backend dockerfile: Dockerfile # 指定Dockerfile路径 container_name: myapp_web ports: - 8080:8080 environment: - SPRING_DATASOURCE_URLjdbc:mysql://mysql:3306/mydb - SPRING_REDIS_HOSTredis depends_on: - mysql - redis networks: - app_net restart: unless-stopped # 异常退出时自动重启 # MySQL数据库服务 mysql: image: mysql:8.0 container_name: myapp_mysql environment: - MYSQL_ROOT_PASSWORDmysecret - MYSQL_DATABASEmydb volumes: - db_data:/var/lib/mysql - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本 ports: - 3306:3306 networks: - app_net healthcheck: # 健康检查 test: [CMD, mysqladmin, ping, -h, localhost] interval: 5s timeout: 3s retries: 5 # Redis缓存服务 redis: image: redis:6 container_name: myapp_redis command: redis-server --requirepass mypassword # 设置密码 volumes: - redis_data:/data - ./redis/redis.conf:/usr/local/etc/redis/redis.conf # 挂载自定义配置 ports: - 6379:6379 networks: - app_net volumes: db_data: redis_data: networks: app_net: driver: bridge2.3 关键配置项解析服务依赖与启动顺序depends_on: - mysql - redis虽然depends_on定义了启动顺序但更好的实践是为MySQL添加健康检查在应用启动命令中添加等待脚本例如# 在Dockerfile中添加健康检查等待脚本 HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1数据持久化方案对比方式优点缺点适用场景匿名卷自动创建简单难以维护删除容器会丢失开发环境临时数据命名卷推荐生命周期独立于容器需要显式声明生产环境数据库存储宿主机目录绑定直接访问宿主机文件路径依赖宿主机环境配置文件、初始化脚本网络隔离策略默认创建的app_net具有以下特性所有服务通过服务名如mysql互相访问对外暴露的只有webapp服务的8080端口可通过networks定义多个网络实现更细粒度隔离3. 高效开发技巧3.1 常用操作命令启动并构建所有服务开发环境docker-compose up -d --build仅重建并启动特定服务docker-compose up -d --no-deps --build webapp查看服务日志docker-compose logs -f webapp执行数据库迁移docker-compose exec webapp ./migrate.sh3.2 性能优化配置对于生产环境建议添加以下配置services: mysql: deploy: resources: limits: cpus: 2 memory: 2G ulimits: nproc: 65535 nofile: soft: 20000 hard: 400003.3 多环境配置方案通过环境变量和多个Compose文件实现docker-compose.yml # 基础配置 docker-compose.override.yml # 开发环境配置默认加载 docker-compose.prod.yml # 生产环境配置启动时指定配置docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d4. 常见问题排查4.1 容器启动失败排查步骤查看日志docker-compose logs service_name检查配置docker-compose config进入容器docker-compose exec service_name sh验证网络docker network inspect myapp_app_net4.2 典型错误解决方案问题1MySQL连接被拒绝解决确保depends_on配合健康检查使用或在应用启动脚本中添加等待逻辑问题2端口冲突解决检查ports配置或使用docker-compose ps查看运行状态问题3卷权限问题解决在Dockerfile中正确设置用户权限例如RUN mkdir -p /var/lib/mysql chown -R mysql:mysql /var/lib/mysql问题4环境变量未生效解决使用docker-compose exec service_name env验证环境变量注意修改docker-compose.yml后需要重新运行docker-compose up -d使更改生效。对于某些配置如环境变量可能需要先执行docker-compose down再重新启动。

更多文章