如何用docker consul 部署到服务器

consul集群 consul安装 consul部署 consul配置中心

    当今是容器的时代,不管是否基于微服务架构开发的系统都建议大家使用docker部署。linux+dokcer是最好的搭配,如果您只安装了windows,可以考虑安装linux虚拟机。Adnc 部署到服务器,需要先安装mysqlredisrabbitmqmongogdbskywalkingconsulnginx
    如何安装mysqlredisrabbitmqmongogdb请参考 如何快速跑起来,里面有详细介绍。
下面介绍如何 docker 安装 consul,skywalking,nginx

安装consul

consul是微服务的中转中心(注册中心/配置中心),最重要的组件。如果consul服务器挂了,系统也会奔溃。因为重要,所有我们必须要部署一个集群
consul分为server节点与client节点,server节点负责存储数据;client节点负责注册、发现、读写配置、健康监测。
如果直接在linux环境部署consul集群,配置很麻烦,使用docker虽简单了很多,但操作步骤还是很多的。

#拉取镜像
docker pull consul
#启动容器consul_server_1
docker run -d -p 8510:8500 --restart=always -v /root/data/consul/server1/data:/consul/data -v /root/data/consul/server1/config/:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_1 consul agent -server -bootstrap-expect=3 -ui -node=consul_server_1 -client='0.0.0.0' -data-dir /consul/data -config-dir /consul/config -datacenter=adnc_dc; 

-d 后台运行
-p 8510:8500 主机8510端口映射到容器8500端口。
-v 挂载文件,-v 参数可以出现多次,我们分别将data数据与config存放在主机。
-name=consul_server_1容器的名称,这里不要用重复的名称,要有一定规则。
-server 表示server节点
-bootstrap-expect=3:表示期望提供的SERVER节点数目,数目一达到,它就会被激活。我们设定是3个服务节点,部署consul集成server节点至少3个。
-ui 开启ui界面,部署成功后我们可以通过http://你的主机Ip:8510,访问这个节点的ui界面。
-node=consul_server_1 节点名字,与容器名称一样,方便运维。
-datacenter=adnc_dc 集群数据中心名称

#为了让其他两个server节点加入集群,首先获取一下consul_server_1的IP地址。
JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' consul_server_1)";
#启动容器consul_server_2并加入集群
docker run -d -p 8520:8500 --restart=always -v /root/data/consul/server2/data:/consul/data -v /root/data/consul/server2/config/:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_2 consul agent -server -ui -node=consul_server_2 -client='0.0.0.0' -datacenter=adnc_dc -data-dir /consul/data -config-dir /consul/config -join=$JOIN_IP;

-join=$JOIN_IP $JOIN_IP是上面获取到的consul_server_1节点的ip, join表示加入集群。

#启动容器consul_server_3并加入集群
docker run -d -p 8530:8500 --restart=always -v /root/data/consul/server3/data:/consul/data -v /root/data/consul/server3/config/:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_3 consul agent -server -ui -node=consul_server_3 -client='0.0.0.0' -datacenter=adnc_dc -data-dir /consul/data -config-dir /consul/config -join=$JOIN_IP; 
#验证2个server节点是否加入集群
docker exec consul_server_1 consul operator raft list-peers

显示信息如下,表示集群搭建成功。集群有3个server节点,consul_server_1是leader。

[root@VM-0-4-centos ~]# docker exec consul_server_1 consul operator raft list-peers
Node             ID                                    Address          State     Voter  RaftProtocol
consul_server_1  0026bb2d-d2e8-5681-a3ad-ada57036e2e1  172.17.0.2:8300  leader    true   3
consul_server_2  fc655a2d-556b-f6aa-1b17-d189da0081b4  172.17.0.3:8300  follower  true   3
consul_server_3  3cc9fc4e-a65c-1666-ab4c-d6cb5cfefd8a  172.17.0.4:8300  follower  true   3
#启动容器consul_client_1并加入集群
docker run -d -p 8550:8500 --restart=always -v /data/consul/client1/config:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --name=consul_client_1 consul agent -node=consul_client_1 -join=$JOIN_IP -client='0.0.0.0' -datacenter=adnc_dc -config-dir /consul/config

client节点可以N多个,一般来说每台服务器上都需要部署一个client节点

consul集群安装完成,我们在浏览器输入http://服务器IP:8510/ui/adnc_dc/nodes,应该可以看到4个节点。如下图:

consul集群 consul安装 consul部署 consul配置中心


安装SkyWalking

SkyWalking是观察性分析平台和应用性能管理系统。
提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。
skywalking需要安装三个软件elasticsearchskywalking-oap-serverskywalking-ui

elasticsearch 一个分布式、高扩展、高实时的搜索与数据分析存储引擎
skywalking-oap-server 可观测性分析平台,可以以从多种数据源接收数据,分析Tracing和Metrics
skywalking-ui UI界面

我们通过docker-compose 安装,安装过程因为墙的原因,可能需要的时间比较长,耐心等待

#启动sw-compose.yml文件关联的3个容器
docker-compose -f sw-compose.yml up -d

sw-compose.yml

version: '3.3'
services:
  elasticsearch:
    image: elasticsearch:6.8.0
    container_name: skywalking-es
    restart: always
    ports:
      - 9200:9200
      - 9300:9300
    environment:
      discovery.type: single-node
      TZ: Asia/Shanghai
      ES_JAVA_OPTS: -Xms256m
  oap:
    image: apache/skywalking-oap-server:6.1.0
    container_name: skywalking-oap
    depends_on:
      - elasticsearch
    links:
      - elasticsearch
    restart: always
    ports:
      - 11800:11800
      - 12800:12800
    environment:
      TZ: Asia/Shanghai
  ui:
    image: apache/skywalking-ui:6.1.0
    container_name: skywalking-ui
    depends_on:
      - oap
    links:
      - oap
    restart: always
    ports:
      - 18886:8080
    environment:
      collector.ribbon.listOfServers: oap:12800

skywalking安装完成,我们访问http://服务器IP:18886/,会出现登录页面,默认账号/密码 都是 admin 。
到此为止,serverapi需要的软件都已经安装完成(除nginxngnix的安装会在部署前端的时候介绍)。


下面正式进入主题,配置与部署。微服务的第一次部署是比较繁琐的,很多事情要做,往后就简单方便了。

配置consul的Key/Value

adnc会从consul读取appsettings的配置,并填充configuration对象。
consul任意节点配置的key/value都会自动同步到其他节点

//Program.cs
if (env.IsProduction() || env.IsStaging())
{
var configuration = cb.Build();
//从consul配置中心读取配置
var consulOption = configuration.GetSection("Consul").Get<ConsulConfig>();
cb.AddConsul(new[] { consulOption.ConsulUrl }, consulOption.ConsulKeyPath);
}
  • consul配置key/vaule配置有3种方法
    1、通过类似postman工具直接调用api配置。
    2、创建配置文件上传到节点目录配置。
    3、直接登录服务节点UI界面配置。

我们采用第3种最简单的方式,直接登录UI界面,配置key/value。
adnc有5个webapp需要部署对应consul的4个key(4个appsettings)

服务名 描述 key path
Adnc.Infr.Gateway ocelot网关 /adnc/production/gateway/appsettings
Adnc.Infr.HealthCheckUI 健康监测UI 配置内容目前没有放在consul配置中心
Adnc.Usr.WebApi 用户中心服务 /adnc/production/usr/appsettings
Adnc.Main.WebApi 运维中心服务 /adnc/production/maint/appsettings
Adnc.Cus.WebApi 客户中心服务 /adnc/production/cus/appsettings
  • 配置key/adnc/production/gateway/appsettings
    请将下面的内容copy到key的value中。

    //CorsHosts 这里配置你前端服务器nginx的IP。如果配错,javascript会存在不能跨域的问题。
    //
    {
    "Logging": {
    "LogLevel": {
      "Default": "Error",
      "Microsoft": "Error",
      "Microsoft.Hosting.Lifetime": "Error"
    }
    },
    "AllowedHosts": "*",
    "CorsHosts": "http://你前端服务器的ip"
    }
  • 配置/adnc/production/usr/appsettings

    根据自己的实际情况修改mysql,reids,MongoDb,RabbitMq对应的信息。
    /adnc/production/maint/appsettings
    /adnc/production/cus/appsettings
    /adnc/production/usr/appsettings
    这3个key除了mysql数据库名字不同,其他信息一样
    请将下面的内容copy到key的value中。

    {
    "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
    "Default": "Error",
    "Microsoft": "Error",
    "Microsoft.Hosting.Lifetime": "Error"
    }
    },
    "Mysql": {
    "WriteDbConnectionString": "Server=172.16.0.4;Port=13308;database=adnc_usr;uid=root;pwd=aaaa;"
    },
    "Redis": {
    "MaxRdSecond": 120,
    "EnableLogging": false,
    "LockMs": 5000,
    "SleepMs": 300,
    "dbconfig": {
    "ConnectionStrings": [
    "172.16.0.4:13379,password=football,defaultDatabase=0,poolsize=50,defaultDatabase=12,prefix="
    ],
    "ReadOnly": false
    }
    },
    "MongoDb": {
    "ConnectionStrings": "mongodb://alpha:football@172.16.0.4:13017/Logs",
    "CollectionNamingConvention": 2,
    "PluralizeCollectionNames": true
    },
    "RabbitMq": {
    "HostName": "172.16.0.4",
    "VirtualHost": "vhost.adnc",
    "Port": "13572",
    "UserName": "adnc",
    "Password": "aaaa"
    },
    "AllowedHosts": "*",
    "CorsHosts": "http://localhost:5888",
    "JWT": {
    "SymmetricSecurityKey": "alphadotnetcoresecurity2020",
    "Issuer": "172.16.0.4",
    "ClockSkew": 1,
    "Audience": "",
    "RefreshTokenAudience": "alpha",
    "Expire": 6000,
    "RefreshTokenExpire": 10080
    }
    }

修改配置文件

  • 修改appsetting.production.json

    appsetting.production.josn的配置都很简单只有两个节点
    一个是consul节点,另一个是skywalking节点。
    Consul节点修改ConsulUrl,换成你的地址
    SkyWalking节点修改Servers,换成你的地址

  • 修改Adnc.Infr.HealthCheckUIappsettings.json文件,将172.16.0.4替换成你服务器的ip即可。
  • 修改Adnc.Infr.Gateway config目录下的ocelot.production.json文件。
    copy下面内容到ocelot.production.json中,不要用现有的配置,因为现有配置需要安装fabio,ocelot路由配置有好几种,以后再介绍,现在我们用直连consul的方式。

    {
    "GlobalConfiguration": {
    "BaseUrl": "http://网关服务器IP:8888",
    "ServiceDiscoveryProvider": {
      "Scheme": "http",
      "Host": "Consul服务器IP",
      "Port": 8550,
      "Type": "Consul"
    }
    },
    "Routes": [
    {
      "UpstreamPathTemplate": "/usr{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Put",
        "Post",
        "Delete"
      ],
      "DownstreamScheme": "http",
      "DownstreamPathTemplate": "/usr{everything}",
      "ServiceName": "adnc.usr.webapi",
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      }
    },
    {
      "UpstreamPathTemplate": "/maint{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Put",
        "Post",
        "Delete"
      ],
      "DownstreamScheme": "http",
      "DownstreamPathTemplate": "/maint{everything}",
      "ServiceName": "adnc.maint.webapi",
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      }
    },
    {
      "UpstreamPathTemplate": "/cus{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Put",
        "Post",
        "Delete"
      ],
      "DownstreamScheme": "http",
      "DownstreamPathTemplate": "/cus{everything}",
      "ServiceName": "adnc.cus.webapi",
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      }
    }
    ]
    }

发布/部署

  1. 在服务器上建wwwroot目录,并且在该目录下新建adnc_gatewayadnc_healthadnc_usrandc_cusadnc_maintnginx 6个子目录。

    依次发布adnc.infr.gatewayadnc.infr.healthuiadnc.cus.webapiandc.usr.webapiadnc.maint.webapi
    部署模式:框架依赖

  2. 发布成功后分别上传到服务器各自对应目录里面。

Adnc.Usr.WebApi

  • 进入andc_usr的目录,新建一个Dockerfile文件,内容如下
    #adnc.usr.webapi
    #使用asp.net core 3.1作为基础镜像,起一个别名为base
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    #设置容器的工作目录为/app
    WORKDIR /app
    #COPY 文件
    COPY . /app
    #设置ASPNETCORE_ENVIRONMENT
    ENV ASPNETCORE_ENVIRONMENT production
    #配置本服务在skywalking名称
    ENV SKYWALKING__SERVICENAME=adnc-usr-webapi
    #skywalking接管的意思,除了adnc_health不需要配置,其他4个必须配置
    ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore
    #设置时区为东八区
    ENV TZ Asia/Shanghai
    #启动服务
    ENTRYPOINT ["dotnet", "Adnc.Usr.WebApi.dll"]
  • andc_usr目录下打包镜像文
    #注意最后有一个点,表示打包dockerfile文件所在的目录
    docker build -t adnc-usr-webapi .
  • 启动adnc-cus-webapi容器,容器监听7010端口
    #把172.16.0.4换成你自己的ip,172.16.0.4是我腾讯服务器的内网ip
    #容器正常启动后,会自动注册到consul
    docker run --name adnc-usr-webapi-7010 -d -p 7010:80 --env DOCKER_LISTEN_HOSTANDPORT=http://172.16.0.4:7010 adnc-usr-webapi
  • 进入consulUI管理界面http://consul服务器ip:8510,查看是否注册成功。

Adnc.Maint.WebApi

  • 进入andc_maint的目录,新建一个Dockerfile文件,内容如下
    #adnc.maint.webapi
    #使用asp.net core 3.1作为基础镜像,起一个别名为base
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    #设置容器的工作目录为/app
    WORKDIR /app
    #COPY 文件
    COPY . /app
    #设置ASPNETCORE_ENVIRONMENT
    ENV ASPNETCORE_ENVIRONMENT production
    #配置本服务在skywalking名称
    ENV SKYWALKING__SERVICENAME=adnc-maint-webapi
    #skywalking接管的意思,除了adnc_health不需要配置,其他4个必须配置
    ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore
    #设置时区为东八区
    ENV TZ Asia/Shanghai
    #启动服务
    ENTRYPOINT ["dotnet", "Adnc.Maint.WebApi.dll"]
  • andc_maint目录下打包镜像文
    #注意最后有一个点,表示打包dockerfile文件所在的目录
    docker build -t adnc-maint-webapi .
  • 启动adnc-maint-webapi容器,容器监听7020端口
    #把172.16.0.4换成你自己的ip,172.16.0.4是我腾讯服务器的内网ip
    #容器正常启动后,会自动注册到consul
    docker run --name adnc-maint-webapi-7020 -d -p 7020:80 --env DOCKER_LISTEN_HOSTANDPORT=http://172.16.0.4:7020 adnc-maint-webapi
  • 进入consulUI管理界面http://consul服务器ip:8510,查看是否注册成功。

Adnc.Cus.WebApi

  • 进入andc_cus的目录,新建一个Dockerfile文件,内容如下
    #andc.cus.webpai
    #使用asp.net core 3.1作为基础镜像,起一个别名为base
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    #设置容器的工作目录为/app
    WORKDIR /app
    #COPY 文件
    COPY . /app
    #设置ASPNETCORE_ENVIRONMENT
    ENV ASPNETCORE_ENVIRONMENT production
    #配置本服务在skywalking名称
    ENV SKYWALKING__SERVICENAME=adnc-cus-webapi
    #skywalking接管的意思,除了adnc_health不需要配置,其他4个必须配置
    ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore
    #设置时区为东八区
    ENV TZ Asia/Shanghai
    #启动服务
    ENTRYPOINT ["dotnet", "Adnc.Cus.WebApi.dll"]
  • andc_cus目录下打包镜像文
    #注意最后有一个点,表示打包dockerfile文件所在的目录
    docker build -t adnc-cus-webapi .
  • 启动adnc-cus-webapi容器,容器监听7030端口
    #把172.16.0.4换成你自己的ip,172.16.0.4是我腾讯服务器的内网ip
    #容器正常启动后,会自动注册到consul
    docker run --name  adnc-cus-webapi-7030 -d -p 7030:80 --env DOCKER_LISTEN_HOSTANDPORT=http://172.16.0.4:7030  adnc-cus-webapi 
  • 进入consulUI管理界面http://consul服务器ip:8510,查看是否注册成功。

Adnc.Infr.Gateway

  • 进入andc_gateway的目录,新建一个Dockerfile文件,内容如下
    #andc.infr.gateway
    #使用asp.net core 3.1作为基础镜像,起一个别名为base
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    #设置容器的工作目录为/app
    WORKDIR /app
    #COPY 文件
    COPY . /app
    #暴露80端口
    ENV ASPNETCORE_ENVIRONMENT production
    ENV SKYWALKING__SERVICENAME=adnc-gateway
    ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore
    ENV TZ Asia/Shanghai
    ENTRYPOINT ["dotnet", "Adnc.Infr.Gateway.dll"]
  • andc_gateway目录下打包镜像文
    #注意最后有一个点,表示打包dockerfile文件所在的目录
    docker build -t adnc-gateway .
  • 启动adnc-cus-webapi容器,容器监听8888端口,并挂载config目录
    #把172.16.0.4换成你自己的ip,172.16.0.4是我腾讯服务器的内网ip
    docker run --name adnc-gateway-8888 -d -p 8888:80 -v /root/wwwroot/adnc_gateway/Config:/app/Config adnc-gateway
  • 进入gateway首页http://服务器ip:8888,会显示Hello Ocelot,production!
  • 到了这一步,如果服务都成功部署,以下地址都可以通过网关正常路由到各自swagger首页。
    http://服务器ip:8888/usr/index.html
    http://服务器ip:8888/maint/index.html
    http://服务器ip:8888/cus/index.html

Adnc.Infr.HealthCheckUI

  • 进入adnc_health的目录,新建一个Dockerfile文件,内容如下
    #adnc.infr.healthcheckui
    #使用asp.net core 3.1作为基础镜像,起一个别名为base
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    #设置容器的工作目录为/app
    WORKDIR /app
    #COPY 文件
    COPY . /app
    ENV ASPNETCORE_ENVIRONMENT production
    ENTRYPOINT ["dotnet", "Adnc.Infr.HealthCheckUI.dll"]
  • adnc_health目录下打包镜像文
    #注意最后有一个点,表示打包dockerfile文件所在的目录
    docker build -t adnc-health .
  • 启动adnc-health容器,容器监听8666端口
    docker run --name adnc-health -d -p 8666:80 adnc-health
  • 直接进入HealthCheckUI界面http://服务器ip:8666,查看服务的健康状态。

ClientApp

终于写到前端了,写到这里我都已经写了一整天。

  • 新建/root/wwwroot/nginx/conf/nginx.conf

    #nginx.conf
    #运行nginx的用户
    #user  nginx;
    user root;
    #启动进程设置成和CPU数量相等
    worker_processes  1;
    #全局错误日志及PID文件的位置
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    #工作模式及连接数上限
    events {
        #单个后台work进程最大并发数设置为1024
    worker_connections  1024;
    }
    http {
        #设定mime类型
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    
        #设定日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log  /var/log/nginx/access.log  main;
    
    sendfile        on;
    #tcp_nopush     on;
    
        #设置连接超时的事件
    keepalive_timeout  65;
    
        #开启GZIP压缩
    #gzip  on;
    include /etc/nginx/conf.d/*.conf;
    }
  • 新建/root/wwwroot/nginx/conf.d/default.conf
    #default.conf
    server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
    }
  • 部署nginx
    #拉取镜像文件
    docker pull nginx
    #启动nginx容器,容器监听80端口,并挂载nginx.conf文件,conf.d,log,data目录
    docker run --name nginx -p 80:80 -v /root/wwwroot/nginx/html:/usr/share/nginx/html -v /root/wwwroot/nginx/conf/nginx.conf:/etc/nginx/nginx.conf  -v /root/wwwroot/nginx/conf.d:/etc/nginx/conf.d -v /root/wwwroot/nginx/logs:/var/log/nginx -d nginx
  • 用visual code 打开 clientApp
    #编译完成后,打包后的文件在clientApp目录下dist目录里面
    npm run build:prod
  • build成功后,将dist目录里的文件上传到/root/wwwroot/nginx/html目录
  • 打开http://服务器ip:80,如果成功,会出现登录页面,输入用户名/密码。
    如果能登录成功,并进入dashboard页,那么恭喜您,adnc部署成功。

问题交流

License

MIT
Free Software, Hell Yeah!