Docker Compose 之進階篇


筆者在前文《Docker Compose 簡介》和《Dcoker Compose 原理》兩篇文章中分別介紹了 docker compose 的基本概念以及實現原理。本文我們將繼續探索 docker compose,並通過 demo 介紹一些主要的用法。
說明:本文的演示環境為 ubuntu 16.04。

應用多個 compose 配置文件

docker-compose 命令默認使用的配置文件是當前目錄中的 docker-compose.yml 文件,當然我們可以通過 -f 選項指定一個其它名稱的配置文件,比如:

$ docker-compose -f docker-compose-dev.yml up

更酷的是我們可以添加多個 -f 選項,docker-compose 會自動合並它們,當然也會根據先后順序把一些重復的配置項覆蓋掉。 下面我們來演示一個常見的使用場景,先創建一個名稱為 docker-compose-base.yml 的配置文件,其內容如下:

version: '3'
services:
  web:
    build: .
  redis:
    image: "redis:latest"

然后再創建名稱為 docker-compose-dev.yml 的配置文件:

version: '3'
services:
  web:
    ports:
     - "5000:5000"

下面的命令會同時應用這兩個配置文件:

$ docker-compose -f docker-compose-base.yml -f docker-compose-dev.yml config

config 命令不會執行真正的操作,而是顯示 docker-compose 程序解析到的配置文件內容:

很顯然,我們指定的兩個配置文件的內容被合並了。接下來我們再來看看配置文件覆蓋的情況。新創建一個名為 docker-compose-prod.yml 的配置文件,編輯其內容如下:

version: '3'
services:
  web:
    ports:
     - "80:5000"
  redis:
    image: "redis:alpine"

然后執行下面的命令:

$ docker-compose -f docker-compose-base.yml -f docker-compose-prod.yml config

這次 docker-compose-prod.yml 文件中的 image 設置覆蓋了 docker-compose-base.yml 文件中的設置,並且映射的端口也改成了 80:5000。
就像 demo 中演示的那樣,我們可以通過多次指定 -f 選項的方式配置不同的環境,並且共用一份基礎的配置文件。

其實 docker-compse 還默認還支持一種合並、覆蓋配置文件的寫法,就是使用約定的文件名稱 docker-compose.yml 和 docker-compose.override.yml。下面我們把 docker-compose-base.yml 文件改名為 docker-compose.yml,把 docker-compose-prod.yml 文件改名為 docker-compose.override.yml,並直接執行不帶 -f 選項的命令:

$ docker-compose config

結果和前面是一樣的,docker-compose 自動合並了配置文件 docker-compose.yml 和 docker-compose.override.yml。這種方式雖然省去了指定 -f 選項的麻煩但其缺點也是很明顯的,就是無法指定更多不同的應用場景。

使用 network

Docker 提供的 network 功能能夠對容器進行網絡上的隔離,下面的 demo 中我們創建三個 service 和兩個虛擬網絡(注意,該 demo 主要是演示 network 的用法,所以筆者並沒有配置 proxy service 中的 nginx):

version: '3'
services:
  proxy:
    image: nginx
    ports:
      - "80:80"
    networks:
      - frantnet
  webapp:
    build: .
    networks:
      - frantnet
      - endnet
  redis:
    image: redis
    networks:
      - endnet
networks:
  frantnet:
  endnet:

其中的 proxy 和 webapp 連接到網絡 frantnet 上,webapp 和 redis 連接在了 endnet 上(請使用《Docker Compose 簡介》一文中介紹的 web 應用和 Dockerfile 來創建 webapp service)。請使用下面的命令來啟動應用:

$ docker-compose -p testnet -f docker-compose-net.yml up -d

從上圖我們可以看到該命令一共創建了兩個 network 和 三個容器。然后我們檢查一下這三個容器的網絡連接狀態。先從 testnet_webapp_1 中 ping 另外的兩個容器:

因為 webapp 服務同時連接到了 frantnet 和 endnet 兩個網絡中,所以它可以同時連接這兩個網絡中的其它容器(proxy 和 redis)。接下來再看看容器 proxy 和 redis 是否可以直接連通,我們從容器 testnet_redis_1 中 ping proxy(注意,執行這個操作前需要在容器  testnet_redis_1 中通過 apt-get update && apt-get install iputils-ping 命令安裝 ping 命令):

