1. 程式人生 > >Docker 容器編排利器 Docker Compose

Docker 容器編排利器 Docker Compose

## Compose 簡介      通過前面幾篇文章的學習,我們可以通過 Dockerfile 檔案讓使用者很方便的定義一個單獨的應用容器。然而,在日常工作中,經常會碰到需要多個容器相互配合來完成某項任務的情況,例如之前我給大家講過的《[Docker 搭建 Redis Cluster 叢集](https://www.cnblogs.com/mrhelloworld/p/docker12.html)》,或者開發一個 Web 應用,除了 Web 服務容器本身,還需要資料庫服務容器、快取容器,甚至還包括負載均衡容器等等。   Docker Compose 恰好滿足了這樣的需求,它是用於**定義和執行多容器 Docker 應用程式**的工具。通過 Compose,您可以使用 `YAML` 檔案來配置應用程式所需要的服務。然後使用一個命令,就可以通過 `YAML` 配置檔案建立並啟動所有服務。   Docker Compose 專案是 Docker 官方的開源專案,來源於之前的 Fig 專案,使用 Python 語言編寫。負責實現對 Docker 容器叢集的快速編排。專案地址為:https://github.com/docker/compose/releases   Docker Compose 使用的三個步驟為: - 使用 `Dockerfile` 檔案定義應用程式的環境; - 使用 `docker-compose.yml` 檔案定義構成應用程式的服務,這樣它們可以在隔離環境中一起執行; - 最後,執行 `docker-compose up` 命令來建立並啟動所有服務。    ## Compose 安裝    ### 下載      官方文件:https://docs.docker.com/compose/install/   您可以在 macOS,Windows 和 Linux 上執行 Compose。本文演示基於 Linux 環境的安裝。我們可以使用 `curl` 命令從 Github 下載它的二進位制檔案來使用,執行以下命令下載 Docker Compose 的當前穩定版本。或者從網頁下載後上傳至伺服器指定目錄 `/usr/local/bin` 也行。 ```shell sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose ```      因為 Docker Compose 存放在 GitHub,可能不太穩定。你也可以通過執行下面的命令,高速安裝 Compose。該加速通道由 `DaoCloud` 提供:http://get.daocloud.io/#install-compose ```shell sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.26.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose ```   您可以通過修改 URL 中的版本,自定義您所需要的版本檔案。    ### 授權      安裝完成以後,檢視指定目錄,發現該檔案沒有可執行許可權,進行授權操作。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed1ac75f86e745b09a6304eedb901374~tplv-k3u1fbpfcp-zoom-1.image " ") ```shell # 將可執行許可權應用於該二進位制檔案 sudo chmod +x /usr/local/bin/docker-compose ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c33e6aba46a04c869510aac788354f47~tplv-k3u1fbpfcp-zoom-1.image " ")    ### 測試    ```shell docker-compose --version ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d97a3ae04adf451190ae82630e924408~tplv-k3u1fbpfcp-zoom-1.image " ")    ### 解除安裝      解除安裝 Compose 非常簡單,直接刪除二進位制檔案即可。 ```shell sudo rm /usr/local/bin/docker-compose ```    ## docker-compose.yml 檔案詳解    ### 概念      官方文件:https://docs.docker.com/compose/compose-file/   Docker Compose 允許使用者通過 `docker-compose.yml` 檔案(YAML 格式)來定義一組相關聯的容器為一個工程`(project)`。一個工程包含多個服務`(service)`,每個服務中定義了建立容器時所需的映象、引數、依賴等。 > 工程名若無特殊指定,即為 `docker-compose.yml` 檔案所在目錄的名稱。   Docker Compose 模板檔案我們需要關注的頂級配置有 `version`、`services`、`networks`、`volumes` 幾個部分,除 `version` 外,其他幾個頂級配置下還有很多下級配置,後面也會詳細給大家介紹,先來看看這幾個頂級配置都什麼意思: - `version`:描述 Compose 檔案的版本資訊,當前最新版本為 `3.8`,對應的 Docker 版本為 `19.03.0+`; - `services`:定義服務,可以多個,每個服務中定義了建立容器時所需的映象、引數、依賴等; - `networkds`:定義網路,可以多個,根據 DNS server 讓相同網路中的容器可以直接通過容器名稱進行通訊; - `volumes`:資料卷,用於實現目錄掛載。    ### 案例      在配置檔案中,所有的容器通過 `services` 來定義,然後使用 `docker-compose` 指令碼來啟動,停止和重啟容器,非常適合多個容器組合使用進行開發的場景。我們先從一個簡單的 Compose 案例學起。   編寫 `docker-compose.yml` 檔案。 ```shell # 建立目錄 mkdir -p /usr/local/docker-nginx # 切換至指定目錄 cd /usr/local/docker-nginx/ # 編寫 docker-compose.yml 檔案 vi docker-compose.yml ```      在檔案中新增以下內容: ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: nginx: # 服務名稱 image: nginx # 建立容器時所需的映象 container_name: mynginx # 容器名稱,預設為"工程名稱_服務條目名稱_序號" ports: # 宿主機與容器的埠對映關係 - "80:80" # 左邊宿主機埠:右邊容器埠 networks: # 配置容器連線的網路,引用頂級 networks 下的條目 - nginx-net # 定義網路,可以多個。如果不宣告,預設會建立一個網路名稱為"工程名稱_default"的 bridge 網路 networks: nginx-net: # 一個具體網路的條目名稱 name: nginx-net # 網路名稱,預設為"工程名稱_網路條目名稱" driver: bridge # 網路模式,預設為 bridge ```      使用 `docker-compose up` 建立並啟動所有服務。這個簡單的案例中就只有一個 Nginx 後續我們會來一些複雜的練習: ```shell # 前臺啟動 docker-compose up # 後臺啟動 docker-compose up -d ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/356a05ab5bce4c3e81970e717e3da408~tplv-k3u1fbpfcp-zoom-1.image " ")      瀏覽器訪問:http://192.168.10.10/ 結果如下: ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4c74ffa438e646f890efc714d21f7f4c~tplv-k3u1fbpfcp-zoom-1.image " ")      使用 `docker-compose down` 可以停止並刪除容器、網路。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8a4f0b3a857e446386142e2fafc220cb~tplv-k3u1fbpfcp-zoom-1.image " ")    ### version      描述 Compose 檔案的版本資訊,當前最新版本為 `3.8`,對應的 Docker 版本為 `19.03.0+`。關於每個版本的詳細資訊請參考:https://docs.docker.com/compose/compose-file/compose-versioning/   以下為 Compose 檔案的版本資訊所對應的 Docker 版本。 | Compose file format | Docker Engine release | | :------------------ | :-------------------- | | 3.8 | 19.03.0+ | | 3.7 | 18.06.0+ | | 3.6 | 18.02.0+ | | 3.5 | 17.12.0+ | | 3.4 | 17.09.0+ | | 3.3 | 17.06.0+ | | 3.2 | 17.04.0+ | | 3.1 | 1.13.1+ | | 3.0 | 1.13.0+ | | 2.4 | 17.12.0+ | | 2.3 | 17.06.0+ | | 2.2 | 1.13.0+ | | 2.1 | 1.12.0+ | | 2.0 | 1.10.0+ | | 1.0 | 1.9.1.+ |    ### services      剛才我們提到 `docker-compose.yml` 檔案中包含很多下級配置項,下面帶大家把一些常用的配置項詳細瞭解一下,先從頂級配置 `services` 開始。   `services` 用來定義服務,可以多個,每個服務中定義了建立容器時所需的映象、引數、依賴等,就像將命令列引數傳遞給 `docker run` 一樣。同樣,網路和資料卷的定義也是一樣的。   比如,之前我們通過 `docker run` 命令構建一個 MySQL 應用容器的命令如下: ```shell docker run -di --name mysql8 -p 3306:3306 -v /mydata/docker_mysql/conf:/etc/mysql/conf.d -v /mydata/docker_mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1234 mysql:8 ```   使用 `docker-compose.yml` 以後則可以這樣定義: ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: mysql: # 服務名稱 image: mysql:8 # 建立容器時所需的映象 container_name: mysql8 # 容器名稱,預設為"工程名稱_服務條目名稱_序號" ports: # 宿主機與容器的埠對映關係 - "3306:3306" # 左邊宿主機埠:右邊容器埠 environment: # 建立容器時所需的環境變數 MYSQL_ROOT_PASSWORD: 1234 volumes: - "/mydata/docker_mysql/conf:/etc/mysql/conf.d" - "/mydata/docker_mysql/data:/var/lib/mysql" ```   然後通過 `dokcer-compose` 相關命令即可完成容器的建立,停止或刪除等一系列操作。    #### image      指定建立容器時所需的**映象名稱標籤**或者**映象 ID**。如果映象在本地不存在,會去遠端拉取。 ```yaml services: web: image: hello-world ```    #### build      除了可以基於指定的映象構建容器,還可以基於 `Dockerfile` 檔案構建,在使用 `up` 命令時會執行構建任務。   通過 `build` 配置項可以指定 `Dockerfile` 所在資料夾的路徑。Compose 將會利用 `Dockerfile` 自動構建映象,然後使用映象啟動服務容器。   `build` 配置項可以使用絕對路徑,也可以使用相對路徑。 ```shell # 絕對路徑,在該路徑下基於名稱為 Dockerfile 的檔案構建映象 /usr/local/docker-centos # 相對路徑,相對當前 docker-compose.yml 檔案所在目錄,基於名稱為 Dockerfile 的檔案構建映象 . ```      接下來我們來個稍微複雜點的練習,通過基礎映象 `centos:7`,在該映象中安裝 jdk 和 tomcat 以後將其製作為一個新的映象 `mycentos:7`。   建立目錄並編寫 `Dockerfile` 檔案。 ```shell # 建立目錄 mkdir -p /usr/local/docker-centos # 切換至指定目錄 cd /usr/local/docker-centos/ # 編寫 Dockerfile 檔案 vi Dockerfile ```   `Dockerfile` 檔案內容如下: ```shell # 指明構建的新映象是來自於 centos:7 基礎映象 FROM centos:7 # 通過映象標籤聲明瞭作者資訊 LABEL maintainer="mrhelloworld.com" # 設定工作目錄 WORKDIR /usr/local # 新映象構建成功以後建立指定目錄 RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat # 拷貝檔案到映象中並解壓 ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat # 暴露容器執行時的 8080 監聽埠給外部 EXPOSE 8080 # 設定容器內 JAVA_HOME 環境變數 ENV JAVA_HOME /usr/local/java/jdk-11.0.6/ ENV PATH $PATH:$JAVA_HOME/bin # 啟動容器時啟動 tomcat 並檢視 tomcat 日誌資訊 CMD ["/usr/local/tomcat/apache-tomcat-9.0.37/bin/catalina.sh", "run"] ```   將所需的資源包 `jdk` 和 `tomcat` 上傳至 Dockerfile 同一目錄。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/55a77e0cef8c451fa547a7ea12f55ab7~tplv-k3u1fbpfcp-zoom-1.image " ")   建立目錄並編寫 `docker-compose.yml` 檔案。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: mycentos: # 服務名稱 build: . # 相對當前 docker-compose.yml 檔案所在目錄,基於名稱為 Dockerfile-alternate 的檔案構建映象 container_name: mycentos7 # 容器名稱,預設為"工程名稱_服務條目名稱_序號" ports: # 宿主機與容器的埠對映關係 - "8080:8080" # 左邊宿主機埠:右邊容器埠 ```   然後通過 `dokcer-compose` 相關命令即可完成容器的建立,停止或刪除等一系列操作。    ##### context      該選項可以是 Dockerfile 檔案的絕對/相對路徑,也可以是遠端 Git 倉庫的 URL,當提供的值是相對路徑時,相對當前 docker-compose.yml 檔案所在目錄。 ```yaml build: context: . # 相對當前 docker-compose.yml 檔案所在目錄,基於名稱為 Dockerfile 的檔案構建映象 ```    ##### dockerfile      一般情況下,預設都基於檔名叫 Dockerfile 的檔案構建映象,當然也可以是自定義的檔名,使用 `dockerfile` 宣告,不過這個選項只能宣告檔名,檔案所在路徑還是要通過 centext 來宣告。 ```yaml build: context: . # 相對當前 docker-compose.yml 檔案所在目錄 dockerfile: Dockerfile-alternate # 基於名稱為 Dockerfile-alternate 的檔案構建映象 ```    #### container_name      Compose 建立的容器預設生成的名稱格式為:`工程名稱_服務條目名稱_序號`。如果要使用自定義名稱,使用 `container_name` 宣告。 ```yaml services: mycentos: build: . container_name: mycentos7 # 容器名稱,預設為"工程名稱_服務條目名稱_序號" ``` > 因為 Docker 容器名稱必須是唯一的,所以如果指定了自定義名稱,就不能將服務擴充套件至多個容器。這樣做可能會導致錯誤。    ##### 關於序號      序號是幹什麼用的呢,看下面這個例子你就懂了,`docker-compose.yml` 檔案內容如下: ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: helloworld: # 服務名稱 image: hello-world ```      然後通過 `--scale` 指定 `helloworld` 服務一次性啟動 3 個。 ```shell docker-compose up -d --scale helloworld=3 ```      通過下圖可以看到有 3 個容器被建立,容器名稱最後的**序號**是從 1 開始累加的,這就是序號的作用。所以如果指定了自定義名稱,就不能將服務擴充套件至多個容器。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/882cd645240447618aea601519b953fd~tplv-k3u1fbpfcp-zoom-1.image " ")    #### depends_on      使用 Compose 最大的好處就是敲最少的命令做更多的事情,但一般專案容器啟動的順序是有要求的,如果直接從上到下啟動容器,必然會因為容器依賴問題而啟動失敗。例如在沒有啟動資料庫容器的情況下啟動了 Web 應用容器,應用容器會因為找不到資料庫而退出。`depends_on` 就是用來解決容器依賴、啟動先後問題的配置項。 ```yaml version: "3.8" services: web: build: . depends_on: - db - redis redis: image: redis db: image: mysql ```   上述 YAML 檔案定義的容器會先啟動 db 和 redis 兩個服務,最後才啟動 web 服務。    #### ports      容器對外暴露的埠,格式:`左邊宿主機埠:右邊容器埠`。 ```taml ports: - "80:80" - "8080:8080" ```    #### expose      容器暴露的埠不對映到宿主機,只允許能被連線的服務訪問。 ```yaml expose: - "80" - "8080" ```    #### restart      容器重啟策略,簡單的理解就是 Docker 重啟以後容器要不要一起啟動: - `no`:預設的重啟策略,在任何情況下都不會重啟容器; - `on-failure`:容器非正常退出時,比如退出狀態為`非0`(異常退出),才會重啟容器; - `always`:容器總是重新啟動,即使容器被手動停止了,當 Docker 重啟時容器也還是會一起啟動; - `unless-stopped`:容器總是重新啟動,除非容器被停止(手動或其他方式),那麼 Docker 重啟時容器則不會啟動。 ```yaml services: nginx: image: nginx container_name: mynginx ports: - "80:80" restart: always ```    #### environment      新增環境變數。可以使用陣列也可以使用字典。布林相關的值(true、false、yes、no)都需要用引號括起來,以確保 YML 解析器不會將它們轉換為真或假。 ```yaml environment: RACK_ENV: development SHOW: 'true' SESSION_SECRET: ```   或者以下格式: ```yaml environment: - RACK_ENV=development - SHOW=true - SESSION_SECRET ```    #### env_file      從檔案中獲取環境變數,可以指定一個或多個檔案,其優先順序低於 environment 指定的環境變數。 ```yaml env_file: - /opt/runtime_opts.env # 絕對路徑 - ./common.env # 相對路徑,相對當前 docker-compose.yml 檔案所在目錄 - ./apps/web.env # 相對路徑,相對當前 docker-compose.yml 檔案所在目錄 ``` > 注意:env 檔案中的每一行需採用 `鍵=值` 格式。以 `#` 開頭的行會被視為註釋並被忽略。空行也會被忽略。    #### volumes      資料卷,用於實現目錄掛載,支援**指定目錄掛載**、**匿名掛載**、**具名掛載**。 - 指定目錄掛載的格式為:`左邊宿主機目錄:右邊容器目錄`,或者`左邊宿主機目錄:右邊容器目錄:讀寫許可權`; - 匿名掛載格式為:`容器目錄即可`,或者`容器目錄即可:讀寫許可權`; - 具名掛載格式為:`資料卷條目名稱:容器目錄`,或者`資料卷條目名稱:容器目錄:讀寫許可權`。 > 關於**匿名掛載/具名掛載**更多的內容請閱讀《[Docker 最常用的映象命令和容器命令](https://www.cnblogs.com/mrhelloworld/p/docker12.html)》文章中**容器相關命令**部分的**目錄掛載**(容器資料卷操作)的內容。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: mysql: # 服務名稱 image: mysql:8 # 建立容器時所需的映象 container_name: mysql8 # 容器名稱,預設為"工程名稱_服務條目名稱_序號" ports: # 宿主機與容器的埠對映關係 - "3306:3306" # 左邊宿主機埠:右邊容器埠 environment: # 建立容器時所需的環境變數 MYSQL_ROOT_PASSWORD: 1234 volumes: # 絕對路徑 - "/mydata/docker_mysql/data:/var/lib/mysql" # 相對路徑,相對當前 docker-compose.yml 檔案所在目錄 - “./conf:/etc/mysql/conf.d“ # 匿名掛載,匿名掛載只需要寫容器目錄即可,容器外對應的目錄會在 /var/lib/docker/volume 中生成 - "/var/lib/mysql" # 具名掛載,就是給資料捲起了個名字,容器外對應的目錄會在 /var/lib/docker/volume 中生成 - "mysql-data-volume:/var/lib/mysql" # 定義資料卷,可以多個 volumes: mysql-data-volume: # 一個具體資料卷的條目名稱 name: mysql-data-volume # 資料卷名稱,預設為"工程名稱_資料卷條目名稱" ```    #### network_mode      設定網路模式,類似 `docker run` 時新增的引數 `--net host` 或者 `--network host` 的用法。 ```yaml network_mode: "bridge" network_mode: "host" network_mode: "none" network_mode: "service:[service name]" network_mode: "container:[container name/id]" ```    #### networks      配置容器連線的網路,引用頂級 networks 下的條目。 ```yaml # 定義服務,可以多個 services: nginx: # 服務名稱 networks: # 配置容器連線的網路,引用頂級 networks 下的條目 - nginx-net # 一個具體網路的條目名稱 # 定義網路,可以多個。如果不宣告,預設會建立一個網路名稱為"工程名稱_default"的 bridge 網路 networks: nginx-net: # 一個具體網路的條目名稱 name: nginx-net # 網路名稱,預設為"工程名稱_網路條目名稱" driver: bridge # 網路模式,預設為 bridge ```    ##### aliases      網路上此服務的別名。同一網路上的其他容器可以使用服務名或此別名連線到服務容器。同一服務在不同的網路上可以具有不同的別名。 ```yaml # 定義服務,可以多個 services: nginx: # 服務名稱 networks: # 配置容器連線的網路,引用頂級 networks 下的條目 nginx-net: # 一個具體網路的條目名稱 aliases: # 服務別名,可以多個 - nginx1 # 同一網路上的其他容器可以使用服務名或此別名連線到服務容器 # 定義網路,可以多個。如果不宣告,預設會建立一個網路名稱為"工程名稱_default"的 bridge 網路 networks: nginx-net: # 一個具體網路的條目名稱 name: nginx-net # 網路名稱,預設為"工程名稱_網路條目名稱" driver: bridge # 網路模式,預設為 bridge ```    ### volumes      通過頂級配置 `services` 的學習,大家應該已經明白頂級配置 `volumes` 是幹嘛的了,這裡再詳細把配置的不同方式講解一下。   以下方式的資料卷宣告建立卷時會使用預設的名稱:`"工程名稱_資料卷條目名稱"`。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: mysql: image: mysql:8 container_name: mysql8 ports: - "3306:3306" environment MYSQL_ROOT_PASSWORD: 1234 volumes: # 具名掛載,就是給資料捲起了個名字,容器外對應的目錄會在 /var/lib/docker/volume 中生成 - "mysql-data-volume:/var/lib/mysql" # 定義資料卷,可以多個 volumes: mysql-data-volume: # 一個具體資料卷的條目名稱 ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7c17ef47199c47208fe2918fdf7480e2~tplv-k3u1fbpfcp-zoom-1.image " ")      以下方式的資料卷宣告建立卷時會使用自定義的名稱。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: mysql: image: mysql:8 container_name: mysql8 ports: - "3306:3306" environment MYSQL_ROOT_PASSWORD: 1234 volumes: # 具名掛載,就是給資料捲起了個名字,容器外對應的目錄會在 /var/lib/docker/volume 中生成 - "mysql-data-volume:/var/lib/mysql" # 定義資料卷,可以多個 volumes: mysql-data-volume: # 一個具體資料卷的條目名稱 name: mysql-data-volume # 資料卷名稱,預設為"工程名稱_資料卷條目名稱" ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1192f31d7e5435c86dea33afd243d49~tplv-k3u1fbpfcp-zoom-1.image " ")    ### networks      通過頂級配置 `services` 的講解,大家其實已經明白頂級配置 `volumes` 是幹嘛的了,這裡再詳細把配置的不同方式講解一下。   如果不宣告網路,每個工程預設會建立一個網路名稱為`"工程名稱_default"`的 `bridge` 網路。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: nginx: image: nginx container_name: mynginx ports: - "80:80" # 定義網路,可以多個。如果不宣告,預設會建立一個網路名稱為"工程名稱_default"的 bridge 網路 #networks: ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0b1f82b5e91f4c4a813d96c96c493c10~tplv-k3u1fbpfcp-zoom-1.image " ")      以下方式的網路宣告建立網路時會使用預設的名稱:`"工程名稱_網路條目名稱"`,網路模式預設為 `bridge`。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: nginx: image: nginx container_name: mynginx ports: - "80:80" networks: # 配置容器連線的網路,引用頂級 networks 下的條目 nginx-net: # 定義網路,可以多個 networks: nginx-net: # 一個具體網路的條目名稱 ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e2bcc9558e7e4841993632ce093b2d68~tplv-k3u1fbpfcp-zoom-1.image " ")      以下方式的網路宣告建立網路時會使用自定義的名稱,還可以通過 `driver` 選擇網路模式,預設為 `bridge`。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: nginx: image: nginx container_name: mynginx ports: - "80:80" networks: # 配置容器連線的網路,引用頂級 networks 下的條目 nginx-net: # 定義網路,可以多個 networks: nginx-net: # 一個具體網路的條目名稱 name: nginx-net # 網路名稱,預設為"工程名稱_網路條目名稱" driver: bridge # 網路模式,預設為 bridge ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/19143f3385714f51ac6f621e8f322c32~tplv-k3u1fbpfcp-zoom-1.image " ")    ## Compose 常用命令      官方文件:https://docs.docker.com/compose/reference/overview/   為了更熟練的使用 Compose,以下常用命令大家多多練習,方可熟能生巧。 ```shell docker-compose [-f ...] [options] [COMMAND] [ARGS...] ```   部分命令選項如下: - `-f,--file`:指定使用的 Compose 模板檔案,預設為 `docker-compose.yml`,可以多次指定,指定多個 yml; - `-p, --project-name`:指定工程名稱,預設使用 `docker-compose.yml` 檔案所在目錄的名稱; - `-v`:列印版本並退出; - `--log-level`:定義日誌等級(DEBUG, INFO, WARNING, ERROR, CRITICAL)。    ### help      `docker-compose -help` 檢視幫助。 ```shell [root@localhost ~]# docker-compose -help Define and run multi-container applications with Docker. Usage: docker-compose [-f ...] [options] [COMMAND] [ARGS...] docker-compose -h|--help Options: -f, --file FILE Specify an alternate compose file (default: docker-compose.yml) -p, --project-name NAME Specify an alternate project name (default: directory name) -c, --context NAME Specify a context name --verbose Show more output --log-level LEVEL Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) --no-ansi Do not print ANSI control characters -v, --version Print version and exit -H, --host HOST Daemon socket to connect to --tls Use TLS; implied by --tlsverify --tlscacert CA_PATH Trust certs signed only by this CA --tlscert CLIENT_CERT_PATH Path to TLS certificate file --tlskey TLS_KEY_PATH Path to TLS key file --tlsverify Use TLS and verify the remote --skip-hostname-check Don't check the daemon's hostname against the name specified in the client certificate --project-directory PATH Specify an alternate working directory (default: the path of the Compose file) --compatibility If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent --env-file PATH Specify an alternate environment file Commands: build Build or rebuild services config Validate and view the Compose file create Create services down Stop and remove containers, networks, images, and volumes events Receive real time events from containers exec Execute a command in a running container help Get help on a command images List images kill Kill containers logs View output from containers pause Pause services port Print the public port for a port binding ps List containers pull Pull service images push Push service images restart Restart services rm Remove stopped containers run Run a one-off command scale Set number of containers for a service start Start services stop Stop services top Display the running processes unpause Unpause services up Create and start containers version Show the Docker-Compose version information ```    ### config      `docker-compose config -q` 驗證 `docker-compose.yml` 檔案。當配置正確時,不輸出任何內容,當配置錯誤時,輸出錯誤資訊。    ### pull      `docker-compose pull` 拉取服務依賴的映象。 ```shell # 拉取工程中所有服務依賴的映象 docker-compose pull # 拉取工程中 nginx 服務依賴的映象 docker-compose pull nginx # 拉取映象過程中不列印拉取進度資訊 docker-compose pull -q ```    ### up      `docker-compose up` 建立並啟動所有服務的容器。指定多個 yml 加 `-f` 選項。以守護程序模式執行加 `-d` 選項。 ```shell # 前臺啟動 docker-compose up # 後臺啟動 docker-compose up -d # -f 指定使用的 Compose 模板檔案,預設為 docker-compose.yml,可以多次指定,指定多個 yml docker-compose -f docker-compose.yml up -d ```    ### logs      `docker-compose logs` 檢視服務容器的輸出日誌。預設情況下,docker-compose 將對不同的服務輸出使用不同的顏色來區分。可以通過 `--no-color` 來關閉顏色。 ```shell # 輸出日誌,不同的服務輸出使用不同的顏色來區分 docker-compose logs # 跟蹤日誌輸出 docker-compose logs -f # 關閉顏色 docker-compose logs --no-color ```    ### ps      `docker-compose ps` 列出工程中所有服務的容器。 ```shell # 列出工程中所有服務的容器 docker-compose ps # 列出工程中指定服務的容器 docker-compose ps nginx ```    ### run      `docker-compose run` 在指定服務容器上執行一個命令。 ```shell # 在工程中指定服務的容器上執行 echo "helloworld" docker-compose run nginx echo "helloworld" ```    ### exec      `docker-compose exec` 進入服務容器。 ```shell # 進入工程中指定服務的容器 docker-compose exec nginx bash # 當一個服務擁有多個容器時,可通過 --index 引數進入到該服務下的任何容器 docker-compose exec --index=1 nginx bash ```    ### pause      `docker-compose pause` 暫停服務容器。 ```shell # 暫停工程中所有服務的容器 docker-compose pause # 暫停工程中指定服務的容器 docker-compose pause nginx ```    ### unpause      `docker-compose unpause` 恢復服務容器。 ```shell # 恢復工程中所有服務的容器 docker-compose unpause # 恢復工程中指定服務的容器 docker-compose unpause nginx ```    ### restart      `docker-compose restart` 重啟服務容器。 ```shell # 重啟工程中所有服務的容器 docker-compose restart # 重啟工程中指定服務的容器 docker-compose restart nginx ```    ### start      `docker-compose start` 啟動服務容器。 ```shell # 啟動工程中所有服務的容器 docker-compose start # 啟動工程中指定服務的容器 docker-compose start nginx ```    ### stop      `docker-compose stop` 停止服務容器。 ```shell # 停止工程中所有服務的容器 docker-compose stop # 停止工程中指定服務的容器 docker-compose stop nginx ```    ### kill      `docker-compose kill` 通過傳送 `SIGKILL` 訊號停止指定服務的容器。 ```shell # 通過傳送 SIGKILL 訊號停止工程中指定服務的容器 docker-compose kill nginx ```    ### rm      `docker-compose rm` 刪除服務(停止狀態)容器。 ```shell # 刪除所有(停止狀態)服務的容器 docker-compose rm # 先停止所有服務的容器,再刪除所有服務的容器 docker-compose rm -s # 不詢問是否刪除,直接刪除 docker-compose rm -f # 刪除服務容器掛載的資料卷 docker-compose rm -v # 刪除工程中指定服務的容器 docker-compose rm -sv nginx ```    ### ~~create~~      `docker-compose create` 為服務建立容器,已不推薦使用。推薦使用 `docker-compose up` 來實現該功能。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/37f76dc3043549bd9cd70839472047a3~tplv-k3u1fbpfcp-zoom-1.image " ") ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/166da6731bc042eca536623b0d1d6cc2~tplv-k3u1fbpfcp-zoom-1.image " ")    ### ~~scale~~      `docker-compose scale` 設定指定服務執行的容器個數,已不推薦使用。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/deb3c92ff4e4440f99b704600ad7b828~tplv-k3u1fbpfcp-zoom-1.image " ") ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b2b9ea8a89bc403d9f5ef9bf921a8e80~tplv-k3u1fbpfcp-zoom-1.image " ")   推薦使用 `--scale service=num` 的引數來設定數量。 ```shell # 通過 --scale 指定 helloworld 服務一次性啟動 3 個 docker-compose up -d --scale helloworld=3 ```    ### images      `docker-compose images` 列印服務容器所對應的映象。 ```shell # 列印所有服務的容器所對應的映象 docker-compose images # 列印指定服務的容器所對應的映象 docker-compose images nginx ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e0540e9a6e024f96a48f61d432b453fa~tplv-k3u1fbpfcp-zoom-1.image " ")    ### port      `docker-compose port` 列印指定服務容器的某個埠所對映的宿主機埠。 ```shell [root@localhost docker-nginx]# docker-compose port nginx 80 0.0.0.0:80 ```    ### top      `docker-compose top` 顯示正在執行的程序。 ```shell # 顯示工程中所有服務的容器正在執行的程序 docker-compose top # 顯示工程中指定服務的容器正在執行的程序 docker-compose top nginx ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cded645a51a349178948631e5be0bf2d~tplv-k3u1fbpfcp-zoom-1.image " ")    ## 總結      Docker Compose 的整體使用步驟還是比較簡單的,三個步驟為: - 使用 `Dockerfile` 檔案定義應用程式的環境; - 使用 `docker-compose.yml` 檔案定義構成應用程式的服務,這樣它們可以在隔離環境中一起執行; - 最後,執行 `docker-compose up` 命令來建立並啟動所有服務。   雖然 **docker-compose.yml 檔案詳解**和**Compose 常用命令**這兩大塊的內容比較多,但是如果要快速入門使用 `Compose`,其實只需要瞭解其中部分內容即可。後期大家可在專案生產環境中根據自身情況再進一步深入學習即可。   接下來我們使用 Docker Compose 搭建一遍 Redis Cluster 叢集環境,感受感受與之前的區別。    ## 參考資料    - https://docs.docker.com/compose/install/ - http://get.daocloud.io/#install-compose - https://docs.docker.com/compose/ - https://docs.docker.com/compose/compose-file/ - https://docs.docker.com/compose/reference/overview/ ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b82b98882616480db9997a8c17a41454~tplv-k3u1fbpfcp-zoom-1.image) 本文采用 `知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議`。 大家可以通過 `分類` 檢視更多關於 `Docker` 的文章。