.env 文件全流程教程

.env 文件全流程教程 · Env File Full Guide

.env 文件零基础完整教程(开发→打包→部署全链路)

什么是.env、语法、python-dotenv使用、git规范、打包分发、容器部署、生产安全规范全覆盖

一、什么是 .env 文件,解决什么核心问题

.env 全称 environment(环境变量文件),是纯文本无后缀隐藏文件,专门存放程序环境变量

核心作用:隔离敏感信息与环境配置,禁止把密码、密钥、数据库地址写死在代码里。

❌ 硬编码(致命错误)

# db.py
DB_HOST = "127.0.0.1"
DB_USER = "root"
DB_PWD = "123456"  # 密码明文写代码
API_KEY = "sk-xxx密钥"

上传代码到Git会泄露账号密钥,开发/生产环境切换需要改代码、重新打包。

✅ 使用 .env 规范方案

# .env
DB_HOST=127.0.0.1
DB_USER=root
DB_PWD=123456
API_KEY=sk-xxx密钥
# db.py 从环境读取,无明文密码
import os
DB_PWD = os.getenv("DB_PWD")

配置与代码完全分离,切换环境仅替换.env,密钥不会提交代码仓库。

.env 四大核心价值

安全隔离 数据库密码、API密钥、token不存入代码仓库

多环境切换 dev/test/prod三套配置一键切换

统一标准 Python/JS/Go/Docker全生态通用

部署兼容 本地开发、服务器、容器共用一套变量名

二、.env 基础语法与文件规范

硬性语法规则:键=值,等号两侧不能空格;#为注释;字符串不需要引号(有空格才加双引号)

2.1 标准 .env 示例

# 数据库配置
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=Root@123456

# 布尔/数字
DEBUG=true
SERVER_PORT=8000
TIMEOUT=30

# 带空格字符串必须双引号
APP_NAME="后端演示服务"

# 空变量
REDIS_PASSWORD=

# 多值数组(逗号分隔,代码自行拆分)
ALLOW_ORIGIN="http://localhost:3000,https://prod.com"

2.2 配套模板文件 .env.example

核心规范:.env 禁止上传Git,必须提供模板 .env.example,仅保留变量名,删除真实密钥。

# .env.example(可提交git)
DB_HOST=填写数据库地址
DB_PORT=3306
DB_USER=root
DB_PASSWORD=请填写数据库密码
API_KEY=第三方密钥留空待填充

2.3 多环境文件命名规范

  • .env.dev 本地开发环境
  • .env.test 测试服务器环境
  • .env.prod 生产服务器环境
  • .env 兜底默认配置

三、Python读取.env:python-dotenv完整使用

Python原生os只能读取系统环境变量,读取本地.env文件需要第三方库 python-dotenv

安装依赖

pip install python-dotenv
写入pyproject.toml dev依赖

基础加载 .env

from dotenv import load_dotenv load_dotenv() import os print(os.getenv(“DB_HOST”))
自动读取项目根目录.env

指定环境文件

load_dotenv(“.env.prod”)
手动加载生产配置文件

3.1 最简读取代码

# config.py 全局配置文件
from dotenv import load_dotenv
import os
# 加载根目录.env,会把变量注入系统环境
load_dotenv()

# 读取环境变量,第二个参数为默认值
DB_HOST = os.getenv("DB_HOST", "127.0.0.1")
DB_PORT = int(os.getenv("DB_PORT", 3306))
DEBUG = os.getenv("DEBUG", "false") == "true"
API_KEY = os.getenv("API_KEY")

# 缺失密钥直接抛出异常,阻断程序启动
if not API_KEY:
    raise ValueError("缺少API_KEY环境变量,请检查.env文件")

3.2 多环境动态加载(开发常用)

from dotenv import load_dotenv
import os

# 通过环境变量区分当前环境,本地/CI/服务器通用
env_mode = os.getenv("ENV_MODE", "dev")
env_file = f".env.{env_mode}"
load_dotenv(env_file)
print(f"当前加载环境配置:{env_file}")

本地启动命令:ENV_MODE=dev python main.py

四、开发阶段完整流程

  1. 项目根目录新建 .env.example 模板,所有变量名齐全,无真实密码
  2. 复制模板为 .env.dev,填充本地数据库、测试密钥
  3. .gitignore 写入 .env* 屏蔽所有环境文件,仅放行 .env.example
  4. 代码统一通过 config.py 读取环境变量,全程无硬编码
  5. 切换环境只需修改启动时 ENV_MODE 参数,不用改代码

.gitignore 标准配置

# 屏蔽所有真实环境文件
.env
.env.dev
.env.test
.env.prod
# 仅保留模板文件不屏蔽
!.env.example

五、Git仓库管理规范(安全核心)

Git三条铁律

1. 所有 .env、.env.* 禁止提交到远程仓库

2. 必须提交 .env.example 模板,保证新人拉取项目可直接复制使用

3. 任何密码、token、私钥绝不写入代码、注释、提交记录

高危警告:一旦误提交.env含密钥文件,即使删除提交记录,Git历史仍存在泄露风险,必须重置仓库或轮换所有密钥!

六、项目打包环节处理 .env

场景1:源码打包(sdist/uv build)

打包工具默认不会打包 .env 文件,只会打包代码与pyproject.toml,不会泄露本地密钥;分发源码包给他人,对方复制.env.example使用。

场景2:exe打包(PyInstaller)

  1. 打包时不要将本地.env打进exe,避免本机密码随程序分发
  2. 程序运行目录外置.env,由使用者自行填写配置
  3. 打包脚本排除.env文件:–exclude .env
pyinstaller main.py --exclude .env

场景3:Docker镜像打包

Dockerfile中绝对不能COPY .env进入镜像,镜像推送仓库会泄露密钥;两种标准方案:

  1. 方案1:运行容器时通过 -e / –env-file 外部传入.env
  2. 方案2:生产使用K8s ConfigMap/Secret管理环境变量

七、部署全链路完整方案(本地→服务器→Docker→K8s)

本地开发 .env.dev 测试服务器 .env.test 生产容器 环境变量注入 线上运行

7.1 本地开发(电脑)

使用.env.dev,load_dotenv自动加载,所有配置本地存储,不上传Git

7.2 物理云服务器部署

  1. 服务器项目目录新建 .env.prod,填入线上数据库、生产密钥
  2. 设置文件权限:chmod 600 .env.prod 仅root可读,防止其他用户读取密钥
  3. 启动脚本指定加载生产环境:ENV_MODE=prod python main.py
  4. 服务器不提交.env到代码仓库,单独运维保管

7.3 Docker 容器部署

错误写法(密钥打进镜像)

# Dockerfile 禁止这么写
COPY .env .

正确运行方式(外部注入)

# 外部传入环境文件,镜像不含密钥
docker run --env-file .env.prod -p 8000:8000 app:latest
# 单独传入单个变量
docker run -e DB_HOST=10.0.0.1 app:latest

7.4 Kubernetes 生产集群

生产禁止使用.env文件,统一使用K8s Secret存储密钥、ConfigMap存储普通配置,集群自动注入容器环境变量,密钥加密存储,不落地文件。

八、生产环境安全红线

绝对禁止操作

❌ 代码、注释、提交记录写数据库密码、API密钥

❌ 将.env打包进exe、Docker镜像、源码包

❌ .env提交到Git/Gitee/GitHub远程仓库

❌ 生产服务器.env文件权限开放给所有用户

❌ 线上容器镜像内置.env配置文件

推荐安全规范

✅ 开发本地使用.env,生产使用系统/容器原生环境变量

✅ 密钥统一轮换机制,一旦泄露立刻重置

✅ 服务器.env权限chmod 600,仅所有者读写

✅ 集群环境使用Secret加密存储敏感信息

九、高频踩坑与解决方案

