Skip to content
fogray edited this page Dec 13, 2016 · 3 revisions

这里的服务指docker swarm mode中的服务。

约定

约定1:服务名作为子域名

<$SERVICE-NAME>.service.imaicloud.com域名下的http请求会被“服务网关”自动转发给名称为<tasks.$SERVICE-NAME>的docker服务。
docker内置的DNS会将<$SERVICE-NAME>转换VIP。 服务网关使用nginx实现。

约定2:服务名作为路径

URI以https://service.imaicloud.com/<$SERVICE-NAME>/开始的http请求会被“服务网关”自动转发给名称为<tasks.$SERVICE-NAME>的docker服务。
约定2的兼容性不如约定1。但imaicloud.com采用的let‘s encrypt的免费https证书不支持通配符域名,为了支持https只能采用这种折中的方式。 约定1与约定2同时支持,调用服务时具体采用哪种方式由开发者自己决定。

约定3:服务名前缀

<$SERVICE-NAME>的编码规则是:以<$TENANT_ID.>为前缀
由于容器集群是多用户共享的,这个约定既避免了服务名重复,也为了过滤不同租户的服务。

约定4:目录名

分布式文件系统上为每个租户创建/tenant/<$TENANT_ID>/的目录 用户可以在上述目录上创建docker volume,也可以存放其他的文件。

部署

1.创建swarm集群

创建docker swarm集群的文档参考[docker swarm模式测试](docker swarm模式测试)。

2.创建overlay网络

目标是创建一个“大”overlay虚拟网络,将反向代理nginx-proxy服务和租户创建的服务连接起来。 该overlay网络的名称是nginx-network。创建命令:

docker network create --driver overlay nginx-network

3.创建nginx-proxy服务

该服务的docker镜像是imaidev/nginx-proxy,该镜像自动构建自库nginx-proxy。 可以到库中看一下nginx配置文件。解释一下nginx配置文件:

resolver 127.0.0.11;
server {
    listen 80;
    location / {
          proxy_set_header Host $host:$server_port;
          proxy_pass http://$http_x_imai_service:$http_x_imai_port;
    }
}
  • 在http请求头中X-IMAI-SERVICE表示租户在swarm集群中创建的服务名称
  • X-IMAI-PORT表示租户在swarm集群中创建的服务监听的端口
docker service create --name nginx-proxy --network webb-network -p 8088:80 imaidev/nginx-proxy

4.创建租户服务

使用jihchi/echo-server2镜像充当租户服务。这个镜像的功能是以json格式直接返回http请求(包括响应头),默认端口是4000端口。 使用docker1.12新增的docker service命令创建服务:

docker service create --name echo-server --network nginx-network jihchi/echo-server2

5. 配置外部nginx

外部nginx解析发往https(http)://service.imaicloud.com的请求。外部nginx还需要向http头中写入X-IMAI-SERVICE和X-IMAI-PORT,以便运行在swarm集群中的nginx-proxy转发请求到正确的租户服务。

server {
                listen 80;
                server_name service.imaicloud.com;
                root html-imaicloud;

                location ~* /(.*[^__]?)__(.*[^__]?)__(.*?)/ {
                        set $service $1__$2__$3;
                        set $port $3;
                        set $req_uri /;
                        if ($request_uri ~* ^/[^\/]+/(.*?)$) {
                                set $req_uri $1;
                        }
                        proxy_set_header X-IMAI-SERVICE $service; #租户__名称__端口
                        proxy_set_header X-IMAI-PORT $port;
                        proxy_set_header X-IMAI-URI $req_uri; #实际请求url
                        proxy_set_header request_uri $request_uri;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                        proxy_pass http://10.0.7.105:8088; #代理到docker内部nginx-proxy服务
                }

        }
server {        #https请求
                listen 443;
                server_name service.imaicloud.com;
                root html-imaicloud;
                ssl on;
                ssl_certificate      /etc/letsencrypt/live/imaicloud.com/fullchain.pem;
                ssl_certificate_key  /etc/letsencrypt/live/imaicloud.com/privkey.pem;
                location / {
                        set $service www;
                        set $port 80;
                        if ($http_host ~* "^(.*[^__]?)__(.*[^__]?)__(.*?)\.service\.imaicloud\.com$") {
                                set $service $1__$2__$3;
                                set $port $3;
                        }
                        proxy_set_header X-IMAI-SERVICE $service;
                        proxy_set_header X-IMAI-PORT $port;
                        proxy_set_header X-IMAI-OTHER $request_uri;
                        proxy_set_header request_uri $request_uri;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header Host $host:$server_port;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";

                        include cors-include.conf;
                        proxy_pass http://10.0.7.105:8088; #代理到docker内部nginx-proxy服务
                }
        }

测试

测试约定1

使用curl或在浏览器中输入:

https://fwvd2i7drqgtzmecfchg5w__echo-server__4000.service.imaicloud.com

测试约定2

使用curl或在浏览器中输入:

http://service.imaicloud.com/fwvd2i7drqgtzmecfchg5w__echo-server__4000/
Clone this wiki locally