Docker部署其实也可以再docker run或者dockerfile里面,将配置文件目录映射到宿主机,然后通过宿主机配置文件修改参数。
FROM docker.io/python:3.6MAINTAINER tianye
# 设置容器时间
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENV LANG C.UTF-8 # 设置编码
ENV PATH=$PATH:/usr/local/lib/python3.6/
ENV PYTHONPATH $PATH # 配置环境变量
ENV PARAMS="" # 给我们要传的参数一个初始值
ARG VERSION=1.20
#代码添加到code文件夹
ADD ./tttt/ /test/code/tttt/
#设置code文件夹为工作目录
WORKDIR /test/code/tttt/
CMD python3 ttt.py $PARAMS
很多时候Dockerfile文件中需要定义变量,减少对Dockerfile文件的修改,在编译的时候从外部传入参数,这种情况可使用 ARG
参数,然后通过--build-arg
进行赋值。
例如:Dockerfile 如下 参数变量VERSION从外部传递进去,在构建镜像时,使用--build-arg VERSION=版本号,进行传递
docker build -f dockerfile/server_dockerfile.v5.0.1 -t server:v5.0.1 zcbus_server --build-arg VERSION=v5.0.1 -e PARAMS="我是参数"
我们这里实现传参是通过环境变量实现的,这里的 -e PARAMS="我是参数" ,PARAMS是在Dockerfile中指定的。
那个k8s呢?集群内随机创建pod对象,文件存储基本也不会使用本地卷,都是用分布式文件系统(FastDFS)或者对象存储(MinIO),好像没有地方放配置文件了啊。那么是不是我上线前就必须把线上配置丢到程序里的配置文件中去呢?
答案那肯定是不用啦。
其实同时做过运维和开发的技术可能会知道,其实springboot的yml文件,其实是支持操作系统环境变量加载的。
例如:
redis:
port: 16379
host: 36.134.204.163
上面是一个常见的redis的配置,其实他还可以成下面这样:
redis:
port: ${REDIS_PORT:16379}
host: ${REDIS_HOST:36.134.204.163}
本机运行的时候,其实没有任何影响。
那么第二种写法是什么意思呢?
这里就要说道系统环境变量了。还记得JavaHome怎么配置吗?那其实就是环境变量。
环境变量是系统中配置的全局参数变量,任何程序都可以直接通过系统接口读取到环境变量的值。
上面的写法就是,如果系统中存在REDIS_PORT环境变量参数设置,那么就使用这个设置,如果没有,那么使用16379作为默认值。host也是一个道理。
系统中存在REDIS_HOST环境变量参数设置
去掉外部的系统中REDIS_HOST环境变量参数
1. 将服务中所有需要解耦的配置项全部配置成环境变量+默认值的方式。
2. 将环境变量的列表提供给k8s运维人员,由他按照列表,配置k8s部署的yml文件,通过spec下env增加对应环境变量设置,改为k8s环境下设置。
k8s会把env配置下的参数,输出到容器的环境变量中,服务直接读取就会生效。从而实现解耦。
其实这个办法是比较推荐的,可以开发组内通过规范的形式,把mysql、redis、mq、nacos等信息都统一处理上。基本不会影响开发人员本地开发测试工作。同时也不会增加k8s运维人员过多负担。
spec:
containers:
- args: []
env:
- name: RUNTIME_ENV
value: 'prd'
- name: DATASOURCE_IP
value: '192.168.0.60'
- name: DATASOURCE_PORT
value: '3306'
- name: DATASOURCE_USERNAME
value: 'root'
- name: DATASOURCE_PASSWORD #数据库密码
其实还有一个办法,经测试,deploy的env的配置,会复写springboot中yml对应key的值。
于是乎我们其实可以直接写成这样:
env:
- name: spring.redis.host
value: '192.168.216.219'
- name: spring.redis.port
value: '6379'
- name: spring.redis.password
value: '123456'
于是k8s下启动容器的java服务中,生效的是k8s配置的192.168.216.219。
jar包中原先的配置就被覆盖掉了。
这种方式感觉上其实比方案一要简单,但其实存在些问题。比方说不同项目中yml的层级不同,可能配置项目的名称也不一样,k8s管理员那里,不太好通过统一的yaml模板部署项目,每次都需要跟研发人员去核对。