1. 程式人生 > >Docker Compose編排微服務

Docker Compose編排微服務

在前面的文章Docker部署Spring Boot中,使用maven構建映象,然後使用docker命令操作容器。微服務架構的應用系統中一般包含若干個微服務,每個微服務一般都會部署多個例項,如果每個微服務都要手動啟停,維護的工作量會很大。Docker Compose可以輕鬆的管理容器,降低維護工作量。

一、Docker Compose簡介

Docker Compose是一個編排多容器分散式部署的工具,提供命令集管理容器化應用的完整開發週期,包括服務構建,啟動和停止。官網地址
Compose 中有兩個重要的概念:

  • 服務 ( service ):一個應用的容器,實際上可以包括若干執行相同映象的容器例項
  • 專案 ( project ):由一組關聯的應用容器組成的一個完整業務單元,在 dockercompose.yml 檔案中定義。
    Compose 的預設管理物件是專案,通過子命令對專案中的一組容器進行便捷地生命週期管理。可見,一個專案可以由多個服務(容器)關聯而成, Compose 面向專案進行管理

Compose 專案由 Python 編寫,實現上呼叫了 Docker 服務提供的 API 來對容器進行管理。因此,只要所操作的平臺支援 Docker API,就可以在其上利用 Compose 來進行編排管理。

二、CentOS 7 安裝docker compose

Compose有很多種安裝方式,例如通過Shell、pip以及將Compose作為容器安裝等。本文通過pip來安裝Compose,其它安裝方式可以參照

官方文件

1. 檢查linux有沒有安裝python-pip包
pip -V
2. 沒有安裝python-pip執行下面命令
yum -y install epel-release
3. 執行成功之後,再次執行下面的命令
yum -y install python-pip
4. 對安裝好的pip進行升級
pip install --upgrade pip
5. 安裝docker compose
pip install docker-compose
6. 檢查安裝的docker compose版本
docker-compose
-version
7. 安裝compose命令補全工具
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose

這樣重新登陸之後,輸入docker-compose並按下tab鍵,Compose就可以自動補全命令。

三、docker compose入門

3.1 基本步驟

  1. 在 Dockfile 中定義你的應用環境,使其可以在任何地方重現該環境。
  2. docker-compose.yml 中定義組成應用程式的服務,以便它們可以在隔離的環境中一起執行。
  3. 執行dcoker-compose up,Compose 將啟動並執行整個應用程式。

3.2 工程、服務、容器

Docker Compose將所管理的容器分為三層,分別是工程(project)、服務(service)、容器(container)。Docker Compose執行目錄下的所有檔案(docker-compose.yml、extends檔案或環境變數檔案)組成一個工程(預設為docker-compose.yml所在目錄的目錄名稱)。一個工程可包含多個服務,每個服務中定義了容器執行的映象、引數、依賴,一個服務科包括多個容器例項

