基于docker的微服務容器化與編排

準備

在本人的微服務系列中俱济,已經演示了各個spring cloud微服務組件的使用,以及相關的示例微服務應用。在每次啟動微服務和對微服務進行擴容饱搏、縮容都不方便,本文使用docker-compose將以下的微服務容器化置逻,并進行自動化部署推沸。

相關代碼請參考:springcloud-demo
各服務治理組件的介紹,請參考我的微服務系列文章券坞。

1.微服務治理組件列表

名稱 描述 內部端口 暴露端口 是否部署集群
discovery 基于Eureka Server的服務注冊中心 8761/8762 8761/8762
configserver 基于cloud config的配置中心 8089 8089
gateway 基于zuul的API網關 8086 8086
track 基于seluth+zipkin的服務跟蹤 9411 9411
hystrix-dashboard 基于hystrix-dashboard的服務監(jiān)控 8087 8087
hystrix-turbine-mq 基于turbine+rabbitmq的服務監(jiān)控數據收集 8089 8089

2.微服務示例列表

名稱 描述 內部端口 暴露端口 是否部署集群
hello 服務提供者鬓催,依賴mysql數據庫 8000 自動
world 服務提供者 8010 自動
helloworld 服務消費者,使用restTemplate+ribbon調用 8020 自動
helloworld-feign 服務消費者恨锚,使用feign方式調用 8030 自動

3.環(huán)境與工具

  • 環(huán)境 linux (ubuntu 16)
  • 工具 docker+gitlab+rabbitmq+docker registry+intellij idea+maven

操作步驟

本文編寫兩個docker-compose.yml文件宇驾,將服務治理和服務示例分開,主要是因為服務示例依賴了服務治理猴伶,部分示例必須要等待服務治理組件加載完畢才能正常啟動课舍,比如hello項目使用了配置中心config server的配置,config server未加載完畢他挎,hello項目啟動異常筝尾。

雖然depends_onlinks等具有啟動順序的問題办桨,但解決不了啟動是否 ready的問題筹淫,關于這個問題,可以參考我的文章:docker-compose 啟動順序

1. 編寫 Dockerfile

在每個項目的根目錄中呢撞,編寫Dockerfile,文件內容為

FROM java:8-jre-alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories
VOLUME /tmp
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
RUN echo $(date) > /image_built_at
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=${SPRING_PROFILES_ACTIVE}"]

其中SPRING_PROFILES_ACTIVE為后面docker-compose.yml傳入的環(huán)境變量损姜,指定項目以使用哪段配置啟動。

2. 在原有的配置文件application.yml增加spring.profiles:docker的配置

主要是使用docker后殊霞,服務依賴的其他服務的連接發(fā)生改變摧阅,通過配置環(huán)境變量來動態(tài)接收docker-compose的配置參數。

  • track增加的spring.profiles:docker配置
---
spring:
  profiles: docker
server:
  port: ${{SERVER_PORT}:9411}
eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_SERVER_LIST}
  • hello 增加的spring.profiles:docker配置
---
spring:
  profiles: docker
  datasource:
    url: jdbc:mysql://mysql:3306/${{MYSQL_DATABASE}:hello}
    username: ${{MYSQL_USERNAME}:user}
    password: ${{MYSQL_PASSWORD}:passworld}
    testWhileIdle: true
    validationQuery: SELECT 1
  jpa:
    show-sql: false
    hibernate:
      ddl-auto: update
      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
      properties:
        hibernate:
          dialect: org.hibernate.dialect.MySQL5Dialect
  zipkin:
    base-url: http://track:9411

eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_SERVER_LIST}

${{MYSQL_USERNAME}:user} 是指配置文件在啟動的時候如果沒有讀取到環(huán)境變量MYSQL_USERNAME的值脓鹃,則使用默認值user逸尖。這種配置在開發(fā)的時候十分有用,比如切換開發(fā)、測試娇跟、生產環(huán)境配置岩齿。

3. 編寫批量編譯的shell腳本images-build.sh

該腳本將進入到各個項目中,使用maven對項目進行打包苞俘,然后使用docker盹沈,根據Dockerfile對項目進行構建,生成分別帶有:lastest 和當前日期標簽的兩個鏡像吃谣。

#!/bin/bash

# 編譯所有的代碼乞封,生成docker 鏡像
function progress(){
    local GREEN CLEAN
    GREEN='\033[0;32m'
    CLEAN='\033[0m'
    printf "\n${GREEN}$@  ${CLEAN}\n" >&2
}

set -e

# 鏡像倉庫前綴
REGPREFIX=127.0.0.1:5000/billjiang
TOTAL=10

#discovery server
progress "Building discovery-server(1/${TOTAL}) jar file ..."
cd common/discovery
mvn clean package -DskipTests
progress "Building discovery(eureka server)(1/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/discovery -q .) ${REGPREFIX}/discovery:$(date -u "+%Y%m%d-%H%M%S")
cd -

