谁说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 提供了一种快速、简便的途径。


分享到:


相關文章: