Docker-compose-1

本章要點:dockek-compose基礎用法,compose基礎説明,無案例

Docker-Compose項目是Docker官方的開源項目,負責實現對Docker容器集羣的快速編排。本文編寫來源參考: docker菜鳥入門,Docker Compose 容器編排技術使用詳解, compose安裝使用、入門進階案例 ,隱藏敏感配置項(secrets方式)

Docker-compose理論

Docker-compose特點

  • 簡化多容器應用程序的管理
  • Docker Compose 允許您將多個容器組合成一個應用程序,並通過一個配置文件來定義和管理它們。這使得啓動、停止、重建和管理整個應用程序變得簡單。
  • 聲明式配置
  • 使用 YAML 文件來定義應用程序的配置,使得配置文件易於閲讀、理解和維護。您可以定義服務的各種屬性,如鏡像、環境變量、端口映射、卷掛載等。
  • 快速啓動和停止
  • 通過簡單的命令,如 docker-compose updocker-compose down,您可以快速啓動和停止整個應用程序。這使得本地開發和測試變得方便和高效。
  • 自動化容器之間的網絡連接
  • Docker Compose 自動為應用程序中的服務創建一個默認網絡,並將每個容器連接到該網絡。這使得容器之間的通信變得簡單,可以通過服務名稱來進行訪問,而無需處理 IP 地址和端口號。
  • 數據卷管理
  • Docker Compose 允許您定義卷掛載,將容器內的數據持久化到宿主機上。這簡化了數據的管理和遷移,並可以確保數據的持久性。
  • 可擴展性和複用性
  • Docker Compose 允許您輕鬆地擴展和重用配置文件。您可以定義多個環境(如開發、測試、生產等)的配置,並根據需要進行組合和使用。

Docker-compose使用場景

如果日常開發中遇到下面的場景,可以考慮使用Docker Compose

  • 搭建本地開發環境
  • Docker Compose 可以幫助開發人員在本地快速搭建和管理多容器的開發環境。通過定義每個服務的鏡像、環境變量、端口映射等屬性,開發人員可以輕鬆地啓動和停止整個應用程序,並在不同的服務之間進行通信。
  • 部署測試環境
  • Docker Compose 可以用於在測試環境中運行和管理多容器的應用程序。通過創建一個與生產環境相似的容器組合,測試人員可以在一個獨立的環境中進行端到端的測試,並且可以輕鬆地重建和銷燬整個測試環境。
  • 持續集成和持續部署
  • Docker Compose 可以與持續集成和持續部署工具集成,如 Jenkins、GitLab CI、Travis 等。通過在配置文件中定義構建步驟和部署策略,可以將整個應用程序以容器化的方式自動構建、測試和部署到生產環境中。
  • 多環境部署
  • Docker Compose 允許你定義多個環境(如開發、測試、生產)的配置文件,並根據需要進行組合和使用,這使得在不同環境中輕鬆部署應用程序變得簡單和可靠。
  • 微服務架構
  • Docker Compose 適用於構建和管理微服務架構。通過將每個微服務定義為一個獨立的服務,並使用容器進行隔離,可以實現微服務之間的鬆耦合和獨立部署。

Docker-compose安裝

  • 安裝docker
  • 方式一
下載鏈接: https://github.com/docker/compose/releases
~]# wget https://github.com/docker/compose/releases/download/v2.40.0/docker-compose-linux-x86_64
~]# mv docker-compose-Linux-x86_64 /usr/local/bin/
~]# chmod +x /usr/local/bin/docker-compose-Linux-x86_64 
~]# mv /usr/local/bin/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose

~]# docker-compose --version
Docker Compose version v2.40.0

~]# docker --version
Docker version 26.1.4, build 5650f9b
  • 方式二
~]# yum install python3
~]# yum -y install python3-pip
~]# pip3 install --upgrade pip
~]# pip3 install docker-compose
~]# docker-compose --version

Docker Compose 配置文件屬性

Docker Compose 使用 YAML 文件來定義服務。官方推薦的默認文件名為 compose.yml ,但同時也支持 docker-compose.yml,compose 文件中包含 6 個頂級屬性version、services、networks、volumes、configs 與secrets,主要就是圍繞這幾個屬性一直加參數,在下面的內容中將會結合實際的案例一一説明。首先在服務器目錄下創建一個docker-compose.yml文件,後面的內容都編寫在該文件中。

version

version 是一個頂級屬性,但已經過時, 不再需要在 compose 文件中出現了。

serivces

services 是一個頂級屬性,也是整個Docker Compose配置文件中作為服務定義最重要的屬性,它用於定義一個應用中所包含的服務。Docker Compose 會將每個服務部署在各自的容器中。其下包含的第一級的屬性即為服務名稱,這個名稱可以根據服務內容隨意命名。而在服務名稱下還可包含很多的屬性,常用屬性如下:

build
  • 用於指定當前 Dockerfile 的路徑,以 [./]就是當前
# 當前目錄  Docker-compose.yml, Dockerfile
version: '3'
services:
  web:       # <--  該 web 服務使用從 Dockerfile 當前目錄中構建的鏡像
    build: .
  • 如果 Dockerfile 文件名不是默認名稱,則需要通過 build 下的 context 屬性指定路徑,dockerfile 屬性指定文件名
當前目錄  Docker-compose.yml, abcDockerfile
services:
  webapp:     # <--  該 webapp 服務使用從 Dockerfile 當前目錄中構建的鏡像
    build:
      context: ./
      dockerfile: abcDockerfile
image

指定當前服務所需要使用的鏡像,如本地沒有這個鏡像,則會從dockerhub中自動pull

  • 使用格式
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 鏡像id
  • 示例
version: "3.7"
services:
  redis:
    image: redis   <-- 鏡像名稱,如果不指定: 就是 latest
container_name

指定自定義容器名稱,如果不指定則自動生成

  • 示例
# 如這段配置,容器名就是 tomcat8.5.100
services:
  tomcat: # 服務名稱
    image: tomcat:8.5.100-jre8 # redis鏡像版本
    container_name: tomcat8.5.100 # 容器名稱
ports

主機映射端口:容器端口

  • 語法
ports:
 - 10240:8080 # 綁定容器的 8080 端口到主機的 10240 端口
 - 8080:8080  # 綁定容器的 8000 端口到主機的 8080 端口
 - 443 # 綁定容器的 443 端口到主機的任意端口,容器啓動時隨機分配綁定的主機端口號
  • 示例
services:
  tomcat: # 服務名稱
    image: tomcat:8.5.100-jre8 # redis鏡像版本
    container_name: tomcat8.5.100 # 容器名稱
    ports:
      - 8081:8080   # 綁定容器的 8080 端口到主機的 8081 端口
command

用於覆蓋 Dockerfile 中的 CMD 指令命令,如果Dockerfile中已經有CMD指定,那就不需要在配置了。

  • 示例
# 假設Dockfile中存在:CMD ["/data/nginx/sbin/nginx","-g","daemon off;"]

services:
  nginx: # 服務名稱
    image: nginx:1.28.0     # nginx鏡像版本
    container_name: n1 # 容器名稱
    ports:
      - 8080:8080   # 綁定容器的 8080 端口到主機的 8081 端口
      command: ["/data/nginx/sbin/nginx","-g","daemon off;"]  
      # 如果指定了command則覆蓋dockerfile的CMD,不指定則用Dockerfile的CMD
restart
  • no:是默認的重啓策略,在任何情況下都不會重啓容器。
  • always:容器總是重新啓動。
  • on-failure:在容器非正常退出時(退出狀態非0),才會重啓容器。
  • unless-stopped:在容器退出時總是重啓容器,但是不考慮在Docker守護進程啓動時就已經停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

注:swarm 集羣模式,請改用 restart_policy。

depends_on

depends_on 是一個用於定義服務之間依賴關係的關鍵字。它允許您指定一個或多個服務依賴於其他服務,以確保在啓動或重新創建容器時,所依賴的服務先於依賴它們的服務啓動。如下,web容器啓動時,需要依賴db和redis兩個容器的啓動之後才會啓動

  • 示例
