使用Docker Compose部署應用(詳解版)

2020-07-16 10:04:47
下面為大家介紹一下如何使用 Docker Compose 部署多容器的應用。

Docker Compose 與 Docker Stack 非常類似。它能夠在 Docker 節點上,以單引擎模式(Single-Engine Mode)進行多容器應用的部署和管理。

多數的現代應用通過多個更小的服務互相協同來組成一個完整可用的應用。比如一個簡單的範例應用可能由如下 4 個服務組成。
  • Web前端。
  • 訂單管理。
  • 品類管理。
  • 後台資料庫。

將以上服務組織在一起,就是一個可用的應用。

部署和管理繁多的服務是困難的。而這正是 Docker Compose 要解決的問題。

Docker Compose 並不是通過指令碼和各種冗長的 docker 命令來將應用元件組織起來,而是通過一個宣告式的組態檔描述整個應用,從而使用一條命令完成部署。

應用部署成功後,還可以通過一系列簡單的命令實現對其完整宣告周期的管理。甚至,組態檔還可以置於版本控制系統中進行儲存和管理。

Docker Compose 的背景

Docker Compose 的前身是 Fig。Fig 是一個由 Orchard 公司開發的強有力的工具,在當時是進行多容器管理的最佳方案。

Fig 是一個基於 Docker 的 Python 工具,允許使用者基於一個 YAML 檔案定義多容器應用,從而可以使用 fig 命令列工具進行應用的部署。

Fig 還可以對應用的全生命週期進行管理。

內部實現上,Fig 會解析 YAML 檔案,並通過 Docker API 進行應用的部署和管理。

在 2014 年,Docker 公司收購了 Orchard 公司,並將 Fig 更名為 Docker Compose。

命令列工具也從 fig 更名為 docker-compose,並自此成為系結在 Docker 引擎之上的外部工具。

雖然它從未完全整合到 Docker 引擎中,但是仍然受到廣泛關注並得到普遍使用。

直至今日,Docker Compose 仍然是一個需要在 Docker 主機上進行安裝的外部 Python 工具。

使用它時,首先編寫定義多容器(多服務)應用的 YAML 檔案,然後將其交由 docker-compose 命令處理,Docker Compose 就會基於 Docker 引擎 API 完成應用的部署。

安裝 Docker Compose

Docker Compose 可用於多種平台。下面將分別介紹在 Windows、Mac 以及 Linux 上的幾種安裝方法。

1) 在 Windows 10 上安裝 Docker Compose

在 Windows 10 上執行 Docker 的推薦工具是 Windows 版 Docker(Docker for Windows, DfW)。

Docker Compose 會包含在標準 DfW 安裝包中。所以,安裝 DfW 之後就已經有 Docker Compose 工具了。

在 PowerShell 或 CMD 終端中使用如下命令可以檢查 Docker Compose 是否安裝成功。

> docker-compose --version
docker-compose version 1.18.0, build 8dd22a96

關於在 Windows 10 上安裝 Windows 版 Docker 的詳細步驟請參考《Windows Docker安裝》一節。

2) 在 Mac 上安裝 Docker Compose

與 Windows 10 一樣,Docker Compose 也作為 Mac 版 Docker(Docker for Mac, DfM)的一部分進行安裝,所以一旦安裝了 DfM,也就安裝了 Docker Compose。

在終端中執行如下命令檢查 Docker Compose 是否安裝。

$ docker-compose --version
docker-compose version 1.18.0, build 8dd22a96

關於安裝 Mac 版Docker的詳細內容請參考《Mac Docker安裝》一節。

3) 在 Windows Server 上安裝 Docker Compose

Docker Compose 在Windows Server 上是作為一個單獨的二進位制檔案安裝的。

因此,使用它的前提是確保在 Windows Server 上已經正確安裝了 Docker。

在 PowerShell 終端中輸入如下命令來安裝 Docker Compose。

