Python: 高级用法
深入了解您的 Python 部署
👋 欢迎来到 Stackhero 文档!
Stackhero 提供现成的 Python 云 解决方案,具有众多优势,包括:
- 通过简单的
git push在几秒钟内 部署您的应用程序。- 使用您自己的域名,并享受 HTTPS 证书的自动配置以增强安全性。
- 享受 自动备份、一键更新,以及简单、透明和可预测的定价,让您高枕无忧。
- 通过私有和专用的 VM获得最佳的性能和强大的安全性。
节省时间并简化您的生活:只需 5 分钟即可试用 Stackhero 的 Python 云托管 解决方案!
部署非 main 分支
到目前为止,我们使用 git push stackhero main 命令将 main 分支部署到生产环境。
如果您需要部署其他分支,可以使用以下命令,其中 <BRANCH> 是您希望部署的分支名称:
git push stackhero <BRANCH>:main
例如,如果您想部署 production 分支,只需运行:
git push stackhero production:main
部署标签而不是分支
您可以选择部署标签而不是分支。要部署特定标签,请在以下命令中将 <TAG> 替换为您想要的标签:
git push stackhero '<TAG>^{}:main'
例如,要部署标签 v1.0.0,您需要执行:
git push stackhero 'v1.0.0^{}:main'
^{}语法确保您推送的是标记的提交而不是标签引用本身。
部署特定提交
除了部署分支或标签,您还可以通过使用其哈希值来部署特定提交。将 <COMMIT_HASH> 替换为您希望部署的提交的哈希值:
git push -f stackhero <COMMIT_HASH>:main
例如,要部署哈希为 abcde 的提交,请运行:
git push -f stackhero abcde:main
回滚到以前的版本
如果最近的部署引入了问题,您可以通过部署早期的提交来回滚。首先,通过运行以下命令识别提交哈希:
git log
此命令显示每个提交的日期、哈希和描述。
例如,输出可能如下所示:
git log
commit cccc8b3ebdccb9abc1926ef49ee589dae5c5fe06 (HEAD -> main, stackhero/main)
Author: Developer
Date: Fri Apr 28 09:36:18 +0000
Break the code
commit bbbb622301772072c3d82f3cc0d91e29e6e84901
Author: Developer
Date: Wed Apr 26 12:49:28 +0000
Update the code
commit aaaa1d8b06535b413e0df8298ccf52339dfef3ff
Author: Developer
Date: Wed Apr 26 12:44:50 +0000
Improve the code
如果当前生产部署是提交 "Break the code"(哈希以 cccc 开头),而您希望回滚到之前的提交 "Update the code"(哈希以 bbbb 开头),请执行:
git push -f stackhero bbbb622301772072c3d82f3cc0d91e29e6e84901:main
为了防止部署损坏的代码并提高生产的稳定性,强烈建议设置一个“staging”环境。
位于开发和生产之间,staging 环境提供了一个接近生产设置的副本。它帮助您在实际部署前彻底测试代码。
使用 staging 增强了您对代码功能和性能的信心,从而实现更稳健的生产部署。
这种类型的环境将在文档后面讨论。
设置 staging 环境
当与开发和生产环境一起使用时,staging 环境是一种最佳实践。它复制生产环境,以便您可以在上线前测试更新和更改,从而降低生产中的问题风险。
staging 环境必须紧密反映生产环境。
然而,它应该使用生产数据库或连接服务的克隆版本,而不是实时生产数据库。
如果您的 Python 服务依赖于数据库或其他服务,请在新的
<Project> - Staging堆栈中重新创建它们。
按照以下步骤使用 Stackhero 设置 staging 环境:
- 在 Stackhero 仪表板上,将现有堆栈从
<Project>重命名为<Project> - Production。例如,如果您的项目名为Chat Bot,则堆栈变为Chat Bot - Production。 - 创建一个名为
<Project> - Staging的新堆栈。对于Chat Bot项目,堆栈变为Chat Bot - Staging。 - 在 staging 堆栈中启动一个 Python 服务。
- 获取
git remote命令并按照 部署到 staging 环境 文档中的说明进行操作。
此配置确保您拥有一个功能齐全的 staging 环境,以便在生产部署前测试更新。
部署到 staging 环境
强烈建议维护独立的 staging 和生产环境。要管理多个环境,请首先重命名当前的远程仓库。例如,将远程 stackhero 重命名为 stackhero-production:
git remote rename stackhero stackhero-production
接下来,为您的 staging 环境创建一个新的 Python 服务。获取 git remote add 命令并通过将 <XXXXXX> 替换为您的服务域来修改它:
-
原始命令:
git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git -
修改后的命令:
git remote add stackhero-staging ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
然后,您可以使用以下命令部署到任一环境:
-
部署到 staging:
git push stackhero-staging main -
部署到生产:
git push stackhero-production main
为了改进部署过程,我们建议使用 改进版 Makefile。
使用这个改进的
Makefile,部署到生产或 staging 变得像运行make deploy-production或make deploy-staging一样简单。
改进版 Makefile
以下是一个支持多规则的改进版 Makefile:
make dev(或简单地make):以开发模式启动应用程序。make deploy:将应用程序部署到名为stackhero的远程。这在您只有一个 Stackhero 实例时效果很好。make deploy-production:将应用程序部署到名为stackhero-production的远程。make deploy-staging:将应用程序部署到名为stackhero-staging的远程。
此
Makefile旨在处理代码未更改的情况,避免 "Everything up-to-date" 错误。
复制并粘贴以下内容作为您的新 Makefile:
# 默认执行规则,当调用 "make" 时不带参数
.DEFAULT_GOAL := dev
# Stackhero for Python 将在您的实例上执行 "run" 规则。
# 这是在您的生产和 staging 环境中运行的命令。
run:
ENV=production gunicorn app:app \
--error-logfile - \
-b 0.0.0.0:8080
# 在开发环境中使用的命令
dev:
python app.py
# "deploy" 规则用于部署到 "stackhero" 实例。
# 适用于只有一个实例的情况。
deploy:
@$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero DEPLOY_BRANCH=main
# "deploy-*" 规则部署到名为 "stackhero-*" 的实例。
# 例如,运行 "make deploy-production" 部署到 "stackhero-production",
# 或 "make deploy-staging" 部署到 "stackhero-staging"。
deploy-%:
@$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero-$* DEPLOY_BRANCH=main
# 内部部署规则。请勿修改。
deploy-script:
@echo "正在将分支 \"${DEPLOY_BRANCH}\" 部署到 \"${DEPLOY_REMOTE}\"..."
@echo
@if [ -n "$$(git status --porcelain)" ]; then \
echo "无法部署,因为有未提交的更改:"; \
echo "\e[0m"; \
git status -s; \
echo ""; \
echo "\e[0;31m"; \
echo "您可以使用此命令提交更改:"; \
echo "git add -A . && git commit -m \"您的消息\""; \
echo "\e[0m"; \
exit 1; \
fi
@git push --dry-run ${DEPLOY_REMOTE} ${DEPLOY_BRANCH} 2>&1 | grep -q -F "Everything up-to-date"; \
EXIT_CODE=$$?; \
if [ $$EXIT_CODE -eq 0 ]; then \
echo -n "没有新内容可部署... 强制部署(这将创建一个新提交)? (y/N) "; \
read answer && \
case $$answer in \
y|Y|yes|YES) \
git commit --allow-empty -m "Force update for deploy purpose to \"${DEPLOY_REMOTE}\"" ; \
;; \
*) \
echo "没有内容可部署!"; \
exit 1; \
;; \
esac \
fi
git push ${DEPLOY_REMOTE} ${DEPLOY_BRANCH}
处理机密信息(环境变量)
在某个时候,您需要存储诸如数据库或第三方服务的令牌和密码等机密信息。重要的是要安全地存储这些信息。避免将它们直接嵌入到您的仓库或代码中,因为这会带来重大安全风险。
使用环境变量提供了两个关键好处:
- 您的机密信息从未存储在您的 Git 仓库中,从而降低了未经授权访问的风险。
- 您可以为不同的环境使用不同的凭据,例如在生产中使用生产数据库,在开发中使用开发数据库。
为开发设置环境变量
在开发环境中,在项目根目录创建一个 .env 文件。此文件应从 Git 中排除,以确保它永远不会被提交。
要自动读取 .env 文件,您可以使用 python-dotenv 模块:
pip install python-dotenv
pip freeze > requirements.txt
然后,在项目根目录创建一个 .env 文件并添加您的变量:
ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"
# ...
最后,通过将 .env 添加到 .gitignore 中,确保它被 Git 排除:
echo ".env" >> .gitignore
为 staging 和生产设置环境变量
.env 文件对于 staging 和生产环境来说不够安全。相反,Stackhero 允许您将环境变量直接安全地存储在您的 Python 服务配置中。
您可以通过选择您的 Python 服务,然后点击“配置”按钮,在 Stackhero 仪表板中设置这些变量。
Stackhero 上的 Python 环境变量
在 Python 中访问环境变量
在 Python 中访问环境变量很简单。只需使用 os.environ.get(),如下所示:
import os
print(os.environ.get('ENV'))
例如,使用环境变量连接到 Redis 服务器可以这样完成:
import os
import redis
r = redis.from_url(os.environ.get("REDIS_URL"))
在开发环境中,在 .env 文件中设置 REDIS_URL 如下:
REDIS_URL="redis://localhost:6379"
对于生产和 staging,在 Stackhero 仪表板的 Python 服务配置中定义 REDIS_URL:
REDIS_URL="rediss://default:<yourPassword>@<XXXXXX>.stackhero-network.com:6380"
管理 Python 包
使用 requirements.txt 文件管理 Python 包是一种最佳实践。此文件列出了运行代码所需的所有包及其版本,以确保可靠性。
保持此文件的更新可确保:
- 安装所有必需的包。
- 仅使用兼容的包版本。
在部署到您的 Stackhero 实例时,requirements.txt 中指定的包会自动安装。
在安装新包后,运行以下命令生成或更新 requirements.txt:
pip freeze > requirements.txt
打开 UDP/TCP 端口
大多数 Python 应用程序使用 HTTP 端口 80(HTTP)和 443(HTTPS)。
如果您的应用程序需要打开其他端口或使用其他协议(TCP 或 UDP),您可以在 Stackhero 仪表板上的 Python 服务中调整“端口重定向”设置。
对于每个额外的端口,指定入口端口(面向公众)、目标端口(由您的 Python 应用程序使用)和协议(TCP 或 UDP)。
Stackhero 仪表板中的端口重定向
文件存储
对于存储用户照片或文档等文件,通常最好使用对象存储解决方案。
对象存储允许您在多个服务或实例之间共享文件,并将存储与代码分离,遵循最佳实践。
我们推荐 MinIO,这是一种快速且强大的解决方案,兼容 Amazon S3 协议。
如果您更喜欢本地文件存储,可以使用位于 /persistent/storage/ 的 Python 实例提供的持久存储。然而,在大多数情况下不推荐这种方法。
警告:切勿将数据存储在
/persistent/storage/文件夹之外!将数据存储在此文件夹之外可能会导致在实例重启、更新或推送新代码时数据丢失。
Apple/macOS:保存您的 SSH 私钥密码
在 macOS 上,每次推送代码时输入 SSH 私钥密码可能会很麻烦。虽然安全性至关重要,但您可以使用 Apple 的钥匙串安全地保存密码,而不是从密钥中删除它。
要存储名为 id_ed25519 的密钥的密码,请执行:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
之后,您将不再被提示输入密钥密码,从而节省时间和精力。
如果您使用的是 RSA 密钥,请在命令中将
id_ed25519替换为id_rsa:ssh-add --apple-use-keychain ~/.ssh/id_rsa