Django 和 Deployment 中的私有设置
Private settings in Django and Deployment
我正在使用 Django 并使用 Ansible 部署我的堆栈。最后,我使用 Fabric 部署我的 Django 项目,从 GitHub 中提取我的代码。
我的问题:处理 Django settings.py 文件中私人设置的最佳做法是什么,例如电子邮件或 S3 的密码?目前,在重新启动应用程序服务器之前,我在部署脚本的末尾将 settings_production.py 从我的机器文件传输到生产机器。此文件包含我没有放入 settings.py 作为回购的一部分的设置。
在我的 settings.py 结尾处,我添加了类似
的内容
try:
from settings_production import *
except ImportError:
pass
有更好的方法吗?
我认为您可以创建一个 settings.py
,然后在其中执行:
try:
from local_settings import *
except ImportError:
pass
你必须把它放在 settings.py
的末尾。对于您的开发环境,您创建 local_settings.py
,在那里您将所有生产配置覆盖为您的本地配置。通过这种方式,您可以跟踪生产设置的更改,同时保持本地尽可能灵活。
但唯一的问题是,如果您不小心忘记覆盖 local_settings.py
中的 settings.py
,您最终可能会使用生产设置,这可能是有害的。
对我来说,我只是在本地添加这个 ~/.bashrc
以确保 django 总是使用 local_settings.py
:
export DJANGO_SETTINGS_MODULE=app.settings.local_settings
编辑:
如果您不想回购来跟踪更改并且不想接触生产服务器,我认为没有更好的方法来复制设置文件。毕竟,您的更改必须以某种方式从您的计算机转移到生产中!也许你可以 rsync
文件,但它并不比织物 put
好,对吧?
答案是:http://12factor.net/config.
您应该通过不同的设置模块来管理环境之间与代码相关的差异。这方面的一个例子是在本地添加 debug_toolbar
到 INSTALLED_APPS
,同时在生产中删除它。要处理这个方面,而不是使用旧的 try: import except ImportError: ...
习惯用法并在本地计算机上保持不受版本控制 local_settings.py
,您应该将所有设置模块保留在版本控制中,包括您的本地设置。然后,在 wsgi.py
和 manage.py
中,使用 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.conf.local')
将您的项目默认为使用本地设置。在开发/生产中,您添加一个环境变量以使用相应的设置模块(例如,DJANGO_SETTINGS_MODULE=myproject.conf.dev
)。
当您使用 12 Factor 时,不再需要将某些设置模块置于版本控制之外,因为使用 12 Factor,您无需将任何密码或敏感设置直接放入设置模块。您改为将它们保留在环境中并像这样访问它们:
# Inside of a settings module
FOO_PASSWORD = os.environ['FOO_PASSWORD']
在 Heroku, this setup is simple, because you can enter config vars 这样的环境中,通过网络界面为您的应用程序。
我推荐几乎所有 12 Factor's principles, esp things like disposability, logs, and config。
合理牺牲
如果你想维护一个额外的设置模块,脱离版本控制,避免在本地开发期间使用环境变量(我不怪你),你仍然可以遵循上述原则,并且在版本控制中 是 的本地设置模块的底部添加 try: from some_other_local import * except: pass
。这将允许您仅在本地设置必要的覆盖设置,同时仍将其余本地设置(例如,本地数据库、相对静态/媒体文件路径、已安装的应用程序等)保留在版本控制中,从而为您提供最佳两个世界。
额外资源
我认为如何做到这一点的一个很好的例子是 jcalazan/ansible-django-stack which besides the code includes a few links, in particular this one about How to deploy encrypted copies of your SSL keys and other files with Ansible and OpenSSL。
所有配置都应使用环境变量完成,因为:
- 他们与语言无关
- 他们通常不太可能被意外签入源代码管理
- 在某些部署环境中,这是您唯一可用的配置形式
所以我们的想法是让您的部署完全可以使用环境变量标志进行配置。
在开发环境中 direnv 是一种按目录设置环境变量的简单方法。
您还可以拥有一种机制,允许开发人员在其开发环境中使用 gitignored python 文件覆盖设置:
# the manage.py file
import os
if __name__ == '__main__':
if os.path.isfile('local_overrides.py'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'local_overrides')
else:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
execute_from_command_line(sys.argv)
和 local_overrides 文件:
# the local_overrides.py file
import os
os.environ["DB_NAME"] = "abc"
from settings import *
INSTALLED_APPS.append('xyz')
请注意,这与建议在末尾添加 try/import 的其他答案不同。这里 local_overrides 文件完全控制,这种设置有三个优点:
- 您可以使用
os.environ
在 python 文件中方便地从设置模块导入之前设置环境变量
- 因为它在 python 文件中,它会触发热重载,而其他环境变量操作工具需要重新启动您的开发服务器
- 您可以从任意数量的设置模块中导入,这样可以更轻松地进行试验
这符合 12factor 建议,但增加了开发人员的便利性。
请注意,12factor 建议不要为每个环境设置模块。我认为环境和“运行 模式”之间存在差异,后者基本上分为三种:在服务器上、在开发模式下或作为单元测试。
因此避免将“生产”设置作为 python 模块,而更喜欢将“服务器”设置作为 python 模块服务于所有服务器环境,因为它们有相似之处,但使用精细的环境变量来区分它们从彼此。
我正在使用 Django 并使用 Ansible 部署我的堆栈。最后,我使用 Fabric 部署我的 Django 项目,从 GitHub 中提取我的代码。
我的问题:处理 Django settings.py 文件中私人设置的最佳做法是什么,例如电子邮件或 S3 的密码?目前,在重新启动应用程序服务器之前,我在部署脚本的末尾将 settings_production.py 从我的机器文件传输到生产机器。此文件包含我没有放入 settings.py 作为回购的一部分的设置。
在我的 settings.py 结尾处,我添加了类似
的内容try:
from settings_production import *
except ImportError:
pass
有更好的方法吗?
我认为您可以创建一个 settings.py
,然后在其中执行:
try:
from local_settings import *
except ImportError:
pass
你必须把它放在 settings.py
的末尾。对于您的开发环境,您创建 local_settings.py
,在那里您将所有生产配置覆盖为您的本地配置。通过这种方式,您可以跟踪生产设置的更改,同时保持本地尽可能灵活。
但唯一的问题是,如果您不小心忘记覆盖 local_settings.py
中的 settings.py
,您最终可能会使用生产设置,这可能是有害的。
对我来说,我只是在本地添加这个 ~/.bashrc
以确保 django 总是使用 local_settings.py
:
export DJANGO_SETTINGS_MODULE=app.settings.local_settings
编辑:
如果您不想回购来跟踪更改并且不想接触生产服务器,我认为没有更好的方法来复制设置文件。毕竟,您的更改必须以某种方式从您的计算机转移到生产中!也许你可以 rsync
文件,但它并不比织物 put
好,对吧?
答案是:http://12factor.net/config.
您应该通过不同的设置模块来管理环境之间与代码相关的差异。这方面的一个例子是在本地添加 debug_toolbar
到 INSTALLED_APPS
,同时在生产中删除它。要处理这个方面,而不是使用旧的 try: import except ImportError: ...
习惯用法并在本地计算机上保持不受版本控制 local_settings.py
,您应该将所有设置模块保留在版本控制中,包括您的本地设置。然后,在 wsgi.py
和 manage.py
中,使用 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.conf.local')
将您的项目默认为使用本地设置。在开发/生产中,您添加一个环境变量以使用相应的设置模块(例如,DJANGO_SETTINGS_MODULE=myproject.conf.dev
)。
当您使用 12 Factor 时,不再需要将某些设置模块置于版本控制之外,因为使用 12 Factor,您无需将任何密码或敏感设置直接放入设置模块。您改为将它们保留在环境中并像这样访问它们:
# Inside of a settings module
FOO_PASSWORD = os.environ['FOO_PASSWORD']
在 Heroku, this setup is simple, because you can enter config vars 这样的环境中,通过网络界面为您的应用程序。
我推荐几乎所有 12 Factor's principles, esp things like disposability, logs, and config。
合理牺牲
如果你想维护一个额外的设置模块,脱离版本控制,避免在本地开发期间使用环境变量(我不怪你),你仍然可以遵循上述原则,并且在版本控制中 是 的本地设置模块的底部添加 try: from some_other_local import * except: pass
。这将允许您仅在本地设置必要的覆盖设置,同时仍将其余本地设置(例如,本地数据库、相对静态/媒体文件路径、已安装的应用程序等)保留在版本控制中,从而为您提供最佳两个世界。
额外资源
我认为如何做到这一点的一个很好的例子是 jcalazan/ansible-django-stack which besides the code includes a few links, in particular this one about How to deploy encrypted copies of your SSL keys and other files with Ansible and OpenSSL。
所有配置都应使用环境变量完成,因为:
- 他们与语言无关
- 他们通常不太可能被意外签入源代码管理
- 在某些部署环境中,这是您唯一可用的配置形式
所以我们的想法是让您的部署完全可以使用环境变量标志进行配置。
在开发环境中 direnv 是一种按目录设置环境变量的简单方法。
您还可以拥有一种机制,允许开发人员在其开发环境中使用 gitignored python 文件覆盖设置:
# the manage.py file
import os
if __name__ == '__main__':
if os.path.isfile('local_overrides.py'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'local_overrides')
else:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
execute_from_command_line(sys.argv)
和 local_overrides 文件:
# the local_overrides.py file
import os
os.environ["DB_NAME"] = "abc"
from settings import *
INSTALLED_APPS.append('xyz')
请注意,这与建议在末尾添加 try/import 的其他答案不同。这里 local_overrides 文件完全控制,这种设置有三个优点:
- 您可以使用
os.environ
在 python 文件中方便地从设置模块导入之前设置环境变量
- 因为它在 python 文件中,它会触发热重载,而其他环境变量操作工具需要重新启动您的开发服务器
- 您可以从任意数量的设置模块中导入,这样可以更轻松地进行试验
这符合 12factor 建议,但增加了开发人员的便利性。
请注意,12factor 建议不要为每个环境设置模块。我认为环境和“运行 模式”之间存在差异,后者基本上分为三种:在服务器上、在开发模式下或作为单元测试。
因此避免将“生产”设置作为 python 模块,而更喜欢将“服务器”设置作为 python 模块服务于所有服务器环境,因为它们有相似之处,但使用精细的环境变量来区分它们从彼此。