#config server
progress "Building config-server(2/${TOTAL}) jar file ..."
cd common/configserver
mvn clean package -DskipTests
progress "Building config server(2/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/configserver -q .) ${REGPREFIX}/configserver:$(date -u "+%Y%m%d-%H%M%S")
cd -

#gateway
progress "Building gateway-zuul(3/${TOTAL}) jar file ..."
cd common/gateway
mvn clean package -DskipTests
progress "Building gateway-zuul(3/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/gateway -q .) ${REGPREFIX}/gateway:$(date -u "+%Y%m%d-%H%M%S")
cd -

#track sleuth+zipkin
progress "Building track(sleuth+zipkin)(4/${TOTAL}) jar file ..."
cd common/track
mvn clean package -DskipTests
progress "Building track by sleuth+zipkin(4/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/track -q .) ${REGPREFIX}/track:$(date -u "+%Y%m%d-%H%M%S")
cd -

#hystrix-dashboard
progress "Building hystrix-dashboard(5/${TOTAL}) jar file ..."
cd common/hystrix-dashboard
mvn clean package -DskipTests
progress "Building hystrix-dashboard(5/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/hystrix-dashboard -q .) ${REGPREFIX}/hystrix-dashboard:$(date -u "+%Y%m%d-%H%M%S")
cd -

#hystrix-turbine-mq
progress "Buildinhg hystrix-turbine-mq(6/${TOTAL}) jar file ..."
cd common/hystrix-turbine-mq
mvn clean package -DskipTests
progress "Building hystrix-turbine-mq(6/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/hystrix-turbine-mq -q .) ${REGPREFIX}/hystrix-turbine-mq:$(date -u "+%Y%m%d-%H%M%S")
cd -

#hello
progress "Buildinhg hello service(7/${TOTAL}) jar file ..."
cd service/hello
mvn clean package -DskipTests
progress "Building hello service(7/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/hello -q .) ${REGPREFIX}/hello:$(date -u "+%Y%m%d-%H%M%S")
cd -


#world
progress "Buildinhg world service(8/${TOTAL}) jar file ..."
cd service/world
mvn clean package -DskipTests
progress "Building world service(8/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/world -q .) ${REGPREFIX}/world:$(date -u "+%Y%m%d-%H%M%S")
cd -

#helloworld
progress "Buildinhg helloworld service(9/${TOTAL}) jar file ..."
cd service/helloworld
mvn clean package -DskipTests
progress "Building helloworld service(9/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/helloworld -q .) ${REGPREFIX}/helloworld:$(date -u "+%Y%m%d-%H%M%S")
cd -

#helloworld-feign
progress "Buildinhg helloworld-feign service(10/${TOTAL}) jar file ..."
cd service/helloworld-feign
mvn clean package -DskipTests
progress "Building helloworld-feign service(10/${TOTAL}) docker image ..."
docker tag $(docker build -t ${REGPREFIX}/helloworld-feign -q .) ${REGPREFIX}/helloworld-feign:$(date -u "+%Y%m%d-%H%M%S")
cd -

4. 進入到項目目錄springcloud-demo,執(zhí)行bash images-build.sh進行批量編譯打包

批量編譯打包springcloud-demo.png

5. 創(chuàng)建服務治理組件的docker-compose.yml岗憋,編寫如下內容

version: "2"
services:

  #啟動注冊中心eureka-server集群 集中管理/服務注冊/服務發(fā)現(xiàn)
  discovery1:
    container_name: discovery1
    image: 127.0.0.1:5000/billjiang/discovery
    ports:
      - "8761:8761"
    environment:
      - ADDITIONAL_EUREKA_SERVER_LIST=http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8761

  discovery2:
    container_name: discovery2
    image: 127.0.0.1:5000/billjiang/discovery
    ports:
      - "8762:8762"
    environment:
      - ADDITIONAL_EUREKA_SERVER_LIST=http://discovery1:8761/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8762
    links:
      - discovery1

  #啟動配置中心config-server集群 配置更新/配置集中管理/多環(huán)境配置
  config1:
    container_name: configserver1
    image: 127.0.0.1:5000/billjiang/configserver
    ports:
      - "8090:8090"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8090
    links:
      - discovery1
      - discovery2

  config2:
    container_name: configserver2
    image: 127.0.0.1:5000/billjiang/configserver
    ports:
      - "8091:8091"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8091
    links:
      - discovery1
      - discovery2

  #啟動網關gateway,可配置成集群,使用nginx進行負載 智能路由/安全控制/負載均衡
  gateway:
    container_name: gateway
    image: 127.0.0.1:5000/billjiang/gateway
    ports:
      - "8086:8086"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8086
    links:
      - discovery1
      - discovery2


  # 啟動seluth+zipkin zipkin服務跟蹤/依賴可視化
  track:
    container_name: track
    image: 127.0.0.1:5000/billjiang/track
    ports:
      - "9411:9411"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=9411
    links:
      - discovery1
      - discovery2


   # hystrix
  # 啟動hystrix-dashboard
  hystrix-dashboard:
    container_name: hystrix-dashboard
    image: 127.0.0.1:5000/billjiang/hystrix-dashboard
    ports:
      - "8087:8087"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8087
    links:
      - discovery1
      - discovery2

  # 啟動hystrix-turbine-mq  基于消息中間件的實時性能數據收集
  hystrix-turbine-mq:
    container_name: hystrix-turbine-mq
    image: 127.0.0.1:5000/billjiang/hystrix-turbine-mq
    ports:
      - "8089:8089"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8089
    links:
      - discovery1
      - discovery2

  mysql:
    container_name: mysql
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=passw0rd
      - MYSQL_DATABASE=foodb
      - MYSQL_USER=user1
      - MYSQL_PASSWORD=passw0rd


