Go微服务十一 Dockerfile ENTRYPOINT的使用 – 接受参数 读取nacos对应的配置文件

作者: 太阳上的雨天 分类: 微服务 发布时间: 2022-03-09 21:21

[微服务二]这篇文章中,简单谈了从nacos读取服务配置文件。在[微服务七]这篇文章中,谈了制作Dockerfile,通过docker将Go项目部署并运行在服务器上。在[微服务八]谈了使用shell脚本一键重新构建基于Docker的Go项目。

这篇文章中,实现动态获取nacos对应的配置文件。在[微服务二]这篇文章中,获取nacos配置文件,是在代码里面写的nacos的ip、端口、组、DataID。这样写,如果要读取其他配置文件就要改动代码,及其的不方便。如果在项目目录写成配置文件,也行。但是每次打包项目上传服务器,配置文件也要上传。不太方便。>[微服务二]这篇文章中,获取nacos配置文件,是在代码里面写的nacos的ip、端口、组、DataID。这样写,如果要读取其他配置文件就要改动代码,及其的不方便。如果在项目目录写成配置文件,也行。但是每次打包项目上传服务器,配置文件也要上传。不太方便。**

现在通过命令行参数传参的形式,根据传入的参数加载nacos上对应的配置文件。

首先要先理解nacos的使用。其次懂得使用Go语言中的flag包来解析命令行参数。获取命令行参数的形式有多种,这里只以flag包为例。

可以通flag.String、flag.Int等等获取对应类型的命令行参数。方法中包含三个字name、value、usage 分别是参数名、参数值、参数说明.如果忘记传什么参数可以通过–help 查看参数说明。

这里以从nacos读取配置文件连接mysql和redis为例浅谈。

话不多说直接上Demo

1. 打开nacos新建一个demo.yaml的配置文件

demo:
  datasource:
    dsn: root:root@tcp(127.0.0.1:3306)/test
    showSql: true
  redis:
    host: 127.0.0.1:6379
    password: root
    db: 0

2. Demo程序

var (
    viperConfig *viper.Viper
)

var (
    nacosIP2 = flag.String("ip", "127.0.0.1", "The nacos of ip address")
    port2    = flag.Int("p", 8848, "The nacos of port")
    group2   = flag.String("g", "demo", "The nacos of Group")
    cfg2     = flag.String("c", "demo.yml", "The path of configuration file")
)

type MysqlConfig struct {
    DbDsn   string
    ShowSQL bool
}

type RedisConfig struct {
    RedisAddr string
    Password  string
    RedisDb   int
}

func init() {
    flag.Parse()
}

func main() {
    ParseRemoteConfig(*nacosIP2, *port2, *group2, *cfg2)
    fmt.Println(GetMysqlConfig())
    fmt.Println(GetRedisConfig())
}

//ParseRemoteConfig 解析nacos配置文件
func ParseRemoteConfig(ip2 string, port2 int, group2 string, cfg2 string) *viper.Viper {

    viperConfig = viper.New()
    viperConfig.SetConfigType("yaml")
    viperConfig.SetConfigName(cfg2)
    serverConfigs := []constant.ServerConfig{
        {IpAddr: ip2, Port: uint64(port2)},
    }
    nacosClient, err := clients.NewConfigClient(vo.NacosClientParam{
        ClientConfig:  &constant.ClientConfig{TimeoutMs: 5000},
        ServerConfigs: serverConfigs,
    })
    if err != nil {
        logger.OmpLog.Fatal("nacos init failed :", err)
    }
    content, err := nacosClient.GetConfig(vo.ConfigParam{
        DataId: cfg2,
        Group:  group2,
    })
    if err != nil {
        logger.OmpLog.Fatal("read from nacos failed:" + content)
    }

    viperConfig.ReadConfig(strings.NewReader(content))
    return viperConfig
}

//GetMysqlConfig mysql配置
func GetMysqlConfig() MysqlConfig {
    var mc MysqlConfig
    mc.DbDsn = viperConfig.GetString("demo.datasource.dsn")
    mc.ShowSQL = viperConfig.GetBool("demo.datasource.showSql")
    return mc
}

//GetRedisConfig redis配置
func GetRedisConfig() RedisConfig {
    var rrc RedisConfig
    rrc.RedisAddr = viperConfig.GetString("demo.redis.host")
    rrc.Password = viperConfig.GetString("demo.redis.password")
    rrc.RedisDb = viperConfig.GetInt("demo.redis.db")
    return rrc
}

执行:

  go run main.go -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml

  # 或者先编译 
  go build
  ./main -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml

即可看到接受到的命令行参数和读取到的配置信息

image-20220309210227887

image-20220309210312996

3. 链接mysql和redis, 修改main函数

ParseRemoteConfig(*nacosIP2, *port2, *group2, *cfg2)
    //  链接mysql
    db, err := sql.Open("mysql", GetMysqlConfig().DbDsn)
    if err != nil {
        panic(err)
    }
    err = db.Ping()

    if err != nil {
        panic(err)
    }
    fmt.Println("mysql connect success...")

    // 链接redis
    rdb := redis.NewClient(&redis.Options{
        Addr:     GetRedisConfig().RedisAddr,
        Password: GetRedisConfig().Password,
        DB:       GetRedisConfig().RedisDb,
    })
    ping := rdb.Ping()

    err = ping.Err()
    if err != nil {
        panic(err)
    }
    fmt.Println("redis connect success...")

执行:

  go run main.go -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml

  # 或者先编译 
  go build
  ./main -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml

即可看到数据库和redis连接成功

image-20220309210510838

四. 结合之前谈到的Dockerfile进行命令行传参

因为部署项目是结合docker进行部署的,不可能把代码上传到服务器,去执行go run 或者go build 。采用shell脚本,一键完成自动服务重载。那么就要通过dockerfile来将上面的参数传递过来。

这个脚本采用upx来帮我们对go项目进行打包

#!/usr/bin/env bash
echo "开始编译文件"
buildFileName="main"
BuildTime=`date +'%Y.%m.%d.%H:%M:%S'`
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -o ${buildFileName}
#go build -o main main.go
echo "编译完成, 编译时间${BuildTime}"
echo "开始压缩文件"
upx -9 ${buildFileName}
echo "完成压缩"

Dcokerfile

FROM golang:1.17.2-alpine

# 设置工作目录
WORKDIR /root/demo

# 添加可执行文件
ADD ./main $WORKDIR

# 添加
ADD config /root/omp-go/omp-router/config
ADD log /root/omp-go/omp-router/log

# 声明服务端口
EXPOSE 9999

# 启动容器时运行的命令
ENTRYPOINT ["./demo", "-ip","127.0.0.1","-p","8848","-g","demo","-c","demo.yml"]

start.sh

#! /bin/bash

if [ ! -f 'main' ]; then
  echo 文件不存在! 待添加的安装包: 'main'
  exit
fi

echo "main-demo..."
sleep 3
docker stop main-demo

sleep 2
docker rm main-demo

docker rmi main-demo
echo ""

echo "main-demo packing..."
sleep 3
docker build -t main-demo .
echo ""

echo "main-demo running..."
sleep 3
docker run --name main-demo \
  -p 9804:9804 \
  -d main-demo \

docker logs -f main-demo | sed '/Started main-demoApplication/q'

echo ""

先进行打包,然后启动即可…

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注