3.3 docker-compose.yml常用命令

  1. build

    配置構建時的選項,Compose會利用它自動構建映象。build的值可以是一個路徑,例如:

    build: ./dir

    也可以是一個物件,用於指定Dockerfile和引數,例如:

    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
  2. command

    覆蓋容器啟動後預設執行命令:

    command: bundle exec thin -p 3000

    也可以是一個list,類似於Dockerfile中的CMD指令,格式如下:

    command: ["bundle", "exec", "thin", "-p", "3000"]
  3. dns

    配置DNS伺服器。可以是一個值,也可以是一個列表。例如:

    dns: 8.8.8.8
    dns:
      - 8.8.8.8
      - 9.9.9.9
  4. dns_search

    配置DNS搜尋域,可以是一個值,也可以是一個列表。例如:

    dns_search: example.com
    dns_search:
      - dc1.example.com
      - dc2.example.com
  5. environment

    環境變數設定,可使用陣列或字典兩種方式,例如:

    environment:
      RACK_ENV: development
      SHOW: 'true'
      SESSION_SECRET:
    
    environment:
      - RACK_ENV=development
      - SHOW=true
      - SESSION_SECRET
  6. env_file

    從檔案中獲取環境變數,可指定一個檔案路徑或路徑列表。如果通過docker-compose -f FiLE指定了Compose檔案,那麼env_file中的路徑是Compose檔案所在目錄的相對路徑。使用environment指定的環境變數會覆蓋env_file指定的環境變數。例如:

    env_file: .env
    
    env_file:
      - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
  7. expose

    暴露埠,只將埠暴露給連線的服務,而不暴露給宿主機。例如:

    expose:
    - "3000"
    - "8000"
  8. external_links

    連線到docker-compose.yml外部的容器,甚至並非Compose管理的容器,特別是提供共享或公共服務的容器。格式跟links類似,例如:

    external_links:
    - redis_1
    - project_db_1:mysql
    - project_db_1:postgresql
  9. image

    指定映象名稱或映象ID,如果本地不存在該映象,Compose會嘗試下載該映象。例如:

    image: java
  10. links

    連線到其他服務容器。可以指定服務名稱和服務列表(SERVICE:ALIAS),也可只指定服務名稱。例如:

    web:
      links:
       - "db"
       - "db:database"
       - "redis"
  11. network_mode

    設定網路模式,例如:

    network_mode: "bridge"
    network_mode: "host"
    network_mode: "none"
    network_mode: "service:[service name]"
    network_mode: "container:[container name/id]"
  12. ports

    暴露埠資訊,可使用HOST:CONTAINER的格式,也可只指定容器埠(此時縮主機將會隨機選擇埠),類似於docker run -p
    需要注意的是,當使用HOST:CONTAINER格式對映埠時,容器埠小於60將會得到錯誤的介面。因此,建議使用字串的形式,例如:

    ports:
        - "3000"
        - "3000-3005"
        - "8000:8000"
        - "9090-9091:8080-8081"
        - "49100:22"
        - "127.0.0.1:8001:8001"
        - "127.0.0.1:5000-5010:5000-5010"
        - "6060:6060/udp"
        - "12400-12500:1240"
  13. volumes

    卷掛載路徑設定。可以設定宿主機路徑(HOST:CONTAINER),也可指定訪問模式(HOST:CONTAINER:ro),例如:

    volumes:
      # Just specify a path and let the Engine create a volume
      - /var/lib/mysql
    
      # Specify an absolute path mapping
      - /opt/data:/var/lib/mysql
    
      # Path on the host, relative to the Compose file
      - ./cache:/tmp/cache
    
      # User-relative path
      - ~/configs:/etc/configs/:ro
    
      # Named volume
      - datavolume:/var/lib/mysql
  14. volumes_from

    從另外一個服務或容器掛載卷。可指定只讀(ro)或讀寫(rw),預設是讀寫(rw),例如:

    
    volumes_from:
    - service_name
    - service_name:ro
    - container:container_name
    - container:container_name:r

四、docker-compose常用命令

下面討論docker-compose的常用命令。

1. build
構建或重新構建服務。服務被構建後將會以project_service的形式存在,例如:compo-setest_db
2. help
  檢視指定命令的文件
```cmd
docker-compose help COMMAND
```
3. kill
通過傳送SIGKILL訊號停止指定服務的容器。示例:
```cmd
docker-compose kill eureka
```
4. logs
檢視服務的日誌輸入
5. port
列印繫結的公共埠。示例:
```cmd
  docker-compose port eureka 8761
```
可輸出eureka服務8761埠所繫結的公共埠
6. ps
列出所有容器。示例:
```cmd
docker-compose ps
```  
7. pull
下載服務映象 
8. rm
  刪除指定服務的容器。示例:
