誰說docker-compose不能水平擴展容器、服務多實例?

雖說我已經從docker-compose走上了docker swarm的邪門歪道,目前被迫走在k8s這條康莊大道, 但是我還是喜歡docker-compose簡潔有效的部署方式。

曾其何時

docker-compose非常適合開發、測試、快速驗證原型,這個小工具讓單機部署容器變得簡潔、高效。正如我在《docker-compose,docker-stack前世今生》裡講,所有人都認為docker-compose是單機部署多容器的瑞士軍刀,沒有docker stack由deploy配置節體現的生產特性(多實例、滾動部署、故障重啟、負載均衡)。

誰說docker-compose不能水平擴展容器、服務多實例?

最近我發現我錯了:docker-compose還是具備服務多實例的能力的。

在docker-compose -h中發現了一個scale參數,這是個啥?docker-compose還能水平擴展,實現多容器?docker-compose定義的容器映射的主機端口不會衝突嗎?

號主精心分析,才找到一個完備的理論來支持scale參數的合理性。在此文中,我們將演示一個示例,說明如何使用Docker Compose運行服務的多實例

<code>

version

:

"3"

services

:

webapp

:

image

:

"luksa/kubia"

depends_on

: - db

ports

: -

"8080:8080"

# 主機

Port

: 容器暴露Port/<code>

在此文件中,我們定義了一個webapp服務(nodejs程序在8080端口監聽)為webapp容器定義了端口映射:從容器8080端口映射到主機的8080端口,這樣我們可以在主機上使用http://localhost:8080URL訪問服務器。

Docker Compose --scale flag

當我們運行docker-compose up -h命令時, 其中--scale選項顯示為服務指定多實例

<code> 
                               `scale` setting 

in

the Compose file

if

present./<code>

很顯然,使用目前的DockerCompose配置運行docker-compose up --scale webapp=3將導致failed: port is already allocated錯誤:

問題在於,我們試圖運行webapp服務的三個實例,並將它們全部映射到主機同一端口,而「主機的8080端口只能綁定給一個容器」

解決錯誤的一種方法是將Docker Compose文件中的端口映射更改為- "8080", 這會將容器的端口8080暴露給主機上的臨時未分配端口。

誰說docker-compose不能水平擴展容器、服務多實例?

這個操作延伸出另一個問題:在啟動容器之前,我們將不知道用於訪問服務的端口。要列出端口映射,請在運行docker-compose up --scale webapp=3之後運行docker-compose ps來查看容器:

<code>   

Name

Command

State

Ports

-------------------------------------------------------------

test_webapp_1

node

app.js

Up

0.0

.0

.0

:32828->8080/tcp

test_webapp_2

node

app.js

Up

0.0

.0

.0

:32830->8080/tcp

test_webapp_3

node

app.js

Up

0.0

.0

.0

:32829->8080/tcp

/<code>

添加負載均衡器

為了能夠在不知道特定容器的端口的情況下訪問webapp服務,並使用負載均衡機制將請求分發到容器,我們需要在容器堆棧中添加負載均衡器。

在此示例中,將使用nginx作為負載均衡器:來完成對外接收、對內轉發。

誰說docker-compose不能水平擴展容器、服務多實例?

在與docker-compose.yml文件相同的目錄中創建以下nginx.conf文件,代理&轉發請求

<code>

user

nginx;

events

{

worker_connections

1000

; }

http

{

server

{

listen

80

;

location

/ {

proxy_pass

http://webapp:8080; } } }/<code>

這將配置nginx將請求從主機端口80轉發到 http://webapp:8080。然後將由Docker’s embedded DNS解決尋址:該DNS服務器使用輪詢實現來根據服務名稱解析DNS請求,並將其分發給Docker容器。

由於nginx服務負責對外接收請求、對內轉發,因此webapp服務可不直接對外暴露。實際上我們可以從Docker Compose文件中刪除webapp端口映射配置,而僅將端口8080通知給鏈接的nginx服務。

<code>

version

:

"3"

services

:

webapp

:

image

:

"luksa/kubia"

nginx

:

image

:

nginx

:latest

volumes

: -

type

: bind

source

: /home/root/test/nginx.conf

target

: /etc/nginx/nginx.conf

depends_on

: - webapp

ports

: -

"80:80"

/<code>

通過此配置,我們現在可以利用Docker Compose工具的scale水平擴展、實現服務多實例。docker-compose up -d --scale webapp=3

<code>

CONTAINER

ID

IMAGE

COMMAND

CREATED

STATUS

PORTS

NAMES

05b024964274

luksa/kubia

"node app.js"

15

minutes

ago

Up

15

minutes

test_webapp_1

2fb56a22810a

luksa/kubia

"node app.js"

15

minutes

ago

Up

15

minutes

test_webapp_3

84041c727b6e

luksa/kubia

"node app.js"

15

minutes

ago

Up

15

minutes

test_webapp_2

3882beae8b56

nginx:latest

"nginx -g 'daemon of…"

15

minutes

ago

Up

15

minutes

0.0

.0

.0

:80->80/tcp

test_nginx_1

/<code>

總結輸出

  • docker-compose利用Docker引擎內嵌DNS,提煉出水平擴展容器、服務多實例的能力 (用一個代理就能應用這個能力)
  • Docker引擎內嵌DNS也是docker-compose利用服務名發現其他容器的關鍵

在需要測試具備水平擴展能力的web服務時,docker-compose up -d --scale 提供了一種快速、簡便的途徑。


分享到:


相關文章: