Docker-compose編排微服務順序啟動


一、概述

docker-compose可以方便組合多個 docker 容器服務, 但是, 當容器服務之間存在依賴關系時, docker-compose 並不能保證服務的啟動順序。docker-compose 中的 depends_on 配置是容器的啟動順序, 並不是容器中服務的啟動順序。本章將詳細敘述如何解決 docker-compose 順序啟動微服務的問題。
 

微服務清單

服務名 端口 服務說明 依賴服務 啟動優先級
eureka-service 8761 服務注冊與發現 --- 1
auth-service 8888 認證服務 eureka-service 2
user-service 8763 用戶服務 eureka-service 2
gateway-service 8081 網關服務 eureka-service 2
 
 
 
 



 
 
說明:eureka需要第一個啟動,其他微服務必須等待eureka啟動之后,才能啟動。否則無法注冊服務!

 

二、解決方案

針對這個問題,docker-compose官方給的建議是,通過wait-for-it.sh腳本來控制。

簡單來說,這個腳本就是探測某個依賴的服務的tcp端口是否開放,否則一直等待,直到端口探測成功,才會啟動后面的命令。

關於wait-for-it.sh的使用,請參考鏈接:

https://blog.csdn.net/wuzhong8809/article/details/82500722

 

環境說明

本文采用一台centos 7.6,通過docker-compose啟動java spring cloud

ip地址:192.168.128.130

 

但是我測試了一下,使用wait-for-it.sh探測eureka的8761端口。發現雖然端口探測成功了,但是並不代表eureka完全啟動好了。因此此時無法訪問eureka的頁面!

那么如何判斷eureka完全啟動好了呢?很簡單,只需要訪問eureka頁面,http狀態碼為200,就表示啟動好了。

curl -I -m 10 -o /dev/null -s -w %{http_code}  http://eureka-server:8761

 

那么問題來了,還是得需要自己寫檢查腳本才行。

check_eureka.sh

#!/bin/bash

while :
    do
        # 訪問eureka注冊中心,獲取http狀態碼
        CODE=`curl -I -m 10 -o /dev/null -s -w %{http_code}  http://kitedge-eureka-server:8761`
        # 判斷狀態碼為200
        if [[ $CODE -eq 200 ]]; then
            # 輸出綠色文字,並跳出循環
            echo -e "\033[42;34m kitedge-eureka-server is ok \033[0m"
            break
        else
            # 暫停1秒
            sleep 1
        fi
    done

# while結束時,也就是eureka啟動完成后,執行容器中的run.sh。
bash /run.sh

說明:訪問eureka注冊中心,獲取http狀態碼。當為200時,跳出循環,執行其他容器中的run.sh。

否則就一直循環,直到eureka頁面正常為止。

 

目錄結構

/opt/springcloud 目錄結構如下:

./
├── auth
│   ├── auth-server.jar
│   ├── dockerfile
│   ├── repositories
│   └── run.sh
├── check_eureka.sh
├── docker-compose.yml
├── eureka
│   ├── dockerfile
│   ├── eureka-server.jar
│   ├── repositories
│   └── run.sh
├── gateway
│   ├── dockerfile
│   ├── gateway-server.jar
│   ├── repositories
│   └── run.sh
└── user
    ├── dockerfile
    ├── repositories
    ├── run.sh
    └── user-service.jar

這里有4個微服務

 

docker-compose.yml

version: '3'
services:
  eureka-server:
    image: eureka-server:1
    container_name: eureka-server
    build: ./eureka
    volumes:
      - ./check_eureka.sh:/check_eureka.sh
      - /data/log/tomcat:/data/log/tomcat
      - /data/file:/data/file
    environment:
      - JVM=128m
    ports:
      - "8761:8761"
    networks:
      test_net:
        aliases:
          - eureka-server
    restart: always
    command: ["bash","/check_eureka.sh"]
    healthcheck:
      test: "/bin/netstat -anpt|grep 8761"
      interval: 30s
      timeout: 3s
      retries: 1

  auth-server:
    image: auth-server:1
    container_name: auth-server
    build: ./auth
    volumes:
      - ./check_eureka.sh:/check_eureka.sh
      - /data/log/tomcat:/data/log/tomcat
      - /data/file:/data/file
    environment:
      - JVM=128m
    ports:
      - "8888:8888"
    networks:
      test_net:
        aliases:
          - auth-server
    restart: always
    depends_on:
      - "eureka-server"
    command: ["bash","/check_eureka.sh"]
    healthcheck:
      test: "/bin/netstat -anpt|grep 8888"
      interval: 30s
      timeout: 3s
      retries: 1

  user-service:
    image: user-service:1
    container_name: user-service
    build: ./user
    volumes:
      - ./check_eureka.sh:/check_eureka.sh
      - /data/log/tomcat:/data/log/tomcat
      - /data/file:/data/file
    environment:
      - JVM=128m
    ports:
      - "8763:8763"
    networks:
      test_net:
        aliases:
          - user-service
    restart: always
    depends_on:
      - "eureka-server"
    command: ["bash","/check_eureka.sh"]
    healthcheck:
      test: "/bin/netstat -anpt|grep 8763"
      interval: 30s
      timeout: 3s
      retries: 1

  gateway-server:
    image: gateway-server:1
    container_name: gateway-server
    build: ./gateway
    volumes:
      - ./check_eureka.sh:/check_eureka.sh
      - /data/log/tomcat:/data/log/tomcat
      - /data/file:/data/file
    environment:
      - JVM=128m
    ports:
      - "8081:8081"
    networks:
      test_net:
        aliases:
          - gateway-server
    restart: always
    depends_on:
      - "eureka-server"
    command: ["bash","/check_eureka.sh"]
    healthcheck:
      test: "/bin/netstat -anpt|grep 8081"
      interval: 30s
      timeout: 3s
      retries: 1

