1. 概述
在软件开发中,将应用程序代码与其使用的数据解耦是一种最佳实践。这种做法使得应用可以在不同环境中迁移而无需修改代码,因为环境相关的配置信息被存储在代码之外。
一个非常典型的例子就是使用 环境变量。环境变量存储了应用程序可以使用的数据,而不是硬编码在逻辑中。
在本教程中,我们会介绍如何在 Docker 中使用 --env-file
传递环境变量,以及在 Kubernetes 中对应的实现方式,即 ConfigMap
和 Secret
。
2. 在 Docker 中使用 --env-file
向 Docker 容器中注入环境变量的一个常见方式是使用 env-file
。它是一个文本文件,包含一系列键值对,代表环境变量。
我们可以通过任意文本编辑器创建这个文件,添加环境变量键值对,然后在容器启动时通过 --env-file
参数传入。
举个例子:
$ echo DB_HOST=test > env-vars.txt
$ echo APP=backend >> env-vars.txt
$ cat env-vars.txt
DB_HOST=test
APP=backend
我们创建了一个名为 env-vars.txt
的 env-file,并添加了两个变量:DB_HOST
和 APP
。
然后我们启动容器并传入该文件:
$ docker run -it --env-file env-vars.txt alpine:latest /bin/sh
/ # env
HOSTNAME=984d3294e8a3
SHLVL=1
HOME=/root
APP=backend
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
DB_HOST=test
可以看到,容器内的环境变量已经成功注入。应用就可以直接使用这些变量了。
3. Kubernetes 中的 ConfigMap
在 Kubernetes 中,我们使用 ConfigMap
来传递环境变量。ConfigMap 是一种 Kubernetes API 对象,用于存储非敏感的配置数据。
与 Docker 的 env-file
不同,ConfigMap 是通过 YAML 文件定义的 Kubernetes 资源对象。我们在 data
字段中定义键值对。
来看一个 ConfigMap 的 YAML 示例:
# env-vars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
DB_HOST: test
APP: backend
使用 kubectl
创建这个 ConfigMap:
$ kubectl apply -f env-vars.yaml
configmap/myconfigmap created
接下来,我们需要创建一个 Pod,并在其中引用这个 ConfigMap:
# mypod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: alpine
command: ["sleep", "3600"]
envFrom:
- configMapRef:
name: myconfigmap
部署 Pod:
$ kubectl apply -f mypod.yaml
pod/mypod created
进入容器查看环境变量:
$ kubectl exec -it mypod -- /bin/sh
/ # env
...
APP=backend
DB_HOST=test
✅ 成功看到注入的变量,说明 ConfigMap 已生效。
4. Kubernetes 中的 Secret
Secret 是专门用于存储敏感数据的 Kubernetes 对象,如密码、密钥或 API Token。 它与 ConfigMap 类似,但数据是以 base64 编码形式存储的。
使用 Secret 的流程和 ConfigMap 类似,只是数据需要先编码。
先对敏感信息进行 base64 编码:
$ echo PASSWORD123 | base64
UEFTU1dPUkQxMjMK
$ echo MySecretKey | base64
TXlTZWNyZXRLZXkK
创建 Secret 的 YAML 文件:
# mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
db_password: UEFTU1dPUkQxMjMK
secret_key: TXlTZWNyZXRLZXkK
应用 Secret:
$ kubectl apply -f mysecret.yaml
secret/mysecret created
创建 Pod 并引用 Secret:
# mysecretpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysecretpod
spec:
containers:
- name: mysecretcontainer
image: alpine
command: ["sleep", "3600"]
envFrom:
- secretRef:
name: mysecret
部署 Pod:
$ kubectl apply -f mysecretpod.yaml
pod/mysecretpod created
进入容器查看环境变量:
$ kubectl exec -it mysecretpod -- /bin/sh
/ # env
...
db_password=PASSWORD123
secret_key=MySecretKey
✅ 成功解码并注入变量,说明 Secret 已生效。
5. 总结
功能 | Docker | Kubernetes |
---|---|---|
传递非敏感环境变量 | --env-file |
ConfigMap |
传递敏感环境变量 | --env-file (不推荐) |
Secret |
Docker 的 --env-file
提供了一种从外部文件注入环境变量的方式,避免了将配置硬编码到镜像中。而 Kubernetes 中的 ConfigMap
和 Secret
则分别对应了非敏感和敏感配置的管理方式。
✅ ConfigMap 适合存储明文配置,如数据库地址、应用模式等。
✅ Secret 更适合存储敏感信息,如密码、密钥等,但要注意其 base64 并非加密,仅用于编码。
⚠️ 踩坑提醒:Secret 的 base64 编码并不是加密,不要误以为它能提供安全性。如需加密,应配合 Kubernetes 的加密功能(如 KMS)或使用外部 Vault。
通过合理使用 ConfigMap 和 Secret,我们可以实现配置与容器镜像的解耦,提升应用的可移植性和安全性。