尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

《Makefile + Shell 脚本 + .env 配置:打造一键化开发的 DevOps 利器》

《Makefile + Shell 脚本 + .env 配置:打造一键化开发的 DevOps 利器》 《Makefile Shell 脚本 .env 配置打造一键化开发的 DevOps 利器》引言在上一篇文章中我们成功用 Docker Compose 跑起了整个服务栈。但每次都要输入冗长的docker-compose --env-file .env.development up -d还要记住各种数据库迁移命令时间久了非常痛苦。本文为你展示项目中的“自动化三剑客”Makefile命令调度中心封装所有繁琐操作set_env.sh智能环境加载器自动配置环境变量.env.example配置模板保障团队协作的一致性读完本文你将实现一键启动开发环境、一键数据库迁移、一键代码检查的丝滑体验。一、Makefile 核心结构解析1.1 变量定义与默认目标makefile.DEFAULT_GOAL : help DOCKER_COMPOSE ? docker-compose ENV ? development VALID_ENVS : development staging production test.DEFAULT_GOAL : help直接输入make时自动显示帮助菜单。ENV ? development默认环境为开发可通过make dev ENVstaging覆盖。VALID_ENVS合法环境列表配合check_env宏做防呆校验。1.2 辅助宏核心智慧makefiledefine check_env if ! echo $(VALID_ENVS) | grep -qw $(ENV); then \ echo Invalid ENV$(ENV). Must be one of: $(VALID_ENVS); exit 1; \ fi endef define load_env_file $(call check_env) ENV_FILE.env.$(ENV); \ if [ ! -f $$ENV_FILE ]; then \ echo Environment file $$ENV_FILE not found. Please create it.; exit 1; \ fi endef run_with_env bash -c source scripts/set_env.sh $(ENV) $(1)check_env确保用户输入的ENV在合法列表中防止因拼写错误导致误操作。load_env_file检查对应的.env.$(ENV)文件是否存在若缺失则直接报错退出。run_with_env核心宏。在执行任何命令前先source scripts/set_env.sh加载环境变量再执行具体命令。保证所有本地命令如uvicorn、alembic都能读到正确的数据库密码。二、本地开发目标直接在宿主机运行2.1 服务器启动makefiledev: $(call run_with_env,uv run uvicorn app.main:app --reload --port 8000) staging: $(call run_with_env,$(MAKE) _serve ENVstaging) prod: $(call run_with_env,$(MAKE) _serve ENVproduction) _serve: $(call run_with_env,./.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --loop uvloop)make dev开发模式--reload开启热重载代码改动自动重启。make staging/make prod模拟预发布/生产环境无热重载开启--loop uvloop高性能事件循环。2.2 数据库迁移makefilemigrate: $(call run_with_env,uv run alembic upgrade head) migration: if [ -z $(MSG) ]; then \ echo Usage: make migration MSG\describe your change\; exit 1; \ fi $(call run_with_env,uv run alembic revision --autogenerate -m $(MSG)) migrate-downgrade: $(call run_with_env,uv run alembic downgrade -1) migrate-history: $(call run_with_env,uv run alembic history --verbose)make migrate将数据库升级到最新版本。make migration MSGadd user table根据 SQLAlchemy 模型变化自动生成迁移脚本。make migrate-downgrade回滚最近一次迁移。make migrate-history查看迁移历史。注意所有迁移命令都通过run_with_env加载了正确的环境变量所以无需手动指定数据库连接字符串。2.3 代码质量检查makefilelint: uv run ruff check . format: uv run ruff format . typecheck: uv run pyright check: lint typecheck echo All checks passedmake lintRuff 代码风格检查。make formatRuff 自动格式化代码。make typecheckPyright 静态类型检查。make check一键运行所有检查CI/CD 流水线中常用。三、Docker 封装目标3.1 轻量级模式仅 API DBmakefiledocker-up: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) up -d --build db app docker-down: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) down docker-migrate: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) exec -T app /app/.venv/bin/alembic upgrade headmake docker-up只启动db和app服务忽略 valkey、prometheus、grafana。日常开发时节省大量内存。make docker-migrate进入正在运行的app容器内部执行数据库迁移针对的是容器内的数据库而非本地数据库。3.2 全量模式完整监控栈makefilestack-up: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) up -d stack-down: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) down stack-logs: $(call load_env_file) APP_ENV$(ENV) $(DOCKER_COMPOSE) --env-file .env.$(ENV) logs -fmake stack-up启动 Compose 文件中定义的所有服务db、app、valkey、prometheus、grafana、cadvisor用于完整的集成测试或演示环境。make stack-logs实时查看所有服务的日志。四、set_env.sh智能环境加载器4.1 强制 source 执行bashif [[ ${BASH_SOURCE[0]} ${0} ]]; then echo Error: This script must be sourced, not executed. exit 1 fi如果直接执行./set_env.sh会报错退出。必须source ./set_env.sh或. ./set_env.sh确保环境变量在当前 Shell 中生效。4.2 自动查找并加载 .env 文件bashENV${1:-development} ENV_FILE$PROJECT_ROOT/.env.$ENV if [ -f $ENV_FILE ]; then set -a source $ENV_FILE set a else EXAMPLE_FILE$PROJECT_ROOT/.env.example if [ -f $EXAMPLE_FILE ]; then cp $EXAMPLE_FILE $ENV_FILE echo Created $ENV_FILE from template. set -a source $ENV_FILE set a fi fiset -a开启自动导出模式source进来的所有变量自动成为环境变量无需每个都加export。新人友好如果.env.development不存在自动从.env.example复制一份并提示用户填入真实配置。4.3 环境摘要打印bashecho Environment: $ENV echo Database host: ${POSTGRES_HOST:-Not set} echo LLM model: ${DEFAULT_LLM_MODEL:-Not set}打印当前环境、数据库地址、LLM 模型等关键信息让你一眼看清当前终端连接的是哪个环境避免“改错数据库”的低级失误。4.4 快捷函数与别名bashstart_app() { cd $PROJECT_ROOT uvicorn app.main:app --reload --port 8000 } alias dev_envsource $SCRIPT_DIR/set_env.sh development alias stage_envsource $SCRIPT_DIR/set_env.sh staging alias prod_envsource $SCRIPT_DIR/set_env.sh productionstart_app在当前 Shell 环境下直接启动 Uvicorn。dev_env/stage_env/prod_env输入一个别名即可瞬间切换环境配置极其方便。五、.env.example配置体系的“宪法模板”env# Application Settings APP_ENVdevelopment PROJECT_NAMEWeb Assistant DEBUGtrue # LLM Settings OPENAI_API_KEYyour-llm-api-key DEFAULT_LLM_MODELgpt-5-mini # Database Settings POSTGRES_HOSTdb # 容器内为 db本地开发需改为 localhost POSTGRES_DBmydb POSTGRES_USERmyuser POSTGRES_PASSWORDmypassword这是一个“死模板”所有敏感值都是假的。开发者克隆项目后执行source set_env.sh它会自动复制此文件为.env.development开发者只需填入真实密钥。POSTGRES_HOSTdb是容器化部署的默认值本地开发时需手动改为localhost。六、四者联动的数据流图解场景开发者执行make docker-up ENVdevelopmentMakefile解析docker-up调用load_env_file宏。load_env_file检查.env.development存在确认环境合法。Makefile执行docker-compose --env-file .env.development up -d --build db app。docker-compose读取.env.development将POSTGRES_PASSWORD注入db和app容器。容器启动app容器内的 Python 进程通过环境变量连接数据库。场景开发者执行make migrate本地迁移Makefile调用run_with_env宏。run_with_env执行source scripts/set_env.sh development加载.env.development到当前 Shell。执行uv run alembic upgrade headAlembic 读取 Shell 中的DATABASE_URL连接本地数据库执行迁移。七、总结文件角色比喻核心价值Makefile遥控器将繁琐命令简化为make dev、make migrateset_env.sh电源适配器自动加载环境变量防呆防错.env.example空白登记表统一配置 Schema保障团队协作三者结合让开发者从“记忆长命令”中解放出来专注于业务代码编写。
返回列表