services:
  tomcat: # 服務名稱
    image: tomcat:8.5.100-jre8 # redis鏡像版本
    container_name: tomcat8.5.100 # 容器名稱
    ports:
      - 8081:8080   # 綁定容器的 8080 端口到主機的 8081 端口
    depends_on:   # <-- 依賴於db跟redis
      - db
      - redis
  • 補充説明
  • 啓動順序
  • 通過在服務的配置中使用 depends_on,您可以告訴 Docker Compose 在啓動容器時按照指定的順序啓動服務。例如,如果服務 A 依賴於服務 B 和服務 C,則在啓動時,Docker Compose 會先啓動服務 B 和服務 C,然後才會啓動服務 A。
  • 僅表示依賴關係
  • depends_on 只表示依賴關係,而不會等待依賴的服務完全可用。它只確保在依賴的服務啓動後再啓動當前服務。因此,依賴的服務可能仍在進行初始化或準備階段,而不一定已經完全可用。如果需要等待服務完全可用,可以結合使用其他工具或技術,例如健康檢查或等待腳本。
  • 無法保證健康狀態
  • depends_on 並不能保證依賴的服務在啓動後處於健康狀態。它只負責在啓動時按照指定順序啓動服務,但並不檢查服務的健康狀態或等待服務變為可用狀態。對於檢查服務健康狀態,可以使用其他機制,例如使用健康檢查命令或工具。
  • 並行啓動
  • 默認情況下,Docker Compose 會盡可能並行啓動服務,而不是完全按照 depends_on 指定的依賴關係順序啓動。這是因為 Docker Compose 會嘗試最大化容器的併發啓動,以提高啓動效率。如果需要強制按照依賴關係順序啓動,請使用 depends_on 結合 restart 關鍵字的 condition: [“service_started”] 選項。
deploy-集羣選項

指定與服務的部署和運行有關的配置。 docker-compose deploy命令的作用是將一個由docker-compose.yml定義的服務棧部署到Swarm集羣。這個命令會創建所需的服務和網絡,並在集羣中啓動它們。它還會管理服務的更新和擴展

deploy屬性下有一個常用屬性 replicas,用於指定該服務啓動的容器的數量。即實現一個服務多個容器。一旦指定了 deploy:replicas,就不能再指定container_name 屬性了。因為各個啓動的容器名稱不能相同,而只能由系統自動生成。

  • 如下示例:
# 這裏有點像k8s?

version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
  • 可以選參數:
  • endpoint_mode:訪問集羣服務的方式。
  • vip: Docker 集羣服務一個對外的虛擬 ip。所有的請求都會通過這個虛擬 ip 到達集羣服務內部的機器
  • **dnsrr:**DNS 輪詢(DNSRR)。所有的請求會自動輪詢獲取到集羣 ip 列表中的一個 ip 地址。
  • labels:在服務上設置標籤。可以用容器上的 labels(跟 deploy 同級的配置) 覆蓋 deploy 下的 labels。
  • mode:指定服務提供的模式。
  • replicated:複製服務,複製指定服務到集羣的機器上。
  • global:全局服務,服務將部署至集羣的每個節點。
  • restart_policy:配置如何在退出容器時重新啓動容器。
  • condition:可選 none,on-failure 或者 any(默認值:any)。
  • delay:設置多久之後重啓(默認值:0)。
  • max_attempts:嘗試重新啓動容器的次數,超出次數,則不再嘗試(默認值:一直重試)。
  • window:設置容器重啓超時時間(默認值:0)。
  • rollback_config:配置在更新失敗的情況下應如何回滾服務。
  • parallelism:一次要回滾的容器數。如果設置為0,則所有容器將同時回滾。
  • delay:每個容器組回滾之間等待的時間(默認為0s)。
  • failure_action:如果回滾失敗,該怎麼辦。其中一個 continue 或者 pause(默認pause)。
  • monitor:每個容器更新後,持續觀察是否失敗了的時間 (ns|us|ms|s|m|h)(默認為0s)。
  • max_failure_ratio:在回滾期間可以容忍的故障率(默認為0)。
  • order:回滾期間的操作順序。其中一個 stop-first(串行回滾),或者 start-first(並行回滾)(默認 stop-first )。
  • update_config:配置應如何更新服務,對於配置滾動更新很有用。
  • parallelism:一次更新的容器數。
  • delay:在更新一組容器之間等待的時間。
  • failure_action:如果更新失敗,該怎麼辦。其中一個 continue,rollback 或者pause (默認:pause)。
  • monitor:每個容器更新後,持續觀察是否失敗了的時間 (ns|us|ms|s|m|h)(默認為0s)。
  • max_failure_ratio:在更新過程中可以容忍的故障率。
  • order:回滾期間的操作順序。其中一個 stop-first(串行回滾),或者 start-first(並行回滾)(默認stop-first)。