6. 在service目錄下肃晚,創(chuàng)建服務示例的docker-compose.yml,編寫如下內容

version: "2"
services:



  # 啟動 hello
  hello:
    image: 127.0.0.1:5000/billjiang/hello
    ports:
      - "8000"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - MYSQL_DATABASE=foodb
      - MYSQL_USERNAME=user1
      - MYSQL_PASSWORD=passw0rd
    external_links:
      - mysql
      - config1
      - config2
      - gateway
      - track

  # 啟動 world
  world:
    image: 127.0.0.1:5000/billjiang/world
    ports:
      - "8010"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT:8010
    external_links:
      - config1
      - config2
      - gateway
      - track

  # 啟動 helloworld
  helloworld:
    image: 127.0.0.1:5000/billjiang/helloworld
    ports:
      - "8020"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT:8020
    external_links:
      - config1
      - config2
      - gateway
      - track
    links:
      - hello
      - world
  # 啟動 hello
  helloworld-feign:
    image: 127.0.0.1:5000/billjiang/helloworld-feign
    ports:
      - "8030"
    environment:
      - EUREKA_SERVER_LIST=http://discovery1:8761/eureka/,http://discovery2:8762/eureka/
      - SPRING_PROFILES_ACTIVE=docker
      - SERVER_PORT=8030
    external_links:
      - config1
      - config2
      - gateway
      - track
    links:
      - hello
      - world

# 其他服務 ..........................
networks:
  default:
    external:
      name: springclouddemo_default

因為docker-compose啟動的時候默認會創(chuàng)建一個springclouddemo_default的網絡仔戈,兩個網絡要通信关串,所以服務示例指定使用springclouddemo_default,這樣組件之間客戶互相通信了监徘。

6. 啟動服務治理的docker-compose.yml

springcloud-demo根目錄下晋修,使用docker-compose up啟動服務編排,如下界面所示:

服務治理服務編排啟動1.png

服務治理服務編排啟動2.png

啟動后凰盔,打開注冊中心地址墓卦,查看已經啟動的服務:


已經啟動的服務列表.png

7. 連接外部docker容器

配置中心使用到了gitlab, 服務跟蹤track使用了rabbitmq,這兩個容器都不在docker-compose之中户敬,要使得能夠互相連通落剪,要把這兩個容器也加入到springclouddemo_default網絡。

docker network connect springclouddemo_default gitlab
docker network connect springclouddemo_default rabbitmq

使用docker network inspect springclouddemo_default可以查看到已經加入網絡的容器山叮。

8. 啟動服務示例編排docker-compose.yml

進入到service目錄著榴,使用docker-compose up啟動服務示例編排,如下所示:

服務示例編排1.png

服務示例編排2

9. 在Eureka Server查看新增的服務

新增注冊服務.png

10. 可以使用如下命令對服務進行擴容

scale擴容.png

刷新Eureka Server屁倔,可以看到服務已經擴展到三個節(jié)點。

擴容后.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末暮胧,一起剝皮案震驚了整個濱河市锐借,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌往衷,老刑警劉巖钞翔,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異席舍,居然都是意外死亡布轿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汰扭,“玉大人稠肘,你說我怎么就攤上這事÷苊” “怎么了项阴?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笆包。 經常有香客問我环揽,道長,這世上最難降的妖魔是什么庵佣? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任歉胶,我火速辦了婚禮,結果婚禮上巴粪,老公的妹妹穿的比我還像新娘跨扮。我一直安慰自己,他們只是感情好验毡,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布衡创。 她就那樣靜靜地躺著,像睡著了一般晶通。 火紅的嫁衣襯著肌膚如雪璃氢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天狮辽,我揣著相機與錄音一也,去河邊找鬼。 笑死喉脖,一個胖子當著我的面吹牛椰苟,可吹牛的內容都是我干的。 我是一名探鬼主播树叽,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舆蝴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了题诵?” 一聲冷哼從身側響起洁仗,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎性锭,沒想到半個月后赠潦,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡草冈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年她奥,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓮增。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡哩俭,死狀恐怖绷跑,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情携茂,我是刑警寧澤你踩,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站讳苦,受9級特大地震影響带膜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜鸳谜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一膝藕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咐扭,春花似錦芭挽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至薛闪,卻和暖如春辛馆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豁延。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工昙篙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诱咏。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓苔可,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袋狞。 傳聞我的和親對象是個殘疾皇子焚辅,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容