```cmd
docker-compose rm eureka
```   
9. run
在一個服務上執行一個命令。示例:
```cmd
docker-composse run web bash
```
這樣可以啟動一個web服務,同時執行bash命令
10. scale
設定指定服務運例項的個數,以service=num的形式 指定。示例:
```cmd
docker-compose sscale user=3 movice=3
```  
11. start
啟動指定服務已存在的容器。示例 :
```cmd
docker-compose start eureka
```  
12. stop
停止已執行的容器。示例:
```cmd
docker-compose sstop eureka
```  
13. up
構建、建立、重新構建啟動連線服務相關的容器。所有連線的服務都會啟動,除非它們已執行。docker-compose up命令會聚合所有容器的輸出,當命令退出時,所有容器都會退出。使用docker-compose up -d可在後臺啟動並執行所有容器。

五、部署示例

本節使用docker compose部署spring cloud專案。

1. 服務概述

我們一共部署四個服務,如下所示:

服務 備註
eureka-server 1111,1112 服務註冊與發現中心(高可用部署)
demo 8102 服務1
feign-upload_first 8100 服務2
feign_upload_second 8101 服務
2. 各服務新增Docker構建外掛
 <!-- Docker maven plugin -->
          <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
              <imageName>simon/${project.artifactId}:${project.version}</imageName>
              <!--<dockerDirectory>src/main/docker</dockerDirectory>-->
              <forceTags>true</forceTags>
              <baseImage>java</baseImage>
              <entryPoint>["java","-jar","/${project.build.finalName}.jar"]</entryPoint>
              <resources>
                <resource>
                  <targetPath>/</targetPath>
                  <directory>${project.build.directory}</directory>
                  <include>${project.build.finalName}.jar</include>
                </resource>
              </resources>
            </configuration>
          </plugin>
3. 修改服務註冊中心地址
一組 compose 的服務通訊需要使用 services 的名稱進行訪問
之前各個專案配置的服務註冊中心地址如下:
```properties
eureka.client.service-url.defaultZone=http://localhost:1111/eureka/,http://localhost:1112/eureka/
```
由於Docker預設網路模式是bridge,各個容器的IP不相同,因此上面的配置不滿足需求。可為Eureka Server所在的容器配置主機名,並讓各個服務使用主機名訪問Eureka Server。所有服務修改配置如下:
```properties
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
```
由於Eureka server是高可用部署,所以配置檔案如下:
* application-peer1.properties
```properties
server.port=1111
spring.application.name=eureka-server
eureka.instance.hostname=peer1
eureka.client.service-url.defaultZone=http://peer2:1112/eureka/
```

* application-peer2.properties
```properties
server.port=1112
spring.application.name=eureka-server
eureka.instance.hostname=peer2
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/
```
4. 編寫docker-compose-manage.yml
```yml
version: "2"
services:
  # 指定服務名稱
  peer1:
    image: ibase/eureka-server:0.0.1-SNAPSHOT
    ports:
      - "1111:1111"
    environment:
      - spring.profiles.active=peer1
  peer2:
    image: ibase/eureka-server:0.0.1-SNAPSHOT
    hostname: peer2
    ports:
      - "1112:1112"
    environment:
      - spring.profiles.active=peer2
```
5. 編寫docker-compose-services.yml
```yml
version: "2"
services:
  # 指定服務名稱
  feign_upload_first:
    #指定服務所使用的映象名稱
    image: ibase/feign_upload_first:0.0.1-SNAPSHOT
    ports:
    - "8100:8100"
  feign_upload_second:
    image: ibase/feign_upload_second:0.0.1-SNAPSHOT
    ports:
    - "8101:8101"
  demo:
    image: ibase/demo:0.0.1-SNAPSHOT
    ports:
    - "8102:8102"
```
這裡說明一下,為什麼有兩份配置,不清楚什麼原因,配置寫在一起,啟動容器會報錯,服務治理與服務service分開就不會出錯,這個需要研究一下。
6. 編譯部署
將所有專案和配置檔案上傳到linux上,在各個服務根目錄使用如下命令構建映象:
```cmd
mvn clean package docker:build
```
先後執行如下命令啟動專案:
```cmd
docker-compose docker-compose-manage.yml up
```
```cmd
docker-compose docker-compose-services.yml up
```
7. 啟動後測試

正常訪問服務介面。