為了便於閱讀,下面的命令使用反引號(`)來對換行進行跳脫,從而將多行命令合併。

下面的命令安裝的是 1.18.0 版本的 Docker Compose,可以參考 GitHub 自行選擇版本號(https://github.com/docker/compose/releases)。

只需要將 URL 中的 1.18.0 替換為你希望安裝的版本即可。

> Invoke-WebRequest ` "https://github.com/docker/compose/releases/download/1
.18.0/docker-compose-Windows-x86_64.exe" `
-UseBasicParsing `
-OutFile $Env:ProgramFilesdockerdocker-compose.exe

Writing web request
Writing request stream... (Number of bytes written: 5260755)

使用 docker-compose --version 命令檢視安裝情況。

> docker-compose --version
docker-compose version 1.18.0, build 8dd22a96

Docker Compose 安裝好了,只要 Windows Server 上安裝有 Docker 引擎即可使用。

4) 在 Linux 上安裝 Docker Compose

在 Linux 上安裝 Docker Compose分為兩步。

首先使用 curl 命令下載二進位制檔案,然後使用 chmod 命令將其置為可執行。

Docker Compose 在 Linux 上的使用,同樣需要先安裝有 Docker 引擎。

如下命令會下載 1.18.0 版本的 Docker Compose 到 /usr/bin/local。請在 GitHub 上查詢想安裝的版本(https://github.com/docker/compose/releases),並替換 URL 中的 1.18.0。

下面的範例是一條寫成多行的命令,如果要將其合併為一行,請刪掉反斜槓()。

https% Total % Received Time Time Time Current

下載 docker-compose 二進位制檔案後,使用如下命令使其可執行。

$ chmod +x /usr/local/bin/docker-compose

檢查安裝情況以及版本。

$ docker-compose --version
docker-compose version 1.18.0, build 8dd22a9

現在就可以在 Linux 上使用 Docker Compose 了。

此外,也可以使用 pip 來安裝 Docker Compose 的 Python 包。

Compose 檔案

Docker Compose 使用 YAML 檔案來定義多服務的應用。YAML 是 JSON 的一個子集,因此也可以使用 JSON。

Docker Compose 預設使用檔名 docker-compose.yml。當然,也可以使用 -f 引數指定具體檔案。

如下是一個簡單的 Compose 檔案的範例,它定義了一個包含兩個服務(web-fe 和 redis)的小型 Flask 應用。

這是一個能夠對存取者進行計數並將其儲存到 Redis 的簡單的 Web 服務。

version: "3.5"
services:
web-fe:
build: .
command: python app.py
ports:
- target: 5000
published: 5000
networks:
- counter-net
volumes:
- type: volume
source: counter-vol
target: /code
redis:
image: "redis:alpine"
networks:
counter-net:

networks:
counter-net:

volumes:
counter-vol:

在深入研究之前粗略觀察檔案的基本結構,首先可以注意到,它包含 4 個一級 key:version、services、networks、volumes。

version 是必須指定的,而且總是位於檔案的第一行。它定義了 Compose 檔案格式(主要是 API)的版本。

注意,version 並非定義 Docker Compose 或 Docker 引擎的版本號。

範例中 Compose 檔案將使用版本 3 及以上的版本。

services 用於定義不同的應用服務。上邊的例子定義了兩個服務:一個名為 web-fe 的 Web 前端服務以及一個名為 redis 的記憶體資料庫服務。

Docker Compose 會將每個服務部署在各自的容器中。

networks 用於指引 Docker 建立新的網路。預設情況下,Docker Compose 會建立 bridge 網路。

這是一種單主機網路,只能夠實現同一主機上容器的連線。當然,也可以使用 driver 屬性來指定不同的網路型別。

下面的程式碼可以用來建立一個名為 over-net 的 Overlay 網路,允許獨立的容器(standalone container)連線(attachable)到該網路上。

networks:
over-net:
driver: overlay
attachable: true

volumes 用於指引 Docker 來建立新的捲。

上面例子中的 Compose 檔案使用的是 v3.5 版本的格式,定義了兩個服務,一個名為 counter-net 的網路和一個名為 counter-vol 的卷。

更多的資訊在 services 中,下面仔細分析一下。

Compose 檔案中的 services 部分定義了兩個二級 key:web-fe 和 redis。

它們各自定義了一個應用程式服務。需要明確的是,Docker Compose 會將每個服務部署為一個容器,並且會使用 key 作為容器名字的一部分。

本例中定義了兩個 key:web-fe 和 redis。因此 Docker Compose 會部署兩個容器,一個容器的名字中會包含 web-fe,而另一個會包含 redis。

web-fe 的服務定義中,包含如下指令。

1) build

指定 Docker 基於當前目錄(.)下 Dockerfile 中定義的指令來構建一個新映象。該映象會被用於啟動該服務的容器。

2) command

python app.py 指定 Docker 在容器中執行名為 app.py 的 Python 指令碼作為主程式。

因此映象中必須包含 app.py 檔案以及 Python,這一點在 Dockerfile 中可以得到滿足。

3) ports

指定 Docker 將容器內(-target)的 5000 埠對映到主機(published)的 5000 埠。

這意味著傳送到 Docker 主機 5000 埠的流量會被轉發到容器的 5000 埠。容器中的應用監聽埠 5000。

4) networks

使得 Docker 可以將服務連線到指定的網路上。這個網路應該是已經存在的,或者是在 networks 一級 key 中定義的網路。

對於 Overlay 網路來說,它還需要定義一個 attachable 標誌,這樣獨立的容器才可以連線上它(這時 Docker Compose 會部署獨立的容器而不是 Docker 服務)。

5) volumes

指定 Docker 將 counter-vol 捲(source:)掛載到容器內的 /code(target:)。

counter-vol 捲應該是已存在的,或者是在檔案下方的 volumes 一級 key 中定義的。

綜上,Docker Compose 會呼叫 Docker 來為 web-fe 服務部署一個獨立的容器。該容器基於與 Compose 檔案位於同一目錄下的 Dockerfile 構建的映象。

基於該映象啟動的容器會執行 app.py 作為其主程式,將 5000 埠暴露給宿主機,連線到 counter-net 網路上,並掛載一個捲到/code。

從技術上講,本例並不需要設定 command: python app.py。因為映象的 Dockerfile 已經將 python app.py 定義為了預設的啟動程式。

但是,本例主要是為了展示其如何執行,因此也可用於覆蓋 Dockerfile 中設定的 CMD 指令。

redis 服務的定義相對比較簡單。

6) image

redis:alpine 使得 Docker 可以基於 redis:alpine 映象啟動一個獨立的名為 redis 的容器。

這個映象會被從 Docker Hub 上拉取下來。

7) networks

設定 redis 容器連線到 counter-net 網路。

由於兩個服務都連線到 counter-net 網路,因此它們可以通過名稱解析到對方的地址。了解這一點很重要,本例中上層應用被設定為通過名稱與 Redis 服務通訊。

使用 Docker Compose 部署應用

下面將實際部署 Compose 檔案中定義的應用。可以從我的百度網路硬碟(https://pan.baidu.com/s/1Q0tcQnSqUQ06rfEdH_MBaw 提取碼: a55v)下載所需的檔案。

將程式碼下載到本地,並部署到新建立的名為 counter-app 的目錄中。

該目錄包含所需的所有檔案,可以作為構建上下文。

Docker Compose 會使用目錄名(counter-app)作為專案名稱,這一點在後續的操作中會看到,Docker Compose 會將所有的資源名稱中加上字首 counter-app_。

進入 counter-app 目錄中,檢查檔案是否存在。

$ cd counter-app
$ ls
app.py docker-compose.yml Dockerfile requirements.txt ...

簡要介紹這幾個檔案。
  • app.py:是應用程式程式碼(一個 Python Flask 應用)。
  • docker-compose.yml:是 Compose 檔案,其中定義了 Docker 如何部署應用。
  • Dockerfile:定義了如何構建 web-fe 服務所使用的映象。
  • requirements.txt:列出了應用所依賴的 Python 包。

app.py 顯然是應用的核心檔案,而 docker-compose.yml 檔案將應用的所有元件組織起來。

下面使用 Docker Compose 將應用啟動起來。以下所有的命令都是執行在剛才建立的 counter-app 目錄下的。

$ docker-compose up &

[1] 1635
Creating network "counterapp_counter-net" with the default driver
Creating volume "counterapp_counter-vol" with default driver
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
1160f4abea84: Pull complete
a8c53d69ca3a: Pull complete
<Snip>
web-fe_1 | * Debugger PIN: 313-791-729

啟動應用將花費幾秒鐘時間,其輸出也非常詳盡。下面我們來講解一下 docker-compose 命令。

常用的啟動一個 Compose 應用(通過 Compose 檔案定義的多容器應用稱為“Compose 應用”)的方式就是 docker-compose up 命令。

它會構建所需的映象,建立網路和卷,並啟動容器。

預設情況下,docker-compose up 會查詢名為 docker-compose.yml 或 docker-compose.yaml 的 Compose 檔案。

如果 Compose 檔案是其他檔名,則需要通過 -f 引數來指定。

如下命令會基於名為 prod-equus-bass.yml 的 Compose 檔案部署應用。

$ docker-compose -f prod-equus-bass.yml up

使用 -d 引數在後台啟動應用也是常見的用法,程式碼如下。

docker-compose up -d

--OR--

docker-compose -f prod-equus-bass.yml up -d

前面的範例命令在前台啟動應用(沒有使用 -d 引數),但是使用了 & 將終端視窗返回。

這種用法不太正規,所有的紀錄檔還是會直接輸出到我們後續可能會用的終端視窗上。

這樣應用就構建並啟動起來了,可以直接使用 docker 命令來檢視 Docker Compose 建立的映象、容器、網路和捲。

$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
counterapp_web-fe latest 96..6ff9e 3 minutes ago 95.9MB
python 3.4-alpine 01..17a02 2 weeks ago 85.5MB
redis alpine ed..c83de 5 weeks ago 26.9MB

可以看到有 3 個在部署過程中構建或拉取的映象。

counterapp_web-fe:latest 映象源自 docker-compose.yml 檔案中的 build: . 指令。

該指令讓 Docker 基於當前目錄下的 Dockerfile 來構建一個新的映象。

該映象基於 python:3.4-alpine 構建,其中包含 Python Flask Web 應用的程式程式碼。更多資訊可以通過檢視 Dockerfile 的內容進行了解。
  • FROM python:3.4-alpine << 基礎映象
  • ADD . /code << 將app複製到映象中
  • WORKDIR /code << 設定工作目錄
  • RUN pip install -r requirements.txt << 安裝依賴
  • CMD ["python", "app.py"] << 設定預設啟動命令

為了方便理解,每一行都新增了注釋。部署時要刪除掉。

請注意,Docker Compose 會將專案名稱(counter-app)和 Compose 檔案中定義的資源名稱(web-fe)連起來,作為新構建的映象的名稱。

Docker Compose 部署的所有資源的名稱都會遵循這一規範。

由於 Compose 檔案的 .Services.redis 項中指定了 image: "redis:alpine",因此會從 Docker Hub 拉取 redis:alpine 映象。

如下命令列出了兩個容器。每個容器的名稱都以專案名稱(所在目錄名稱)為字首。此外,它們還都以一個數位為字尾用於標識容器範例序號,因為 Docker Compose 允許擴縮容。

$ docker container ls
ID COMMAND STATUS PORTS NAMES
12.. "python app.py" Up 2 min 0.0.0.0:5000->5000/tcp counterapp_web-fe_1
57.. "docker-entry.." Up 2 min 6379/tcp counterapp_redis_1

counterapp_web-fe 容器中執行的是應用的 Web 前端。其中執行的是 app.py,並且被對映到了 Docker 主機的 5000 埠,稍後會進行連線。

如下的網路和卷列表顯示了名為 counterapp_counter-net 的網路和名為 counterapp_counter-vol 的卷。

$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1bd949995471 bridge bridge local
40df784e00fe counterapp_counter-net bridge local
f2199f3cf275 host host local
67c31a035a3c none null local

$ docker volume ls
DRIVER VOLUME NAME
<Snip>
local counterapp_counter-vol

應用部署成功後,讀者可以用 Docker 主機的瀏覽器連線 5000 埠來檢視應用的執行效果,如下圖所示。

應用部署成功的運行效果