利用Traefik部署Golang微服务简单示例
利用 Traefik 部署 Golang 微服务简单示例,先安装 Traefik,我这里直接用 docker-compose。
cd /opt
mkdir traefik && cd traefik
# 编写文件
vim docker-compose.yaml
我这里将 traefik 的 compose文件和具体的项目代码的 compose 文件分开来写。
traefik 的 docker-compose.yaml 文件
version: '3'
services:
my_traefik:
restart: always
image: traefik:2.1.6
ports:
- '80:80'
- '8003:8080'
- '443:443'
command:
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- webgateway
networks:
webgateway:
external:
name: my_gateway
此编排文件中的网络使用了自定义的 my_gateway,所以要先创建一下
docker network create my_gateway
监听80端口是入口服务,所有的服务请求都会进到80端口这里,8080端口是 traefik 自己的 webUI 服务。
针对上面的几个重要参数,以下是详细的解释:
—api.insecure=true:
这个参数表示开启 Traefik 的 API,并允许使用非安全的连接进行访问。由于设置为了 true,所以可以通过 HTTP 访问 API。请注意,在生产环境中,为了安全起见,建议使用安全的 HTTPS 连接并禁用这个选项。
—providers.docker=true:
这个参数表示启用 Traefik 的 Docker 提供者插件。它告诉 Traefik 要监控和管理运行在 Docker 上的容器化服务。
—providers.docker.exposedbydefault=false:
这个参数指示 Traefik 不自动暴露所有运行的容器化服务。默认情况下,Traefik 会将每个容器标记为可公开访问的服务。但是,通过将此参数设置为 false,您可以明确控制哪些服务应该由 Traefik 管理和暴露。
—entrypoints.web.address=:80:
这个参数定义了入口点(Entrypoint)的配置。入口点指定了如何监听流量并将其传递给后端服务。在示例中,我们使用名为 “web” 的入口点,并将其绑定到主机的 80 端口上。这意味着 Traefik 将监听来自主机的 HTTP 流量,并根据路由规则转发到相应的服务。
编写完成后直接创建
docker-compose up -d
已经运行起来了
接下来开始编辑一个简单的 go 服务,在当前目录下创建一个新目录 demo 并创建 main.go 文件
mkdir demo && cd demo
vim main.go
main.go 代码
package main
import (
"fmt"
"html"
"net/http"
)
func main() {
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8005", nil))
}
Dockerfile代码
FROM golang:alpine as Builder
ENV CGO_ENABLED 0
ENV GOOS linux
WORKDIR /www
COPY go.mod .
COPY . .
RUN go build -ldflags="-s -w" -o /www/app main.go
FROM alpine
WORKDIR /www
COPY --from=Builder /www/app /www/app
CMD ["./app"]
创建当前项目的 docker-compose
vim docker-compose.yaml
# 以下是文件内容
version: '3'
services:
mydemo2:
container_name: mydemo2
build:
context: .
dockerfile: Dockerfile
labels:
- "traefik.enable=true"
- "traefik.http.routers.mydemo2.rule=Host(`t.com`) && PathPrefix(`/demo2`)"
- "traefik.http.routers.mydemo2.entrypoints=web"
- "traefik.http.services.mydemo2.loadbalancer.server.port=8005"
restart: always
command: ["./app"]
networks:
- webgateway
networks:
webgateway:
external:
name: my_gateway
其中,上面的 traefik 参数解释:
“traefik.enable=true”:
这个标签告诉 Traefik 启用对该服务的代理。
“traefik.http.routers.mytest.rule=Host(‘t.com’)”:
这个标签定义了路由规则。这里的规则是基于 Host(主机名)匹配,当流量访问到 Host 为 “t.com” 时,将被路由到该服务。
“traefik.http.routers.mytest.entrypoints=web”:
这个标签指定了流量进入的入口点。在这里,我们使用名为 “web” 的入口点。这个入口点需要事先在 Traefik 配置中定义并配置对应的监听端口。
“traefik.http.services.mytest.loadbalancer.server.port=8005”:
这个标签指定了该服务后端的端口号。Traefik 将会将收到的流量代理到后端服务容器的 8005 端口。
networks: webgateway:
这个参数指定了容器所连接的网络。在这个例子中,容器将连接到名为 “webgateway” 的外部网络。
修改 /etc/hosts 文件,新增
127.0.0.1 t.com
启动新建的 demo 服务
docker-compose up -d --build
启动完成后访问 t.com/bar 验证一下效果
[root@centos-dev demo]# curl -v t.com/bar
* About to connect() to t.com port 80 (#0)
* Trying 192.168.179.3...
* Connected to t.com (192.168.179.3) port 80 (#0)
> GET /bar HTTP/1.1
> User-Agent: curl/7.29.0
> Host: t.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Length: 13
< Content-Type: text/plain; charset=utf-8
< Date: Tue, 27 Jun 2023 23:00:47 GMT
<
* Connection #0 to host t.com left intact
Hello, "/bar"[root@centos-dev demo]#
可以了~
这里面有一个大坑要特别注意
假如目录结构是这样的
/www
docker-compose.yaml
demo-docker-compose.yaml
demo(项目目录)
main.go
Dockerfile
如果项目的docker-compose.yaml放在与项目目录demo同级的地方,如上所示,则里面的 Dockerfile 一定要根据 docker-compose.yaml 文件为主。
意思是,在这种情况下 dockerfile 里面的COPY go.mod .
要改为
COPY demo2/go.mod .
否则会一直报错
=> ERROR [builder 3/6] COPY go.mod ./ 0.0s
------
> [builder 3/6] COPY go.mod ./:
------
Dockerfile:7
--------------------
5 | WORKDIR /www
6 |
7 | >>> COPY go.mod ./
8 | RUN go mod download
9 |
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 04f9fa94-6937-4d74-9d3b-9d851fda6071::p7k2oodsv37vsdr3z56v26iez: "/go.mod": not found
声明: 因编程语言版本更新较快,当前文章所涉及的语法或某些特性相关的信息并不一定完全适用于您当前所使用的版本,请仔细甄别。文章内容仅作为学习和参考,若有错误,欢迎指正。