记一次 SpringBoot + Docker 内部容器通信失败问题

原味地址:记一次 SpringBoot + Docker 内部容器通信失败问题 - 林子宸的博客

年底了,最近公司项目颇忙,又加上服务器到期了,没有续费(穷),所以重新购买了一个阿里的服务器,但因为域名是在腾讯云办理的,又需要将域名转到阿里旗下,前前后后的,耽误了不少时间,所以最近一直没有更新博客。(给懒找几个借口)。

在之前服务器上,所有的服务都是原生部署的,考虑到以后会经常更换新的服务器,每次配置都需要花大把的时间,所以本次及以后就通过 docker 容器来部署项目,并通过 docker compose 来管理容器,这样就方便多了。嗯,说干就干。

docker-compose.yml

通过百度 + CV大法,啪,很快啊,就将需要的配置 CV 过来了。

version: "3"

services:
  # 给SpringBoot起一个自定义的服务名
  myblog:
    # 将来 Dockerfile 构建的镜像名及版本号
    image: myblog:1.1
    # 指定容器名称
    container_name: myblog
    # 开放端口
    ports:
      - "9090:9090"
    # 配置容器连接的自定义网络,跟mysql、redis 属于同一个网络
    networks:
      - app_net
    # 容器启动时依赖于以下服务
    depends_on:
      - mysql
      - redis
  # mysql服务
  mysql:
    image: mysql:5.7
    ports:
      - "13306:3306"
    volumes:
      - /mydocker/mysql/data:/var/lib/mysql
      - /mydocker/mysql/conf.d:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: 'root'
    networks:
      - app_net
  # redis 服务
  redis:
    image: redis:6.0
    ports:
      - "16379:6379"
    volumes:
      - /mydocker/redis/data:/data
      - /mydocker/redis/redis.conf:/usr/local/etc/redis/redis.conf
    networks:
      - app_net
    command: redis-server /usr/local/etc/redis/redis.conf
  # nginx 服务
  nginx:
    image: nginx:1.22
    volumes:
      - /mydocker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /mydocker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - /mydocker/nginx/html:/usr/share/nginx/html
      - /usr/local/app:/usr/local/app
    ports:
      - "80:80"
    networks:
      - app_net
networks:
  app_net:

上面将 mysql 的 3306端口映射到 13306,redis 的 6379 映射到 16379 的,就是因为端口映射,导致后面找了半天的 BUG…

application.yml

使用 docker-compose 的好处之一就是在项目的配置文件中,连接第三方服务的 ip 不用固定写死了,直接通过 docker 服务名来连接,这样即使以后容器更换了 ip,我们也无需再去改动项目配置了,nice。又是一顿 CV。

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://mysql/blog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC
    username: root
    password: root
  redis:
    host: redis
    port: 16379

上面 mysql 和 redis 的 host 地址不再使用固定ip了,这就很香。

部署

接下来的步骤就很简单了,CV大法编写 Dockerfile,打 jar包,上传服务器,build docker image,开放端口,最后通过 docker-compose up 一键启动,看日志:

up.png

nice!!启动成功,测一下 mysql 和 redis 的连接情况,通过 navicat 和 RedisDesktopManager 分别连接一下,发现世间最美的单词 successful,nice,激动的心,颤抖的手,眼看即将成功了,最后一步,访问项目:

jedisError.png

嗯?报错了,连不上端口 16379 的 redis 服务,小问题,不就是连接不上嘛,查配置呗。

排查

查 docker-compose.yml ,是不是配置错误了,容器卷挂错了,检查一通,没问题。

查 防火墙,16379端口也已开放,已重启,没问题。

查 redis.conf ,是不是配置有问题,但是 RedisDesktopManager 都连接成功了,没问题。

查 application.yml,是不是写的有问题,发现端口啥的用的也是映射后的端口,貌似也没问题。

查 docker network inspect,是不是redis没有连接到自定义网络,也没有问题。

network.png

什么情况,而且经过测试,项目连 mysql 可以,但唯独 redis 连接不上,嘿!奇了怪了。查百度,谷歌,也没有搜索相关的情况。

不要灰心,百度不到,问群友,毕竟加了那么多技术扯皮群,群里个个都是人才,说话又好听,超爱那里的。

把相关问题描述,问题截图往群里一扔,虽然是大半夜,但还是有群友给出了回复:

jedis的bug.png

因为项目里用的是 jedis 的连接池,所以我又把 jedis 改回来原来的 lettuce,重新打包构建启动,看日志,嘿,不管用:

logError.png

然后群友又回复了,会不会java启的时候,redis还没起来,但是 docker-compose.yml 中已经配置了 depends_on,所以这个情况应该也不存在。还是未能解决。

询问未果,最终还是在网上找到了一篇帖子,原来 在docker网络中运行所有内容 (redis、replica和spring) 时,应该使用端口6379而不是映射端口

reply.png

隧将项目的 application.yml中 redis 的端口,从 16379 改回原 6379,再打包构建测试,nice,终于可以了。

总结

docker 内部容器通信时,应该使用默认端口。如果外部服务通信,需要使用映射的端口。

以上结论来自个人测试,如有问题,欢迎指出。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值