networks (service|頂層屬性)

用於指定當前服務容器要連接到的網絡。該網絡必須是已經存在的,通常會提前創建好,或通過頂級屬性networks 創建的網絡。

  • networks主要有下面的幾種
  • default
    默認情況下docker-compose會建立一個默認的網絡,名稱為docker-compose.yml所在目錄名稱小寫形式加上“_default”,我們的TFLinux環境就是“tflinux_default”。
# 這個默認網絡會對所有services下面的服務生效,所以services下面的各個服務之間才能夠通過service名稱互相訪問。如果要自定義默認網絡可以針對“default”網絡進行設置,這樣就會影響到默認網絡了。
networks:
  default:
    driver: bridge
  • 自定義
# 除了默認網絡之外,我們也可以建立自定義的網絡,這個網絡名稱就比較隨意了
networks:
  persist:
    driver: bridge
  • 已存在的網絡
# 通過 docker network create 創建的網絡,這裏需要用到 external 關鍵字, 這裏就可以配置跨主機橋用。
networks:
  persist:
    external:
      name: bridge2
  • 菜鳥網示例
services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2
  • aliases :同一網絡上的其他容器可以使用服務名稱或此別名來連接到對應容器的服務。
volumes(service|頂層屬性)

將主機的數據卷或者文件掛載到容器裏,用於多個容器之間共享數據。這些卷可以用於持久性數據存儲,例如數據庫文件、配置文件等。通過使用 docker-compose volume,您可以輕鬆地管理這些數據卷,並確保它們在容器之間共享和持久化。volume 通常可以使用路徑與卷標兩種方式。

  • 示例-路徑
db:
  image: mariadb:latest
  ports:
    - "3306:3306"
  volumes:
    - /etc/mysql:/var/lib/mysql
  • 示例-卷標
    通過創建卷標docker volume create name 掛載點: /var/lib/docker/volume/CreateName/_data
services:
  backend:
  image: awesome/database
  volumes:
    - db-data:/etc/data
  backup:
  image: backup-service
  volumes:
    - db-data:/var/lib/backup/data
volumes:
 db-data:

secrets

官網參數secrets, 沒實際測試當前僅在刷理論,後續在測試

Secrets是Docker提供的一種安全機制,用於存儲和管理敏感數據,如密碼、API密鑰等,通過使用Secrets,我們可以將這些數據與應用程序代碼分離,從而提高安全性和可維護性。根據官網介紹Secret是1.25之後引入的,它運行在swarm上的命令。使用Secrets需要執行Swarm初始化操作 docker swarm init

  • 基於環境變量
  1. 創建secret:
echo "pgpwd" | docker secret create PGSQL_PWD -
  1. 查看secret
docker secret ls
  1. 編輯docker-compose.yml
version: '3.1'
services:
  postgres-dev:
    image: pgrouting/pgrouting:12-3.1-3.1.3
    container_name: postgres-dev
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${PGSQL_PWD}
    ports:
      - 5432:5432
    volumes:
      - /etc/localtime:/etc/localtime:ro   #將外邊時間直接掛載到容器內部,權限只讀
      - ./data:/var/lib/postgresql/data
    secrets:
      - PGSQL_PWD
  • 基於文件
  • 示例1
  1. 創建密碼文件
# 在 docker-compose.yml 同級目錄下,
echo "thispassword" > password.txt    # 定義密碼
chmod 600 password.txt # 僅當前用户可讀寫
  1. 編輯docker-compose.yml
version: '3.8' 
services: 
  app: 
    image: nginx
    secrets: 
      - source: db_password  # 引用上述密鑰名稱 
        target: /run/secrets/db_pass  # 容器內掛載路徑,默認權限 0400 
secrets: 
  db_password:  # 密鑰名稱,需唯一 
    file: ./password.txt   # 本地文件路徑,相對 Compose 文件位置
  • 示例2
echo "thispassword" >> my_secret.txt

vim docker-compose.yml
version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt    # 權限需設置為600