利用 docker compose.yml文件 实现负载均衡

本文介绍如何使用Docker平台定义、运行和扩展服务,通过编写docker-compose.yml文件实现服务的负载均衡。涵盖镜像拉取、服务部署、资源限制、重启策略、端口映射及网络配置等内容。

docker中的服务

我们将扩展应用并启用负载均衡。在分布式应用中,应用的不同部分称为“服务”。例如,假设有一个视频共享网站,它可能提供用于在数据库中存储应用程序数据的服务、用于在用户上传一些内容后在后台进行视频转码的服务、用于前端的服务等。

服务实际上是“生产中的容器”。一项服务仅运行一个镜像,但它会编制镜像的运行方式 - 它应使用的端口、容器的多少个从节点应运行才能使服务的容量满足其需求等。扩展服务将更改运行该软件的容器实例数,并将多个计算资源分配给进程中的服务。

幸运的是,很容易使用 Docker 平台定义、运行和扩展服务 – 只需编写一个 docker-compose.yml 文件即可。

docker-compose.yml文件

docker-compose.yml是一个YAML文件,用于定义Docker容器在生产中的行为方式,编排应用以及其中服务的方式。

以下为docker-compose.yml文件的一个样例,通过将username/repository:tag替换为自己的镜像详细信息来更新此文件

version: "3"
services: 
  web:
    # 将 username/repo:tag 替换为您的名称和镜像详细信息
    # image: waldenz/imagesample:v1
    image: username/repository:tag
    deploy:
      replicas: 5
      resources: 
        limits:
          cpus: "0.1"
          #memory:50M
      restart_policy:
        condition: on-failure
    ports:
      - "1002:5003"
    networks:
      - webnet
networks:
  webnet:

yml文件解析:

1. 从waldenz/imagesample:v1镜像库中拉取镜像;

2. 将该镜像的五个实例作为服务web运行,并将每个实例限制为最多10%的cpu以及50M RAM;

3. restart_policy: 重启策略, 如果某个容器发生故障,立即重启容器;

4. 将主机上的1002端口映射到web容器中的5003;

5. 指示web容器通过负载均衡的网络 webnet 共享端口1002;

6. 使用默认设置定义 webnet网络(此为负载均衡的overlay网络)

运行新的负载均衡的应用

首先需要运行一下命令,才可以使用 docker stack deploy 

docker swarm init

为应用指定一个名称。例子中取名为 myapp0416

docker stack deploy -c docker-compose.yml myappname

 查看启动的该应用下的所有容器的列表,

docker stack ps myappname

您可以多次在一行中运行 curl http://localhost:1002,也可以在浏览器中转至该 URL 并多次点击“刷新”。无论采用哪种方式,您都将看到容器 ID 更改,从而说明负载均衡;借助每项请求,将以循环方式选择五个从节点之一做出响应。 

扩展应用

更改docker-compose.yml中的replicas值,保存更改并重新运行 docker stack deploy 命令来扩展应用。如下图

docker将执行原地更新,而无需先清除技术栈或终止任何容器。将之前文件中 replicas 由5改为7,重新运行 docker stack deploy   可以发现节点67是刚启动的。

另一种方法扩展应用中的服务

水平扩展副本,用 docker service scale命令。

举例: 服务名为myapp_web,即myappname应用下的web服务,扩展为5个副本,相当于修改yml文件中的replicas个数。

docker service scale myappname_web=5

清除应用和swarm

docker stack rm myappname

相关命令

docker stack ls                    #列出docker主机上所有正在运行的应用

docker stack deploy -c  <composefile> <appname> #运行指定的compose文件,启动应用appname

docker stack services <appname>  #列出与应用关联的服务

docker stack ps <appname>      #列出与应用关联的正在运行的容器

docker stack rm <appname>     #清除应用

