场景
工作环境中,用容器部署服务是很常见的操作,而新上线的业务,测试人员需要对服务进行测试
但是一下几种可能,使得测试人员并不能方便的查看日志:
- 有的测试人员docker并不熟
- 权限比较严格,测试人员没权限操作容器
- 临时需要查看日志
第一第二中情况咱就不说了,第三种情况,如果只是临时需要,咱们其实没必要特意去接入日志服务
只需要写个服务,将读取到的日志通过api返回出去就好了,又不会占用很多资源,又能随起随停
代码部分
package main
import (
"bufio"
"context"
"fmt"
"net/http"
"strconv"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/gin-gonic/gin"
)
var (
host = "10.0.0.12"
RemoteDockerHost = "tcp://" + host + ":2376"
CaPath = "cert/" + host + "/ca.pem"
ClientCertPath = "cert/" + host + "/cert.pem"
ClientKeyPath = "cert/" + host + "/key.pem"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
containerName := c.DefaultQuery("c", "mysql")
n := c.DefaultQuery("n", "1000")
ccc, err := strconv.ParseInt(n, 10, 64)
if err != nil {
fmt.Println("参数转化失败:", err)
c.String(http.StatusBadRequest, "传参有误")
c.Abort()
return
}
// 创建Docker客户端并指定远程Docker守护进程地址
cli, err := client.NewClientWithOpts(
client.WithHost(RemoteDockerHost),
// client.WithVersion("1.41"),
client.WithAPIVersionNegotiation(),
client.WithTLSClientConfig(CaPath, ClientCertPath, ClientKeyPath),
)
if err != nil {
fmt.Println("创建容器失败:", err)
c.String(http.StatusBadRequest, "容器访问失败")
c.Abort()
return
}
_, err = cli.ContainerInspect(c.Request.Context(), containerName)
if err != nil {
fmt.Println("容器查询失败:", err)
c.String(http.StatusBadRequest, "容器不存在")
c.Abort()
return
}
// fmt.Println(containerInfo)
option := types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: true,
// Timestamps: true,
Tail: n,
}
cxt, cancel := context.WithTimeout(c.Request.Context(), 500*time.Millisecond)
defer cancel()
out, err := cli.ContainerLogs(cxt, containerName, option)
if err != nil {
fmt.Println(err.Error())
c.String(http.StatusBadRequest, "容器日志访问失败")
c.Abort()
return
}
defer out.Close()
scanner := bufio.NewScanner(out)
// defer cancel()
num := int64(0)
var content []byte
for scanner.Scan() {
num++
buf := scanner.Bytes()
if len(buf) > 8 {
content = append(content, scanner.Bytes()[8:]...)
}
if num != 1 {
content = append(content, '\n')
}
if num >= ccc {
cancel()
}
}
c.Data(http.StatusOK, "text/plain; charset=utf-8", content)
})
r.Run(":50000")
}
因为go语言的特性,对资源消耗比较小,而且非常容易编译成二进制可执行文件,所以能非常好的解决上面的需求
使用
起的服务是50000端口的,然后可以接受两个查询参数
- c,表示容器ID,可以是容器ID,也可以是容器名,默认是mysql容器
- n,表示查询的最后的行数,默认是1000行
这样就可以通过查询参数的方式查询主机上的任意容器的日志,当然,觉得不安全,也可以设置黑白名单之类的,这里就不做处理了
标签:容器,http,err,fmt,content,api,go,日志 From: https://www.cnblogs.com/guangdelw/p/17585875.html