在Docker swarm中使用compose

本文介绍了如何在Docker Swarm集群中使用Compose。在Swarm中构建image需将其上传至镜像仓库以供多节点使用。面对多依赖服务,如foo依赖于bar和baz,需要手动设置部署约束以确保它们在同一节点。此外,解决主机端口冲突可通过命名volume或清理遗留状态。最后,讨论了自动调度与手动调度策略在Compose中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文介绍如何在单独Docker环境下使用compose,本文介绍如何在swarm集群中使用compose。

限制

image构建

在swarm中构建image与单机版一样,使用相同的命令。但是构建完成的image只存在于当前主机,如果运行镜像的多个实例,并且这些实例分布在集群中的不同节点上,那么就需要分发构建好的镜像,一个节点不会共享另一个节点上已经构建好的镜像。解决办法为首先在某个节点上构建image,然后再将image上传到镜像仓库,然后在compose的定义文件中从仓库引用此镜像。救命如下:

$ docker build -t myusername/web .
$ docker push myusername/web

$ cat docker-compose.yml
web:
  image: myusername/web

$ docker-compose up -d
$ docker-compose scale web=3

多依赖

如果某个应用有多个服务组成,如下例:

version: "2"
services:
  foo:
    image: foo
    volumes_from: ["bar"]
    network_mode: "service:baz"
  bar:
    image: bar
  baz:
    image: baz

上例中,foo的volume依赖于bar,foo的网络与baz共享,实例这三个服务必需部署在同一个节点上才行,也就是foo明确依赖于bar与baz。在部署时的实际调度中,如果依次先部署foo,那么系统会发现它依赖于bar与baz,然后系统在同一个节点上就会先部署bar与baz,然后再部署foo。但实际上,swarm并不是这样调度的,它是并发的,有可能先部署bar与baz,这两个服务都没有指出依赖谁,因此可能部署到集群中的任何节点上,并且是不同的节点,这个时候再部署foo时就会出问题,因为它依赖的东西分布在不同的节点上。解决的一种方案是手动为部署增加约束,如:

version: "2"
services:
  foo:
    image: foo
    volumes_from: ["bar"]
    network_mode: "service:baz"
    environment:
      - "constraint:node==node-1"
  bar:
    image: bar
    environment:
      - "constraint:node==node-1"
  baz:
    image: baz
    environment:
      - "constraint:node==node-1"

以上强制要求所有三个服务必需部署在节点node-1上。这种方式实际上不太灵活,因为强制指定了节点名称。一种方法是通过标签,将目标节点打上标签,然后再约束中指定标签名称,这需要一个选择器,k8s是这样做的,compose可能也有这种功能。

主机端口与容器重建 (Host ports and recreating containers)

这一段实在看不明白是什么意思,一会volume一会port,不明白到底是什么原因引起冲突。原文如下:

If a service maps a port from the host, such as 80:8000, then you may get an error like this when running docker-compose up on it after the first time:

docker: Error response from daemon: unable to find a node that satisfies
container==6ab2dfe36615ae786ef3fc35d641a260e3ea9663d6e69c5b70ce0ca6cb373c02.

The usual cause of this error is that the container has a volume (defined either in its image or in the Compose file) without an explicit mapping, and so in order to preserve its data, Compose has directed Swarm to schedule the new container on the same node as the old container. This results in a port clash.

它下边提到的两个方法到是看明白了。一个是命名volume,代码如下:

version: "2"

services:
  web:
    build: .
    ports:
      - "80:8000"
    volumes:
      - web-logs:/var/log/web

volumes:
  web-logs:
    driver: custom-volume-driver

上例中,volume是有名字的,并且是某个存储系统单独提供的,不依赖于宿主机,容器实例部署在那里,它就跟到那里。有一个疑问就是多实例多volume的问题,假如运行5个实例,然后又调整到10个实例,那么这个volume怎么绑定呢?

第二方法是彻底清除上次运行产生的遗留,以免冲突,如下:

$ docker-compose stop web
$ docker-compose rm -f web
$ docker-compose up web

 自动调度
在上边例子里已经出现过,compose中服务的配置可能会影响调度,如:

  • network_mode: "service:..." and network_mode: "container:..." (andnet: "container:..." in the version 1 file format).

  • volumes_from

  • links

手动调度

# Schedule containers on a specific node
environment:
  - "constraint:node==node-1"

# Schedule containers on a node that has the 'storage' label set to 'ssd'
environment:
  - "constraint:storage==ssd"

# Schedule containers where the 'redis' image is already pulled
environment:
  - "affinity:image==redis"

实例上就是部署时的约束、亲各与反亲和等。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值