<think>我们只需要移除文件,使用rm命令即可。注意:在shell脚本中,变量名使用需要加上$符号,但这里文件名是变量$dockercompose.yml,所以直接使用该变量。 但是,请注意变量名通常使用小写字母,这里用户使用了$dockercompose.yml,我们假设这个变量已经定义并且包含正确的文件名(包括路径,如果需要)。 如果这个变量没有定义,那么脚本会尝试删除一个名为".yml"的文件(因为$dockercompose会被当作变量,如果未定义则替换为空)。所以,我们需要确保变量已定义。 为了安全,我们可以先检查文件是否存在,然后再删除。 修改建议:在脚本中,我们最好先检查文件是否存在,然后执行删除操作,并给出相应的提示。 代码示例: ```bash # 假设变量dockercompose.yml存储了要删除的文件路径 if [ -f "$dockercompose.yml" ]; then rm "$dockercompose.yml" echo "File $dockercompose.yml has been removed." else echo "File $dockercompose.yml does not exist." >&2 exit 1 fi ``` 但是,注意用户给出的变量名是`$dockercompose.yml`,这看起来有点奇怪,因为通常变量名中不会包含点(.)。所以,我们可能需要确认这个变量名是否正确。如果用户的意思是变量名为`dockercompose`,而文件名为`docker-compose.yml`,那么这里可能是用户写错了。 根据问题描述,用户说“移除文件$dockercompose.yml”,我们可以理解为有一个变量名为`dockercompose`,它存储了一个字符串,这个字符串是文件名(比如“docker-compose.yml”),然后我们删除这个文件。那么变量名应该是`dockercompose`,而不是`dockercompose.yml`。因为`.yml`是变量的一部分,这会导致shell将整个字符串解析为变量`dockercompose`的属性(但实际上shell变量没有属性,所以会出错)。 所以,我怀疑用户可能是想表达:有一个变量`dockercompose`,它存储了文件名(例如值为"docker-compose.yml"),然后我们删除这个文件。那么正确的变量引用应该是`$dockercompose`,而不是`$dockercompose.yml`。 因此,我们假设用户定义的变量名是`dockercompose`,那么删除文件的代码应该是: ```bash rm "$dockercompose" ``` 但是,如果用户确实定义了一个变量名为`dockercompose.yml`(虽然不常见,但shell允许变量名包含点),那么我们可以使用: ```bash rm "${dockercompose.yml}" ``` 由于问题中没有明确,我们按照常见的做法,假设变量名为`dockercompose`,文件扩展名包含在变量值中。 所以,我建议用户检查变量名。为了安全,我们提供两种可能: 情况1:变量名为`dockercompose`,其值为文件名(如"docker-compose.yml") 情况2:变量名就是`dockercompose.yml`,其值为文件名(但这种情况很少见) 如果用户不确定,我们可以先输出变量的值,然后再删除。 但根据问题,用户要求的是“移除文件$dockercompose.yml”,我们按照字面意思,变量名就是`dockercompose.yml`,那么代码应该写为: ```bash # 使用大括号来明确变量名 file_to_remove="${dockercompose.yml}" if [ -f "$file_to_remove" ]; then rm "$file_to_remove" echo "File $file_to_remove has been removed." else echo "File $file_to_remove does not exist." >&2 exit 1 fi ``` 但是,更可能的情况是用户打错了,应该是变量名`dockercompose`,然后文件yml文件,所以文件名是`${dockercompose}.yml`?还是变量`dockercompose`已经包含了完整的文件名? 我重新阅读问题:“我想在shell脚本中移除文件$dockercompose.yml”,这里`$dockercompose.yml`应该被理解为一个变量,变量名是`dockercompose.yml`。但是,在shell中变量名可以包含点,所以技术上可行。 为了减少歧义,我们可以建议用户使用更标准的变量名(如`docker_compose_file`),并在定义时包含完整的文件名。 不过,我们按照用户的要求,直接使用`$dockercompose.yml`作为变量名,但要注意在shell中使用大括号来避免歧义。 最终代码(针对变量名为`dockercompose.yml`): ```bash # 检查变量是否设置 if [ -z "${dockercompose.yml}" ]; then echo "Error: Variable dockercompose.yml is not set." >&2 exit 1 fi if [ -f "${dockercompose.yml}" ]; then rm "${dockercompose.yml}" echo "File ${dockercompose.yml} has been removed." else echo "File ${dockercompose.yml} does not exist." >&2 exit 1 fi ``` 但是,我们也可以用一个临时变量来简化: ```bash file="${dockercompose.yml}" if [ -f "$file" ]; then rm "$file" echo "File $file has been removed." else echo "File $file does not exist." >&2 exit 1 fi ``` 这样更清晰。 考虑到用户可能误写变量名,我们更倾向于认为变量名应该是`dockercompose`(没有点),那么代码为: ```bash file="$dockercompose" # 假设变量名是dockercompose,它包含了完整的文件名 if [ -f "$file" ]; then rm "$file" echo "File $file has been removed." else echo "File $file does not exist." >&2 exit 1 fi ``` 由于用户的问题中明确写了`$dockercompose.yml`,所以我们还是按照用户写的变量名来处理。但是,如果用户实际上是想表达变量名是`dockercompose`,而文件后缀是`.yml`,那么应该是`${dockercompose}.yml`,即: ```bash file="$dockercompose.yml" ``` 但是,这样又要求变量`dockercompose`的值不包含后缀,例如变量值为"docker-compose",然后加上后缀".yml"。 综上所述,用户的问题存在歧义。我们无法确定,因此需要用户澄清。 但是,在无法澄清的情况下,我们按照用户字面意思:有一个变量名为`dockercompose.yml`,其值就是完整的文件名(包括路径,如果需要)。我们使用大括号引用这个变量。 因此,最终代码: ```bash # 删除文件 $dockercompose.yml (变量名为dockercompose.yml) file="${dockercompose.yml}" if [ -f "$file" ]; then rm "$file" echo "Removed file: $file" else echo "ERROR: File '$file' not found or not a regular file" >&2 exit 1 fi ``` 注意:如果变量未设置,那么`${dockercompose.yml}`会被扩展为空字符串,这会导致`-f`检查当前目录下一个名为空字符串的文件,显然不存在,所以会报错。因此,我们可以先检查变量是否设置。 改进版: ```bash # 检查变量 dockercompose.yml 是否设置且非空 if [ -z "${dockercompose.yml+set}" ]; then echo "ERROR: Variable 'dockercompose.yml' is not set." >&2 exit 1 fi file="${dockercompose.yml}" if [ -f "$file" ]; then rm "$file" echo "Removed file: $file" else echo "ERROR: File '$file' not found or not a regular file" >&2 exit 1 fi ``` 但是,更简单的做法是直接使用变量,并检查文件存在性。如果变量为空,那么`-f`会检查空字符串,文件不存在,所以会进入else分支,报错文件不存在。这样也可以,但是错误信息会显示文件名为空,不太友好。 因此,我们分开检查: ```bash file="${dockercompose.yml}" # 检查文件名为非空 if [ -z "$file" ]; then echo "ERROR: File name is empty." >&2 exit 1 fi if [ -f "$file" ]; then rm "$file" echo "Removed file: $file" else echo "ERROR: File '$file' not found or not a regular file" >&2 exit 1 fi ``` 这样更安全。 综上所述,我们提供以下脚本: </think> 以下是在 Shell 脚本中安全移除 `$dockercompose.yml` 文件的代码实现及解释: ```bash #!/bin/bash # 定义要操作的文件变量 dockercompose_yml="docker-compose.yml" # 检查文件是否存在 if [ ! -f "$dockercompose_yml" ]; then echo "ERROR: File $dockercompose_yml does not exist" >&2 exit 1 fi # 移除文件并检查结果 if rm -f "$dockercompose_yml"; then echo "Successfully removed $dockercompose_yml" else echo "ERROR: Failed to remove $dockercompose_yml (check permissions)" >&2 exit 1 fi ``` ### 关键点说明: 1. **安全移除流程**: - 先检查文件是否存在(`-f` 测试) - 使用 `rm -f` 强制删除(避免交互提示) - 通过 `rm` 命令的**返回值判断操作结果**(0=成功,非0=失败) 2. **变量命名优化**: - 使用下划线命名法 `dockercompose_yml`(更符合 Shell 变量规范) - 避免使用 `.` 在变量名中(原 `$dockercompose.yml` 会被解析为变量属性) 3. **错误处理**: - 文件不存在时返回错误码 1 - 删除失败时提示权限问题(常见失败原因) - 所有错误信息重定向到 STDERR(`>&2`) > 声明式配置(如 Docker Compose)通过 YAML 文件定义服务依赖关系,相比命令式操作更易维护和版本控制[^1]。删除配置文件时需确保相关服务已停止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值