在上一part《把AspDotNetCoreMvc程序运行在Docker上-part4:实现负载均衡》中,我们通过几个比较复杂的步骤在docker平台上实现了对网站程序的负载均衡,配置步骤比较多。如果实际的站点较少,整个架构比较简单的情况下,这么做没有太大问题,如果应用较多的时候,会容易出错。那么这时候我们可能会想到自己写一些脚本来实现自动化,当然这是可行的。然而docker已为我们着想好,给我们提供了docker-compose功能,利用它我们可以实现对复杂应用的管理,包括容器、网络、volume等。

准备工作

先删除上一part我们创建的容器、网络和volume(不用觉得可惜,后面用上docker-compose可以轻易实现)

docker rm -f $(docker ps -aq)
docker network rm $(docker network ls -q)
docker volume rm $(docker volume ls -q)

安装docker-compose

在linux平台上需要手动执行如下命令安装

sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

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

(最新版本可以从这里https://github.com/docker/compose/releases获知)

安装之后,运行docker-compose –version检查是否成功

准备MVC站点程序

可以从这里下载

https://github.com/shenba2014/AspDotNetCoreMvcDocker/tree/docker-compose

然后执行

dotnet restore

bower install

一会用到这个站点程序创建一个镜像以及对应的容器

创建docker-compose配置文件

新建docker-compose.yml文件(在docker所在宿主服务器直接创建也可以)

version: "3"

volumes:

productdata:

networks:

frontend:

backend:

services:

mysql:

image: "mysql:8.0.0"

volumes:

- productdata:/var/lib/mysql

networks:

- backend

environment:

- MYSQL_ROOT_PASSWORD=password

- bind-address=0.0.0.0

这个文件足够的自描述,把上一节我们用到的内容都作出了定义,还是简单解释一下

version:版本号,目前最新的是3.0

volumes:之前的《把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器》里面有介绍过,用于在docker容器外存储数据

networks:在上一part说过,定义了两个网络:frontend和backend

services:定义将要用到的容器,这里只定义了mysql容器,这些参数跟使用docker create命令创建容器的参数一致。具体可参考上一part《把AspDotNetCoreMvc程序运行在Docker上-part4:实现负载均衡》。

docker-compose执行构建

 

执行如下构建命令

docker-compose –f docker-compose.yml build

输出结果

WARNING: Some networks were defined but are not used by any service: frontend, backend

mysql uses an image, skipping

这里的警告信息意思是我们定义的两个网络还没被任何服务组件使用。

运行了这个命令只是定义,并没有真正的创建volume、network或者容器。

接下来运行docker-compose.yml定义的应用,才会真正的创建内容

docker-compose -f docker-compose.yml up

可以理解为启动刚才我们定义的组件,然后会有一堆的输出内容

WARNING: Some networks were defined but are not used by any service: frontend
Creating network "dockertemp_backend" with the default driver
Creating dockertemp_mysql_1 ...
Creating dockertemp_mysql_1 ... done
Attaching to dockertemp_mysql_1

很明显docker-compose在依次创建network、容器实例。

名字看起来比较奇怪,都带了dockertemp_前缀。因为docker-compose.yml所在的目录命令是dockertemp,所以最终提供的名称有这个前缀,避免了命名冲突。

而为什么是mysql_1,带有_1后缀,后续会用到,这里是为了用于横向扩展做集群的时候用到。

进一步通过如下命令验证volume、network和容器是创建成功的

docker volume ls

docker netowrk ls

docker ps –a

使用docker-compose –f docker-compose.yml down -v可删除network、容器和volume,全自动完成(保存在volume的数据也会删除,如果要保留volume把-v去掉即可)。

现在docker-compose文件里只定义了一个service,接下来继续添加MVC站点容器以及负载均衡容器。

添加MVC站点容器以及负载均衡容器

首先从以下路径下载代码

https://github.com/shenba2014/AspDotNetCoreMvcDocker/tree/docker-compose

这个分支跟之前的不一样,增加了对支持docker-compose的一些改动。

代码拉下来之后执行如下命令

dotnet restore

dotnet publish --framework netcoreapp2.0 --configuration Release --output dist

cd dist | npm install

dist文件夹里的内容就是我们后续要用到的MVC站点内容。

从源代码查看完整的docker和docker-compose.yml文件

先看看docker文件的更新内容

FROM microsoft/aspnetcore:2.0.0

COPY dist /app

COPY dist/node_modules/wait-for-it.sh/bin/wait-for-it /app/wait-for-it.sh

RUN chmod +x /app/wait-for-it.sh

WORKDIR /app

EXPOSE 80/tcp

ENV WAITHOST=mysql WAITPORT=3306

ENTRYPOINT ./wait-for-it.sh $WAITHOST:$WAITPORT --timeout=0 && exec dotnet AspDotNetCoreMvcDocker.dll

红色部分是新增的内容,这里拷贝了一个wait-for-it的脚本到了容器内部,并且在ENTRYPOINT里设置了等待mysql启动之后再启动MVC容器。

简单解释一下,因为使用了docker-compose启动容器之后,我们不能确保mysql容器服务是否已正常启动,如果mysql没有启动,那么站点也没法使用。所以容器必须在mysql容器启动之后执行,这里就引入了一个npm的package:wait-for-it,这个只能在Linux平台下使用。

接下打开完整的docker-compose.yml文件,这里只列出新增的service(完整文件内容不列出,可查看代码)

dbinit:
     build:
       context: .
       dockerfile: Dockerfile
     networks:
       - backend
     environment:
       - INITDB=true
       - DBHOST=mysql
       - DBPASSWORD=password
     depends_on:
       - mysql
   mvc:
     build:
       context: .
       dockerfile: Dockerfile
     networks:
       - backend
       - frontend
     environment:
       - DBHOST=mysql
       - DBPASSWORD=password
     depends_on:
       - mysql

loadbalancer:
     image: dockercloud/haproxy
     ports:
       - 3000:80
     links:
       - mvc
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
     networks:
       - frontend

这里才原来的基础上增加了dbinit,mvc和loadbalancer三个service,分别描述如下

dbinit:主要是用于初始化数据库,这里是把它当做一个容器来执行,实际在完成了数据库初始化自后就会退出。

mvc:这里就是MVC站点的容器,跟我们上一part定义MVC的参数类似。主要是增加了depends_on参数,指明mvc容器依赖于mysql容器。

loadbalancer:顾名思义,就是负载均衡服务器容器,通过links参数指向了其代理的站点是MVC容器,并且通过volumes参数配置了/var/run/docker.sock文件映射为主机的文件,具体作用不描述,主要是为了在扩容的时候通知到负载均衡服务器。

启动站点

把上一步的dist文件夹docker、docker-compose.yml文件拷贝到docker服务器(如果开发机就是docker服务器可以忽略),然后在这些文件的所在目录执行如下命令

docker-compose -f docker-compose.yml build

这个命令之前提到过,类似于编译,检查是否有错误,实际上不会创建容器

接着运行

docker-compose -f docker-compose.yml up dbinit

开启dbinit容器,之前我们提到,这个dbinit也是个MVC容器,但是只是负责数据库初始化,完成之后会自动关闭,这是这个命令的output

Creating network "dockertemp_frontend" with the default driver
Creating network "dockertemp_backend" with the default driver
Creating volume "dockertemp_productdata" with default driver
Creating dockertemp_mysql_1 ...
Creating dockertemp_mysql_1 ... done
Creating dockertemp_dbinit_1 ...
Creating dockertemp_dbinit_1 ... done
Attaching to dockertemp_dbinit_1
dbinit_1        | wait-for-it.sh: waiting for mysql:3306 without a timeout
dbinit_1        | wait-for-it.sh: mysql:3306 is available after 16 seconds
dbinit_1        | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
dbinit_1        |       No XML encryptor configured. Key {1b1e827d-d1d0-4d0c-a92d-8632ee0791ef} may be persisted to storage in unencrypted form.
dbinit_1        | Preparing Database...
dbinit_1        | Applying Migrations...
dbinit_1        | Creating Seed Data...
dbinit_1        | Database Preparation Complete
dockertemp_dbinit_1 exited with code 0

从output可以看到有一个等待mysql启动的步骤,等待了16秒。然后是执行了数据库初始化,创建表以及插入一些种子数据。最后一个行输出表明该容器自动退出。

好了数据库准备好之后,就可以启动MVC和负载均衡容器,还是通过docker-compose命令

docker-compose -f docker-compose.yml up mvc loadbalancer

执行完成之后,就可以访问我们的MVC站点了,这里我们只启用了一个MVC站点,试试从浏览器打开http://192.168.115.136:3000/,一切正常的话就能看到网站和数据了

做了这么多步骤,就是为了实现负载均衡,接下来一行命令让他立即扩容到4个MVC站点

docker-compose -f docker-compose.yml scale mvc=4

秒级扩容就是这简单,不信的话运行docker ps看看下面是不是有4个MVC站点容器,还不相信的话手动多刷几次http://192.168.115.136:3000/,会发现from server的值是会发生变化的。

好了,如果这时候要实现优雅降级怎么办,没问题,还是一行命令

docker-compose -f docker-compose.yml scale mvc=1

系统自动移除了三个MVC站点容器,当然也是秒级的。

最后关闭所有服务的命令是

docker-compose -f docker-compose.yml stop

写了这么多就是为了描述docker-compose的使用方法,对比上一part,实际上就是把之前的工作都放到一个批处理文件里执行,将所有服务当做一个整体来管理,同时也提供了遍历站点扩容和降级的方式。看起来已经很方便了,当然还没完,后续还有大招。

把AspDotNetCoreMvc程序运行在Docker上-part5:使用docker-compose的更多相关文章

  1. 把AspDotNetCoreMvc程序运行在Docker上-part4:实现负载均衡

    在上一part<把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器>,我们利用MySql容器和Volume实现了真正意义上的数据存储.整个结构非常简 ...

  2. 把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器

    接上一篇博文<把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像>,这次我们看看如何使用docker存储数据. 背景 之前的示例都只有一个网站应用 ...

  3. 把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像

    在上一个part<把AspDotNetCoreMvc程序运行在Docker上-part1>,已经将成功将aspdotnetcore程序运行在两个不同的容器中,目前两个容器的内容完全相同,只 ...

  4. 把AspDotNetCoreMvc程序运行在Docker上-part1

    接<基于ASP.Net Core学习Docker技术第一步:在CentOS7安装Docker平台>这个博文,在搭建完成Docker平台之后,可以开始让aspdotnetcore程序运行在d ...

  5. docker 上传到docker hub 采坑

    前面是仓库名称 后面可以命名img名字 docker push gaodi2345/wj:docker_gui

  6. 小程序运行时如何助力传统APP转型?

    小程序和H5或者RN有什么区别?优越性在哪里? 长期以来,移动互联网界一直在寻找一种既能获得Native原生的体验,又可以低门槛快速开发的技术.在这个过程中出现了很多尝试,例如React Native ...

  7. 在OSX和Windows版本Docker上运行GUI程序

    看到很多人在Docker问题区讨论:如何在OS X和Windows的Docker上运行GUI程序, 随手记录几个参考资料: https://github.com/docker/docker/issue ...

  8. 在docker上运行.net core程序

    一.安装docker及镜像 1.在centos上安装docker,命令如下: # yum install docker 2.让docker随机启动: # service docker start# c ...

  9. 在 Docker 上运行一个 RESTful 风格的微服务

    tags: Microservice Restful Docker Author: Andy Ai Weibo:NinetyH GitHub: https://github.com/aiyanbo/d ...

随机推荐

  1. KVM NAT网络模式配置

    NAT方式原理 NAT方式是kvm安装后的默认方式.它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机. 检查当前的网络设置: #virsh net-list --all N ...

  2. javascript快速排序的思考

    还记得三个月前,学习过快速排序,示例所讲的python快速排序十分易于理解,然而网上学习的c#的快速排序当时就懵逼的,现在已经全忘了,大概记得个思路 在学习完了一些高级的js方法后,今天用js模拟了p ...

  3. 使用nexus来搭建Nuget私服

    近期在搭建nuget私服.选择nexus这个产品.nexus支持npm,.nuget等,功能比较强大. 前言 博主使用centos7.5来搭建nexus,遇到了不少的问题.最后还是搞定了. 1:下载n ...

  4. winform中控件的简单数据绑定

    是因为在学习组件开发过程中有个Bindable的属性,不明白意义,然后才接触到winform的数据绑定,想着先把数据绑定这块看一下,然后去测试下是否Bindable属性设为false,就不能绑定该属性 ...

  5. (C#)计算1-2+3-4+.....+m

    方法一: public static int Sum(int m) { int sum = 0; bool bol = true; for (int i=1;i<=m;i++) { if (bo ...

  6. Restframework 分页器 Pagnation 组件实例-5

    分页逻辑 from rest_framework.pagination import PageNumberPagination class BookView(APIView): # authentic ...

  7. Android之自定义控件

    开发自定义控件的步骤: 1.了解View的工作原理  2. 编写继承自View的子类 3. 为自定义View类增加属性  4. 绘制控件  5. 响应用户消息  6 .自定义回调函数    一.Vie ...

  8. 关于MySQL连接抛出Authentication Failed错误分析

    [问题描述] 在应用端,偶尔看到有如下报错: Authentication to host 'xxxx' for user 'yyyy' using method 'mysql_native_pass ...

  9. jQuery.extend 函数

    jQuery.extend 函数详解 JQuery的extend扩展方法: Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,在此,我们一起去了解了解. 一.J ...

  10. day 47 Django 4的简单应用 创建简单的图书管理 (单表的增删改查)

    前情提要  Django  已经学了大半.. 很多东西已经能够使用在生产环境当中 一:模糊查询 二:单表删除 三:单表修改 四:图书管理 图书管理操作 视图结构 A:路由层 A :配置路由文件 参数解 ...