SpringCloud通过docker-compose部署服务器


文章目录

  • SpringCloud通过docker-compose部署服务器
  • 〇、阅读条件
  • 一、概述
  • 二、部署流程
  • 1、环境(博主部署环境)
  • 2、前置条件
  • 3、详细过程
  • 3.0、打包模块
  • 3.1、dockerfile编写
  • 3.2、编写docker-compose.yml(如已有镜像,请跳转到3.5)
  • 3.3、构建镜像
  • 3.4、将镜像上传值服务器(若无需上传镜像服务器,跳转至3.7,更多配置参考3.5)
  • 3.5 、编写docker-compose.yml(通过拉取镜像方式)
  • 3.6、构建容器并运行
  • 3.7 编写更多模块
  • 三、问题
  • 1、应用注册到eureka地址错误
  • 2、springboot读取不到配置文件
  • 四、总结
  • 五、参考资料


〇、阅读条件

  • 阅读本文需要具备以下知识:
  • springcloud
  • linux基础
  • docker

一、概述

  • 随着用户数量的增长,一台服务器往往难以承受巨大的流量,同时,服务的日趋复杂也需要多台服务器分别运行来提高可用性。微服务技术的使用越来越成为当前的主流。
  • 一个应用的部署往往需要和系统环境、硬件环境等匹配,而docker的使用则使这个过程更轻松、更安全、更简单。
  • docker-compose则可以方便的创建、管理docker镜像和容器。
  • 难点:
  • 在部署过程中将遇到很多细节问题,如网络互通、配置等,均导致部署失败,后续将提及。

二、部署流程

1、环境(博主部署环境)

  • 操作系统:centos7.6
  • Docker 20.10.5
  • Docker-compose 1.28.6

2、前置条件

  • springCloud服务本地测试无误
  • 服务器对应端口正常访问,服务器间可正常通讯(可内网,本文为公网案例)


3、详细过程

docker 与spring docker与springcloud的整合_docker 与spring

3.0、打包模块

  • 将springboot模块打包为jar包,若需要读取jar包相对路径的配置文件,可在后续编写docker-compose注意(会提到)
  • 编写springboot配置文件(非必须)
server:
  port: ${SERVICE_PORT:8001}

spring:
  application:
    name: microUserService	# 服务名称,feign访问的依据
  cloud:	
    sentinel:	# sentinel配置
      transport:
        dashboard: ${SENTINEL_URL:localhost}:${SENTINEL_PORT:8888}
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://${DB_URL:localhost}:${DB_PORT:3306}/${DB_NAME:db}?serverTimeZone=UTC&allowMultiQueries=true
    username: ${DB_USER:root}
    password: ${DB_PASSWORD:root}
  redis:
    host: ${REDIS_HOST:localhost}
    port: ${REDIS_PORT:6379}
    password: ${REDIS_PASSWORD}