networks:
    test_net:
      external: true

參數解釋:

image:指定服務的鏡像名稱或鏡像ID。如果鏡像在本地不存在,Compose將會嘗試拉取鏡像。

container_name:容器名稱,相當於docker run --name xxx,里面的--name參數。

build:指定Dockerfile所在文件夾的路徑。Compose將會利用Dockerfile自動構建鏡像,然后使用鏡像啟動服務容器。

volumes:掛載一個目錄或者一個已存在的數據卷容器,相當於docker run -v xxx:xxx里面的-v參數。

environment:環境變量,相當於docker run -e xxx=xxx里面的-e參數。

ports:映射端口,相當於docker run -p xx:xx里面的-p參數。

networks:網絡設置,這里表示連接test_net網橋,aliases表示設置別名。相當於docker run -it --network xx --network-alias xxx

restart:重啟方式,相當於docker run --restart里面的--restart參數。

depends_on:指定依賴於哪個服務

command:覆蓋容器啟動后默認執行的命令,相當於docker run xxx /bin/bash里面最后一段命令。

healthcheck: 判斷容器的狀態是否正常
設置選項:

  • test:測試命令
  • --interval=DURATION (default: 30s),間隔
  • --timeout=DURATION (default: 30s), 超時時間
  • --start-period=DURATION (default: 0s),初始化時間
  • --retries=N (default: 3),當連續失敗指定次數后,容器狀態會變成unhealthy

 

 這里主要介紹eureka目錄下的幾個文件。

dockerfile

FROM mayan31370/openjdk-alpine-with-chinese-timezone:8-jdk
ADD eureka-server.jar /
ADD run.sh /
RUN chmod 755 run.sh && mkdir -p /data/log/tomcat /data/file

EXPOSE 8761
ENTRYPOINT [ "/run.sh"]

 

repositories

#https://mirrors.aliyun.com/alpine/v3.6/main/
#https://mirrors.aliyun.com/alpine/v3.6/community/
#aliyun
https://mirrors.aliyun.com/alpine/v3.6/main/
https://mirrors.aliyun.com/alpine/v3.6/community/

 

run.sh

#!/bin/sh

java -Xms${JVM} -Xmx${JVM} -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=256m -jar /eureka-server.jar

 

再來看auth下的幾個文件。

dockerfile

FROM mayan31370/openjdk-alpine-with-chinese-timezone:8-jdk
ADD auth-server.jar /
ADD repositories /etc/apk/repositories
ADD run.sh /
RUN chmod 755 run.sh && mkdir -p /data/log/tomcat /data/file && apk update && apk add bash curl

EXPOSE 8888
#ENTRYPOINT [ "/run.sh"]

注意:這里注釋掉了ENTRYPOINT ,因為它由check_eureka.sh腳本來啟動。注意看此腳本的最后一行,它就是來執行run.sh的。

 

repositories

內容同上,這里就不重復貼了

 

run.sh

#!/bin/sh

java -Xms${JVM} -Xmx${JVM} -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=256m -jar /auth-server.jar

 

另外2個微服務,user和gateway。和auth也是類似的,只不過dockerfile和run.sh里面的jar包名不一樣,其他內容都是一樣的。

 

啟動服務

創建bridge網絡

docker network create test_net

 

一切准備就緒了,先build,再啟動。

cd /opt/springcloud
docker-compose build
docker-compose up -d

 

等待幾分鍾,查看容器狀態

# docker-compose ps
     Name                   Command                 State               Ports         
--------------------------------------------------------------------------------------
auth-server      bash /check_eureka.sh           Up (healthy)   0.0.0.0:8888->8888/tcp
eureka-server    /run.sh bash /check_eureka.sh   Up (healthy)   0.0.0.0:8761->8761/tcp
gateway-server   bash /check_eureka.sh           Up (healthy)   0.0.0.0:8081->8081/tcp
user-service     bash /check_eureka.sh           Up (healthy)   0.0.0.0:8763->8763/tcp

 

訪問eureka注冊中心
 
效果如下:

 

 

 
 

本文參考連接:

https://blog.csdn.net/wuzhong8809/article/details/82500722

https://www.jianshu.com/p/d2f39703bcb5


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM