Docker Swarm 部署 micro 微服务应用

本贴最后更新于 1736 天前,其中的信息可能已经物是人非

微服务应用使用容器部署非常方便,但是当应用服务注册自身地址(ip:port)到服务注册中心的时候,如果注册的是容器内的 ip,别的服务是无法访问到的。

解决这个问题,可以在运行容器的时候指定网络模式为 host (--net=host) ,这样就可以跳过 Docker 的独立网络栈,直接通过本机 IP 端口就可以访问,但是这样会大量占用本地端口。

最好的场景还是后端服务都在容器网络中,仅 API 网关暴露一个端口供外部访问,但是同时还后端服务还需要能实现跨机器的网络连通。

早期 Docker 本身的容器网络本身并不支持跨机器,也就是说明如果容器部署在不同的节点(服务器)上面,只能通过暴露端口到宿主机上,再通过宿主机之间进行通信。Docker 12.0 之后的版本自带 Docker Swarm,Docker Swarm 的 Overlay 网络驱动可以实现跨主机网络通信。Kubernetes 固然好,但是同时也非常重,学习成本也很大,Swarm 在小项目中还是有用武之地的。

dokcer swarm 集群搭建

准备两台安装有 docker 的机器:
192.168.0.1
192.168.0.2

192.168.0.1 创建 master 节点

#    docker swarm init

#    docker swarm join \
>     --token SWMTKN-1-3uu3gjkdt6xgk06wd1c9gfog8xec99ga69ilcclyzyk181n5ki-6f7frw75gvpdwsl1yvpf885lw \
>     192.168.0.1:2377
This node joined a swarm as a worker.

复制上面的 docker swarm join ...
在 192.168.0.2 上执行,即将本机加入 swarm 集群。

至此,我们已经创建了一个最基础的 swarm 的集群,执行命令查看:

#   docker node ls
ID                           HOSTNAME   STATUS  AVAILABILITY  MANAGER STATUS
r76ighlnw0p2r0tbd9wmoqaep    server2    Ready   Active
rzqbzl58hlu89xoty4cedn0er *  server1    Ready   Active        Leader

创建 overlay 网络

先创建一个可以跨机器的 overlay 网络

docker network create -d overlay my_net

部署应用服务

部署服务注册中心 consul

在服务器 192.168.0.1 中使用 Docker 简单部署一个使用。

docker run --name consul -d -p 8500:8500/tcp consul agent -server -ui -bootstrap-expect=1 -client=0.0.0.0

部署 API 网关

采用 micro 官方的 micro api,不了解 micro 的可以看我之前的博客,或者去 micro 官方仓库查看。

docker service create --replicas 4  --publish published=8898,target=8080  --name micro-p -e MICRO_REGISTRY=consul  -e MICRO_REGISTRY_ADDRESS=192.168.0.1:8500 -e  MICRO_API_HANDLER=http  --network=my_net microhq/micro:latest api

部署后端服务

编写一个简单的 micro web 服务

package main

import (
	"log"

	"github.com/gin-gonic/gin"
	"github.com/micro/go-micro/web"
)

type Say struct{}

func (s *Say) Anything(c *gin.Context) {
	log.Print("Received Say.Anything API request")
	c.JSON(200, map[string]string{
		"message": "Hi, this is the Greeter API",
	})
}

func main() {
	// Create service
	service := web.NewService(
		web.Name("go.micro.api.greeter"),
	)

	service.Init()

	// Create RESTful handler (using Gin)
	say := new(Say)
	router := gin.Default()
	router.GET("/greeter", say.Anything)

	// Register Handler
	service.Handle("/", router)

	// Run server
	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

Dockerfile 如下:

FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY hello-gin /hello-gin
ENTRYPOINT /hello-gin

LABEL Name=hello-gin Version=0.0.1

将 Docker build 出来推到自己的 Docker 仓库上,或者直接 pull 我的镜像。

部署服务

 docker service create --replicas 2 --name hello-xx -e MICRO_REGISTRY=consul  -e MICRO_REGISTRY_ADDRESS=192.168.0.1:8500 --network=xuxu_net  xuxu123/hello-gin:v0.1.0

测试 demo

curl --request GET  --url http://192.168.0.1:8080/greeter

总结

主要简单演练了一遍 Docker Swarm 集群部署以及微服务部署的一个简单场景部署。相较于 K8S 的强大功能,Swarm 似乎显得有些多余,但是 Swarm 的简单明了在小厂中未必有没有用武之地吧。

  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    476 引用 • 899 回帖
  • swarm
    4 引用 • 2 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    你好,按照你的 dockfile build 后去创建容器,一直停留在 preparing 状态,拉你的镜像就没问题,请问什么原因呢,另外我用 go mod 依赖写的 micro 服务,该如何写 dockfile 呢?请教!

    1 回复
  • Allenxuxu
    作者

    这篇文章主要是讲 Docker Swarm 的,和 docker build 关系不大,你可以把你的命令和输出信息贴出来,我帮你看看。