## mybatis 配置
mybatis:
  mapper-locations: classpath:**/mapper/*.xml
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


## eureka 配置
eureka:
  client:
    service-url:
      defaultZone: ${EUREKA_URL:localhost}:${EUREKA_PORT:7001}/eureka/
  instance:
    ip-address: ${HOSTNAME:localhost} # 很重要,配置了这个,使用eureka注册会使用改地址,否则会注册172.xxx.xxx.xxx(容器地址),外部无法访问(学习、测试可写死)
    instance-id: ${HOSTNAME:localhost}:microUserService:${service.port} #自定义服务名称信息
    hostname: ${HOSTNAME:localhost}	
    prefer-ip-address: true  #显示访问路径的 ip 地址

3.1、dockerfile编写

为每个模块编写对应的Dockerfile

  • 容器需要依赖对应版本的java容器
  • 需要复制 xxx.jar 文件到容器内路径
  • 暴露端口
  • 设置启动指令
  • 文件相对路径如下,其中config为外部配置的放置位置,也可以和user-service.jar同级。

docker 与spring docker与springcloud的整合_spring cloud_02

具体样例如下

# [Dockerfile]

FROM java:8-alpine	# java 1.8版本的容器,其他版本请自行搜索

COPY ./user-service.jar /tmp/app.jar # 将user-service.jar文件复制到容器内的/tmp目录下,并重命名为 app.jar

EXPOSE 8001	# 暴露端口(自行决定,需要和应用的运行端口一致)

ENTRYPOINT cd /tmp && java -jar /tmp/app.jar # 配置启动命令,其中 cd /tmp 是为了启动时能够读取jar包外的配置文件(配置文件路径自行百度),若使用配置中心,可后续直接使用配置中心管理配置

3.2、编写docker-compose.yml(如已有镜像,请跳转到3.5)

  • 自定义名称
  • 配置构建的相对路径
  • 挂载文件映射
  • 开放权限(较新的docker版本才需要)
  • 配置环境变量(建议将springboot 的配置写为环境变量的形式)
  • 相对路径如下,其中user-service内结构如3.1

docker 与spring docker与springcloud的整合_docker_03

具体如下

# [docker-compose.yml]

version: "3.2" 

services:
  user-service:	# 名字随便取
    build: ./user-service  # 构造路径(Dockerfile在的路径)
    volumes: # 挂载文件映射
      - "./user/config:/tmp/config" # 配置文件映射,即3.1中的config,也可以直接挂载配置文件,./user/config/application-prod.yml:/tmp/config/application-prod.yml
      - "./user/logs:/tmp/logs" # 日志路径自行定义,前者为服务器路径,后者为容器内路径
    ports:	# 服务器-容器端口映射
      - "8001:8001"	
    privileged: true	# 开放权限,在较新版本docker才需要

3.3、构建镜像

  • 将文件上传至服务器
  • 进入到 docker-compose.yml所在路径
  • 执行指令
docker-compose up --build # 构建镜像 并运行该镜像的容器
  • 测试镜像是否正常运行

3.4、将镜像上传值服务器(若无需上传镜像服务器,跳转至3.7,更多配置参考3.5)

将镜像上传值 容器镜像服务器 ,方便其他服务器获取镜像。

博主使用的是腾讯云,若每次都本地上传,速度很慢(大约1MB/s),但是如果从腾讯云的镜像服务器下载,则是飞一般的体验!!!(具体服务器搭建可去腾讯云搜索 容器镜像服务 ,申请个人版(免费))

  • 输入 docker images查看镜像信息
  • 重命名该镜像为 服务器+命名空间+镜像仓库:版本 的格式
  • 例如服务器名为 ccr.xxx.tencentyun.com
  • 命名空间为 mmkj
  • 镜像仓库为 app_user-service
  • 版本为 latest
  • 指令为:
docker tag app_user-service ccr.xxx.tencentyun.com/mmkj/app_user-service:latest
  • 输入docker images查看,发现多了一个
  • 将镜像推送置服务器
docker push app_user-service ccr.xxx.tencentyun.com/mmkj/app_user-service:latest

3.5 、编写docker-compose.yml(通过拉取镜像方式)

当镜像服务器上有了你的服务器,就可以编写docker-compose.yml直接拉取镜像构建容器了

# [docker-compose.yml]
version: "3.2"

services:
  user-service:	# 名字随便取
    image: ccr.xxx.tencentyun.com/mmkj/app_user-service # 镜像服务器容器地址
    volumes:	# 挂载文件
      - "./user-service/config:/tmp/config" # 配置文件
      - "./user-service/logs:/tmp/logs" # 日志文件
    ports:	# 端口映射
      - "8001:8001"
    privileged: true	# 给与权限
    environment:	# 环境变量(可以在application.yml中自行配置,非必须)
      - SERVICE_PORT=8001	# 服务端口
      - SENTINEL_URL=xxx.xxx.xxx.xxx	# sentinel路由
      - SENTINEL_PORT=8888	# sentinel 端口
      - DB_URL=xxx.xxx.xxx.xxx	# 数据库相关配置
      - DB_PORT=3306
      - DB_NAME=dbname
      - DB_USER=root
      - DB_PASSWORD=root
      - HOSTNAME=xxx.xxx.xxx.xxx	# 主机地址,强烈建议配置该部分,否则可能导致服务注册至eureka时,使用容器网路的地址(外部无法访问)

3.6、构建容器并运行

同3.3

3.7 编写更多模块

编写更多dockerfile和docker-compose 即可完成服务部署

可通过docker logs -f 容器id docker-compose logs -f 运行查看日志

附mysql和redis的compose 部署文件

version: "3.2"

services:
  redis:
    image: redis
    container_name: docker_redis
    volumes:
      - ./redis/datadir:/data
      - ./redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./redis/logs:/logs
    command:
      #      两个写入操作 只是为了解决启动后警告 可以去掉
      /bin/bash -c "echo 511 > /proc/sys/net/core/somaxconn
      && echo never > /sys/kernel/mm/transparent_hugepage/enabled
      && redis-server /usr/local/etc/redis/redis.conf"	# 如需自定义配置文件,请自行百度
    ports:
      - "6379:6379"
    privileged: true
  mysql:
    image: mysql:5.7.37
    environment:
      MYSQL_ROOT_PASSWORD: 'root'	# 数据库密码
    ports:
      - "3306:3306"
    volumes:
      - "./mysql/mysql-5.7.37/data:/var/lib/mysql"
      - "./mysql/mysql-5.7.37/mysql/conf:/etc/mysql/conf.d"
    privileged: true

三、问题

1、应用注册到eureka地址错误

  • Q:浏览器能访问到服务,eureka上注册服务正常,但是其他微服务无法访问到该微服务
  • A:考虑在配置文件中配置 ip-address 字段,详见上文3.0中的配置文件
## eureka 配置
eureka:
  client:
    service-url:
      defaultZone: ${EUREKA_URL:localhost}:${EUREKA_PORT:7001}/eureka/
  instance:
    ip-address: ${HOSTNAME:localhost} # 很重要,配置了这个,使用eureka注册会使用改地址,否则会注册172.xxx.xxx.xxx(容器地址),外部无法访问(学习、测试可写死)
    instance-id: ${HOSTNAME:localhost}:microUserService:${service.port} #自定义服务名称信息
    hostname: ${HOSTNAME:localhost}	
    prefer-ip-address: true  #显示访问路径的 ip 地址

2、springboot读取不到配置文件

  • Q:配置文件与jar包 同级同级的config 文件夹下,但是不生效
  • A:有多种可能
  • 需要在jar包同级执行shell指令才能读取到配置文件,故dockerfile编写时需加入 ENTRYPOINT cd /tmp && java -jar /tmp/app.jar
  • 容器没有权限读写配置文件,创建容器时加入 privileged: true即可(可用docker exec -it 容器名 /bin/sh进入容器尝试启动进行测试)

四、总结

  • 通过使用 docker 能够很容易的搭建 大量 服务,或许单个服务部署比较麻烦,但当服务有10个甚至100、1000个时,docker的使用将大大减少服务的部署、维护和移植成本。
  • 通过环境变量的方式编写配置文件将大大降低镜像的耦合度,提高可用性,多个服务器部署只需要修改docker-compose即可,当然使用 配置中心 也是主流的方式,这里不做阐述。
  • 通过docker-compose部署主要步骤为:
  • 编写配置文件
  • 创建镜像
  • 测试运行

五、参考资料