Golang viper包环境变量采坑指南(Docker环境变量读取)
发布时间: 2020-11-17 更新时间: 2023-02-06
Golang viper,docker,环境变量 4.40 K 4 分钟 1984
Golang viper包环境变量采坑指南(Docker环境变量读取)
一、起因
这两天项目基本上已经开发完成,准备上生产环境,通过docker来部署。但是始终无法读取到环境变量,在本地go build
的程序偏偏可以。文件目录如下:
__
|--conf.yaml
|--docker-compose.yaml
|--Dockerfile
|--go.mod
|--main.go
安装viper:go install github.com/spf13/viper
二、简化代码
- main.go
/**
* @Author: qzq
* @Description:
* @File: main
* @Version: 1.0.0
* @Date: 2020/11/26 10:10
**/
package main
import (
"github.com/spf13/pflag"
"github.com/spf13/viper"
"log"
"os"
"os/signal"
"syscall"
)
var (
cfg = pflag.StringP("config", "c", "", "配置文件路径")
)
func main() {
pflag.Parse()
if *cfg != "" {
viper.SetConfigFile(*cfg) // 如果指定了配置文件,则解析指定的配置文件
} else {
viper.AddConfigPath(".") // 查找配置文件所在路径
viper.SetConfigName("conf") // 配置文件的文件名,没有扩展名,如 .yaml, .toml 这样的扩展名
}
viper.SetConfigType("yaml") // 设置扩展名。在这里设置文件的扩展名。
viper.AutomaticEnv()
err := viper.ReadInConfig() // 搜索并读取配置文件
if err != nil { // 处理错误
panic(err)
}
log.Printf("app.PageSize:%d \n", viper.GetInt("app.PageSize"))
log.Printf("app.AppMode:%s \n", viper.GetString("app.AppMode"))
quit := make(chan os.Signal)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
}
- conf.yaml
app:
PageSize: 8
AppMode: debug
三、本地环境(windows)运行
- 未设置环境变量,直接读取conf文件内容。执行
go run main.go
2020/11/26 18:21:15 app.PageSize:8 2020/11/26 18:21:15 app.AppMode:debug
- 设置环境变量,命令行中输入
set app.PageSize=10
,set app.AppMode=1112
。执行go run main.go
2020/11/26 18:21:01 app.PageSize:10 2020/11/26 18:21:01 app.AppMode:1112
在本地环境(windows)中,设置的环境变量能读取
四、docker环境运行
- Dockerfile
FROM golang:1.14-alpine as builder
MAINTAINER "QZQ"
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io
WORKDIR /projects
COPY . .
RUN go build .
FROM alpine as prod
MAINTAINER "QZQ"
WORKDIR /projects
COPY --from=builder /projects/viper_demo ./viper_demo
COPY --from=builder /projects/conf.yaml ./conf.yaml
- docker-compose.yaml
version: "3"
services:
viper_demo:
container_name: viper_demo
build: .
image: viper_demo:latest
environment:
# 设置环境变量
app.PageSize: 10
app.AppMode: debug
- 按照上述配置文件,构建docker镜像并启动容器。
- 执行
docker-compose build
- 执行
docker-compose up
- 输出内容如下
2020/11/26 18:21:15 app.PageSize:8 2020/11/26 18:21:15 app.AppMode:debug
- 执行
在docker环境中,设置的环境变量无法读取
五、解决过程
-
官方文档关于读取环境变量的解释。
When working with ENV variables, it’s important to recognize that Viper treats ENV variables as case sensitive.
使用ENV变量时,务必要意识到Viper将ENV变量视为区分大小写。(谷歌翻译)当viper读取环境变量的时候,是区分大小写的。按照这个说法,那么在docker中是能读取,但是实际情况是无法读取。
-
后面查到类似问题【go中的os.Getenv(""),得不到自定义环境变量】。最终的解决方法如下:
对于viper,是按照大写找的,如果环境变量中有小写,是找不到的!
六、最终解决方法
- 修改
dokcer-compose.yaml
文件
version: "3"
services:
viper_demo:
container_name: viper_demo
build: .
image: viper_demo:latest
environment:
APP.PAGESIZE: 10
APP.APPMODE: debug1111
- 重新构建并执行
- 执行
docker-compose build
- 执行
docker-compose up
- 输出内容如下
2020/11/26 18:21:15 app.PageSize:10 2020/11/26 18:21:15 app.AppMode:debug111
- 执行
七、总结
- viper读取环境变量时,环境变量最好都是大写。