问题现象原因解决方案
load_dotenv读不到变量 1.文件名错误 2.等号两侧有空格 3.文件不在项目根目录 文件放根目录,key=value无空格,指定文件路径load_dotenv(“.env.dev”)
数字读取出来是字符串 .env所有值默认字符串 int(os.getenv(“PORT”, 8000))强制转换
Git提交把.env上传了 .gitignore未配置,新用户复制遗漏 立即轮换所有密钥,清理git历史,完善.gitignore与模板
Docker镜像内置.env泄露密钥 Dockerfile COPY .env 删除COPY .env,运行时–env-file外部传入
多人开发配置冲突 共用.env,本地数据库不同 每人使用独立.env.dev,统一.env.example模板
生产.env被其他用户读取 文件权限755/644 chmod 600 .env.prod,仅管理员可读

十、全流程标准落地模板

1. 项目目录结构

project/
├── .gitignore          # 屏蔽.env系列
├── .env.example        # 模板,可提交git
├── .env.dev            # 本地开发(不上传)
├── config.py           # 统一读取环境变量
├── pyproject.toml      # 依赖含python-dotenv
├── main.py             # 程序入口
└── Dockerfile          # 打包不复制.env

2. .gitignore 标准内容

.env
.env.*
!.env.example
__pycache__
*.pyc
dist
build

3. pyproject.toml 依赖配置

[project.optional-dependencies]
dev = [
  "python-dotenv>=1.0.0"
]

4. config.py 通用加载代码

from dotenv import load_dotenv
import os

# 识别环境
env_mode = os.getenv("ENV_MODE", "dev")
env_path = f".env.{env_mode}"
load_dotenv(env_path)

# 基础配置
DEBUG = os.getenv("DEBUG", "false") == "true"
SERVER_PORT = int(os.getenv("8000"))
DB_HOST = os.getenv("DB_HOST")
DB_USER = os.getenv("DB_USER")
DB_PWD = os.getenv("DB_PASSWORD")

# 强制校验核心密钥
required_vars = ["DB_HOST", "DB_PASSWORD"]
for var in required_vars:
    if not os.getenv(var):
        raise RuntimeError(f"环境变量 {var} 未配置,请检查 {env_path} 文件")
全链路总结:开发本地.env隔离密钥→git仅保留模板→打包排除环境文件→部署时外部注入环境,生产优先使用集群Secret而非本地.env文件

.env File Full Guide (Dev → Build → Deploy)

What is .env, syntax, python-dotenv, git rules, packaging, Docker/K8s deployment security

1 What is .env File & Core Purpose

.env = environment file, stores environment variables, separates sensitive credentials from source code.

Never hardcode DB password, API key inside your Python scripts.

2 Syntax & Template .env.example

Syntax: KEY=VALUE, no space around =, # for comment.

.env.example: commit to git with placeholder values, real .env files ignored by gitignore.

3 python-dotenv Usage

pip install python-dotenv

from dotenv import load_dotenv
import os
load_dotenv(".env.dev")
db_pwd = os.getenv("DB_PASSWORD")

4 Multi Environment Separation

  • .env.dev local dev
  • .env.test staging
  • .env.prod production

Launch command: ENV_MODE=prod python main.py

5 Git Ignore Rule

# .gitignore
.env
.env.*
!.env.example

Never push real .env to remote repo, risk credential leak.

6 Packaging Rules

  • Source dist: .env excluded by default
  • PyInstaller: exclude .env from binary
  • Docker: Do NOT COPY .env into image

7 Full Deployment Flow

Local PC: .env.dev

VM Server: .env.prod with chmod 600 permission

Docker: pass env via –env-file at runtime

docker run --env-file .env.prod app

K8s: Use Secret for secrets, ConfigMap for plain config (no .env file)

8 Production Security Rules

  • No credentials in source code / git history
  • No .env inside docker images / executable packages
  • Restrict file permission chmod 600 on server .env
  • Rotate keys immediately after credential leak
  • Cluster use encrypted Secret instead of local .env file

Common Errors

  • Spaces around KEY=VALUE cause read failure
  • All values read as string, cast int/bool manually
  • Accidentally commit .env → rotate all secrets

Standard Project Structure

project/
├── .gitignore
├── .env.example
├── .env.dev
├── config.py
├── pyproject.toml
├── main.py
└── Dockerfile