Docker Compose 本地开发环境怎么搭,先理解服务名、数据卷和初始化脚本

4次阅读
没有评论

本地开发环境一旦超过一个服务,就很容易从“启动应用”变成“到处找端口、连数据库、翻日志”。这时候 Docker Compose 的价值就出来了:它不是单纯帮你少敲几条 docker run,而是把应用、数据库、缓存、反向代理这些依赖放进同一份可重复执行的环境说明里。

如果只是临时启动一个 Redis,用单条 docker run 就够了。但如果是一个 Java 服务依赖 MySQL、Redis、Nginx,或者本地要跑 Kafka、Zookeeper 这种多容器组合,用 Compose 会清晰很多。

Compose 适合解决什么问题

Compose 最适合这几类场景:

  1. 应用服务加 MySQL、Redis、Nginx。
  2. Kafka 加 Zookeeper。
  3. 本地开发环境。
  4. 简单测试环境。

它的核心好处是把多个容器放在同一个编排文件里。容器之间可以直接用服务名访问,比如应用容器访问 MySQL 时可以写 mysql:3306,不需要先查容器 IP。

这点很重要。很多本地环境问题,其实不是服务没启动,而是连接地址写错了:宿主机访问容器用 localhost:映射端口,容器访问另一个容器则优先用 Compose 服务名。

常用命令先记住这几个

日常使用不需要背太多命令,先记住下面几条就够:

# 后台启动
docker compose up -d

# 查看容器状态
docker compose ps

# 查看日志
docker compose logs -f

# 停止并删除容器
docker compose down

# 重新构建并启动
docker compose up -d --build

旧版本命令是 docker-compose,新版本更推荐 docker compose。如果你在网上看到两种写法,不一定是谁写错了,多半是版本差异。

Java 服务加 MySQL 的基本结构

一个常见的本地环境是 Java 服务加 MySQL。大体结构可以这样理解:

version: "3"

services:
  mysql:
    image: mysql/mysql-server:5.7
    environment:
      MYSQL_DATABASE: demo
      MYSQL_ROOT_PASSWORD: root
      MYSQL_ROOT_HOST: "%"
      TZ: Asia/Shanghai
    ports:
      - "3306:3306"
    volumes:
      - ./db/migration:/docker-entrypoint-initdb.d
      - ./mysql/data:/var/lib/mysql
    restart: always

  server:
    build: .
    working_dir: /app
    environment:
      TZ: Asia/Shanghai
    volumes:
      - ./:/app
      - ~/.m2:/root/.m2
    ports:
      - "8080:8080"
    command: mvn spring-boot:run -Dspring-boot.run.profiles=docker
    depends_on:
      - mysql

这份配置里,真正要理解的不是每个字段,而是几个关键点。

服务名就是容器之间的域名

在同一个 Compose 项目里,mysql 这个服务名可以当成内部域名使用。也就是说,server 容器里访问数据库时,连接地址通常写:

jdbc:mysql://mysql:3306/demo

而不是写:

jdbc:mysql://localhost:3306/demo

localhost 在容器里指的是容器自己,不是宿主机,也不是 MySQL 容器。这个概念没分清时,经常会出现“端口明明映射了,应用还是连不上数据库”的问题。

数据卷决定数据会不会丢

MySQL、Redis 这类服务要特别注意数据目录。比如:

volumes:
  - ./mysql/data:/var/lib/mysql

左边是宿主机目录,右边是容器内目录。这样做的好处是容器删了,数据还能留在项目目录里。否则你每次重建容器,都可能像换了一台新机器一样,数据库内容跟着没了。

Redis 也类似:

volumes:
  - ./redis/data:/data
  - ./redis/redis.conf:/etc/redis/redis.conf

本地开发建议把数据和配置映射出来。这样配置改动能追踪,数据也更容易备份和清理。

初始化脚本只在空数据目录执行

MySQL 官方镜像有个常用目录:

/docker-entrypoint-initdb.d

你可以把初始化 SQL 或 shell 脚本挂进去,例如:

volumes:
  - ./db/migration:/docker-entrypoint-initdb.d

但这里有个容易踩的点:初始化脚本通常只会在 /var/lib/mysql 为空时执行。也就是说,如果数据目录已经存在,哪怕你后面新增了 SQL 文件,也不会自动重新跑。

所以排查“初始化 SQL 怎么没执行”时,先看数据目录是不是旧的。开发环境可以删除本地数据目录重来,但生产或重要测试数据不要这么干。

depends_on 只保证启动顺序

depends_on 很容易被误解。它能保证 servermysql 之后启动,但不保证 MySQL 已经完全 ready。

MySQL 容器启动后,还要经历初始化、建库、加载权限等过程。这个时间里应用如果立刻连接,仍然可能失败。

更稳的做法是:

  1. 应用侧连接池和启动流程支持重试。
  2. 本地排查时先看 docker compose logs -f mysql
  3. 必要时加健康检查,等依赖 ready 后再启动应用。

不要把 depends_on 当成“依赖服务已经可用”的保证。

Kafka 和 Zookeeper 要注意 advertised 地址

Kafka 这类服务比 MySQL 更容易踩网络地址问题。历史上常见配置会出现:

environment:
  KAFKA_ADVERTISED_HOST_NAME: 192.168.5.139
  KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181

这里的 KAFKA_ADVERTISED_HOST_NAME 要能被客户端访问到。如果客户端在宿主机、容器内、局域网其他机器,写法可能都不一样。

所以 Kafka 连不上时,不要只看端口是否暴露,也要看它对外宣告的地址是不是客户端能访问的地址。

本地排查顺序

Compose 环境启动失败时,可以按这个顺序查:

  1. docker compose ps 看容器是否都在运行。
  2. docker compose logs -f 服务名 看启动日志。
  3. 确认端口映射有没有冲突。
  4. 容器之间访问用服务名,宿主机访问用映射端口。
  5. 确认数据卷路径是否正确。
  6. 确认初始化脚本是否因为旧数据目录而没有执行。
  7. 外网镜像或 Maven 依赖下载慢时,先解决代理和镜像源。

排查时不要急着改一堆配置。先确认是哪一层不通:容器没启动、端口没暴露、服务名写错、数据库没 ready,还是初始化数据不对。

小结

Docker Compose 搭本地开发环境,最重要的不是把 YAML 写得多复杂,而是理解几个稳定规则:

  • 多容器环境用 Compose 比一堆 docker run 更容易复现。
  • 容器之间优先用服务名访问。
  • 数据目录要用 volume 映射出来。
  • MySQL 初始化脚本只在空数据目录时自动执行。
  • depends_on 只管启动顺序,不保证服务已可连接。

把这几件事想清楚,本地 Java、MySQL、Redis、Nginx、Kafka 这类组合环境就会少很多玄学问题。

正文完
 0
bdspAdmin
版权声明:本站原创文章,由 bdspAdmin 于2026-06-10发表,共计2948字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)