無法從容器 testnet_redis_1 中 ping 通 proxy 容器,這也就說明我們通過不同的虛擬網絡實現了容器網絡之間的隔離,從而在最大程度上去保護后端網絡的安全。

按順序啟動容器

默認情況下 compose 啟動容器的順序是不確定的,但是有些場景下我們希望能夠控制容器的啟動順序,比如應該讓運行數據庫的程序先啟動。我們可以通過 depends_on 來解決有依賴關系的容器的啟動順序問題,看下面的 demo:

version: '3'
services:
  proxy:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      - webapp
      - redis
  webapp:
    build: .
    depends_on:
      - redis
  redis:
    image: redis

啟動應用:

無論我們執行多少次這樣的啟動操作,這三個容器的啟動順序都是不變的。如果不應用 depends_on,每次執行 up 命令容器的啟動順序可能都是不一樣的。
需要注意的是 depends_on 只是解決了控制容器啟動順序的問題,如果一個容器的啟動時間非常長,后面的容器並不會等待它完成啟動。如果要解決這類問題(等待容器完成啟動並開始提供服務),需要使用 wait-for-it 等工具。

配置數據卷(volume)

數據卷是處理容器中的持久化數據的主要方式,在 compose 中我們可以通過兩種方式來指定數據卷:

  • 使用命名的數據卷
  • 直接指定主機上的路徑來創建數據卷

下面的 demo 演示了這兩種數據卷的配置方式:

version: "3.2"
services:
  web:
    image: nginx:alpine
    volumes:
      - type: volume
        source: mydata
        target: /data
      - type: bind
        source: ./nginx/logs
        target: /var/log/nginx
  jenkins:
    image: jenkins/jenkins:lts
    volumes:
      - jenkins_home:/var/jenkins_home
      - mydata:/data
volumes:
  mydata:
  jenkins_home:

在這個例子中我們一共創建了三個數據卷,分別是兩個命名的數據卷 jenkins_home 和 mydata:

其中的 jenkins_home 數據卷是給 jenkins 保存數據的。如果要在多個容器之間共享數據卷,就必須在頂級的 volumes 節點中定義這個數據卷,比如 mydata 數據卷,它被 web 和 jenkins service 共享了。比如我們在 web service 中的 mydata 數據卷中創建一個名為 hello 的文件,該文件會同時出現在 jenkins service 中:

我們還創建了一個 bind 類型的 volume 在當前目錄下的 nginx/logs 目錄下保存 nginx 的日志:

配置日志驅動

我們還可以通過 logging 節點為 service 指定日志驅動及其相關的選項:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"
  redis:
    image: "redis:latest"

上面的代碼指定日志驅動為 json-file,存儲日志的最大文件 size 為 200k,最多存儲 10 這樣大的文件。

在 compose file 文件中應用模板

從版本 3.4 開始,可以在 compose file 文件中使用 extension fields,其實我們可以簡單的把它理解為可以重用的代碼模板。模板的定義必須以 x- 開頭,然后以 & 開頭的字符串為模板命名,之后就可以以 * 加上模板的名稱引用模板:

version: '3.4'
x-logging:
  &default-logging
  driver: json-file
  options:
    max-size: "200k"
    max-file: "10"

services:
  web:
    build: .
    ports:
     - "5000:5000"
    logging: *default-logging
  redis:
    image: "redis:latest"
    logging: *default-logging

運行下面的命令看看模板替換的情況:

$ docker-compose -p template -f docker-compose-template.yml config

上圖顯示所有對模板的引用都被替換成了模板的內容。

總結

Docker compose 是一件強有力的效率工具,本文只是介紹了一些常見的用法。如果你還想掌握更多內容,請參考 compose file 的官方文檔。

參考:
Compose file version 3 reference
Docker Compose from development to production
Networking in Compose
Control startup order in Compose
3 Docker Compose features for improving team development workflow


免責聲明!

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



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