I tend to use SQLite when doing Django development, but on a live server something more robust is often needed (MySQL/PostgreSQL, for example). Invariably, there are other changes to make to the Django settings as well: different logging locations / intensities, media paths, etc.
在进行Django开发时,我倾向于使用SQLite,但是在活动服务器上通常需要更健壮的东西(例如,MySQL/PostgreSQL)。同样,对于Django设置还有其他更改:不同的日志记录位置/强度、媒体路径等等。
How do you manage all these changes to make deployment a simple, automated process?
如何管理所有这些更改,使部署成为一个简单、自动化的过程?
14 个解决方案
#1
83
Update: django-configurations has been released which is probably a better option for most people than doing it manually.
更新:django配置已经发布,对于大多数人来说,这可能是一个更好的选择,而不是手工操作。
If you would prefer to do things manually, my earlier answer still applies:
如果您喜欢手工操作,我之前的回答仍然适用:
I have multiple settings files.
我有多个设置文件。
-
settings_local.py
- host-specific configuration, such as database name, file paths, etc. - settings_local。与主机相关的配置,如数据库名、文件路径等。
-
settings_development.py
- configuration used for development, e.g.DEBUG = True
. - settings_development。py -用于开发的配置,例如DEBUG = True。
-
settings_production.py
- configuration used for production, e.g.SERVER_EMAIL
. - settings_production。py -用于生产的配置,例如SERVER_EMAIL。
I tie these all together with a settings.py
file that firstly imports settings_local.py
, and then one of the other two. It decides which to load by two settings inside settings_local.py
- DEVELOPMENT_HOSTS
and PRODUCTION_HOSTS
. settings.py
calls platform.node()
to find the hostname of the machine it is running on, and then looks for that hostname in the lists, and loads the second settings file depending on which list it finds the hostname in.
我把这些和一个设置联系在一起。首先导入settings_local的py文件。然后是另两个中的一个。它决定在settings_local中通过两个设置加载哪个。py - DEVELOPMENT_HOSTS和PRODUCTION_HOSTS。设置。py调用platform.node()来查找正在运行的机器的主机名,然后在列表中查找该主机名,并根据在哪个列表中找到主机名加载第二个设置文件。
That way, the only thing you really need to worry about is keeping the settings_local.py
file up to date with the host-specific configuration, and everything else is handled automatically.
这样,您真正需要担心的是保持settings_local。使用特定于主机的配置更新的py文件,其他所有内容都是自动处理的。
Check out an example here.
看看这里的一个例子。
#2
25
Personally, I use a single settings.py for the project, I just have it look up the hostname it's on (my development machines have hostnames that start with "gabriel" so I just have this:
就我个人而言,我只使用一个设置。项目的py,我只是让它查找主机名(我的开发机器上有以“gabriel”开头的主机名,所以我只有这个:
import socket
if socket.gethostname().startswith('gabriel'):
LIVEHOST = False
else:
LIVEHOST = True
then in other parts I have things like:
在其他部分,我有这样的东西:
if LIVEHOST:
DEBUG = False
PREPEND_WWW = True
MEDIA_URL = 'http://static1.grsites.com/'
else:
DEBUG = True
PREPEND_WWW = False
MEDIA_URL = 'http://localhost:8000/static/'
and so on. A little bit less readable, but it works fine and saves having to juggle multiple settings files.
等等。有点不太容易读,但它可以很好地工作,而且还可以保存多个设置文件。
#3
21
At the end of settings.py I have the following:
在设置的最后。我有以下几点:
try:
from settings_local import *
except ImportError:
pass
This way if I want to override default settings I need to just put settings_local.py right next to settings.py.
这样,如果我想重写默认设置,我只需要将settings_local。py就在settings.py旁边。
#4
11
I have two files. settings_base.py
which contains common/default settings, and which is checked into source control. Each deployment has a separate settings.py
, which executes from settings_base import *
at the beginning and then overrides as needed.
我有两个文件。settings_base。py包含公共/默认设置,并被检入源代码控件。每个部署都有单独的设置。py,在开始时从settings_base导入*执行,然后根据需要重写。
#5
7
The most simplistic way I found was:
我发现最简单的方法是:
1) use the default settings.py for local development and 2) create a production-settings.py starting with:
1)使用默认设置。py用于本地开发,2)创建生产设置。py:开始
import os
from settings import *
And then just override the settings that differ in production:
然后重写不同产品的设置:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
....
}
}
#6
2
Somewhat related, for the issue of deploying Django itself with multiple databases, you may want to take a look at Djangostack. You can download a completely free installer that allows you to install Apache, Python, Django, etc. As part of the installation process we allow you to select which database you want to use (MySQL, SQLite, PostgreSQL). We use the installers extensively when automating deployments internally (they can be run in unattended mode).
与此相关的是,对于使用多个数据库部署Django本身的问题,您可能想看看Djangostack。您可以下载一个完全免费的安装程序,允许您安装Apache、Python、Django等。作为安装过程的一部分,我们允许您选择要使用的数据库(MySQL、SQLite、PostgreSQL)。在内部自动部署时,我们会大量使用安装程序(它们可以在无人值守的模式下运行)。
#7
1
I have my settings.py file in an external directory. That way, it doesn't get checked into source control, or over-written by a deploy. I put this in the settings.py file under my Django project, along with any default settings:
我有我的设置。py文件在外部目录中。这样,它就不会被检查到源代码控制中,或者被部署过度。我把它放在设置里。我的Django项目下的py文件,以及任何默认设置:
import sys
import os.path
def _load_settings(path):
print "Loading configuration from %s" % (path)
if os.path.exists(path):
settings = {}
# execfile can't modify globals directly, so we will load them manually
execfile(path, globals(), settings)
for setting in settings:
globals()[setting] = settings[setting]
_load_settings("/usr/local/conf/local_settings.py")
Note: This is very dangerous if you can't trust local_settings.py.
注意:如果不能信任local_settings.py,这将非常危险。
#8
1
In addition to the multiple settings files mentioned by Jim, I also tend to place two settings into my settings.py file at the top BASE_DIR
and BASE_URL
set to the path of the code and the URL to the base of the site, all other settings are modified to append themselves to these.
除了Jim提到的多个设置文件,我还倾向于在设置中设置两个设置。将位于顶部的BASE_DIR和BASE_URL设置为代码路径的py文件,并将URL设置为站点的底部,所有其他设置都将被修改为附加到这些文件上。
BASE_DIR = "/home/sean/myapp/"
e.g. MEDIA_ROOT = "%smedia/" % BASEDIR
BASE_DIR = "/home/sean/myapp/"例如MEDIA_ROOT = "%smedia/" % BASEDIR
So when moving the project I only have to edit these settings and not search the whole file.
因此,在移动项目时,我只需编辑这些设置,而不是搜索整个文件。
I would also recommend looking at fabric and Capistrano (Ruby tool, but it can be used to deploy Django applications) which facilitate automation of remote deployment.
我还建议您看看fabric和Capistrano (Ruby工具,但它可以用于部署Django应用程序),这有助于实现远程部署的自动化。
#9
1
Well, I use this configuration:
我用这个结构:
At the end of settings.py:
在结束时。py:
#settings.py
try:
from locale_settings import *
except ImportError:
pass
And in locale_settings.py:
而在locale_settings.py:
#locale_settings.py
class Settings(object):
def __init__(self):
import settings
self.settings = settings
def __getattr__(self, name):
return getattr(self.settings, name)
settings = Settings()
INSTALLED_APPS = settings.INSTALLED_APPS + (
'gunicorn',)
# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings
#10
0
I think it depends on the size of the site as to whether you need to step up from using SQLite, I've successfully used SQLite on several smaller live sites and it runs great.
我认为这取决于站点的大小,至于是否需要使用SQLite,我已经成功地在几个较小的活动站点上使用了SQLite,它运行得很好。
#11
0
I use environment:
我使用环境:
if os.environ.get('WEB_MODE', None) == 'production' :
from settings_production import *
else :
from settings_dev import *
I believe this is a much better approach, because eventually you need special settings for your test environment, and you can easily add it to this condition.
我认为这是一种更好的方法,因为最终您需要为您的测试环境设置特殊的设置,并且您可以很容易地将其添加到这个条件中。
#12
0
So many complicated answers!
很多复杂的答案!
Every settings.py file comes with :
每一个设置。py文件附带:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
I use that directory to set the DEBUG variable like this (reaplace with the directoy where your dev code is):
我使用该目录来设置调试变量,比如这个(重新配置您的dev代码所在的directoy):
DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
DEBUG = True
Then, every time the settings.py file is moved, DEBUG will be False and it's your production environment.
然后,每次设置。py文件被移动,调试将为False,这是您的生产环境。
Every time you need different settings than the ones in your dev environment just use:
每当您需要与开发环境中的设置不同的设置时,只需使用:
if(DEBUG):
#Debug setting
else:
#Release setting
#13
0
This is an older post but I think if I add this useful library
it will simplify things.
这是一个较老的帖子,但我认为如果我添加这个有用的库,它将简化事情。
使用django-configuration
Quickstart
pip install django-configurations
Then subclass the included configurations.Configuration class in your project's settings.py or any other module you're using to store the settings constants, e.g.:
然后子类化包含的配置。项目设置中的Configuration类。py或任何其他用于存储设置常量的模块,例如:
# mysite/settings.py
from configurations import Configuration
class Dev(Configuration):
DEBUG = True
Set the DJANGO_CONFIGURATION
environment variable to the name of the class you just created, e.g. in ~/.bashrc
:
将DJANGO_CONFIGURATION环境变量设置为您刚刚创建的类的名称,例如,在~/.bashrc中:
export DJANGO_CONFIGURATION=Dev
出口DJANGO_CONFIGURATION = Dev
and the DJANGO_SETTINGS_MODULE
environment variable to the module import path as usual, e.g. in bash:
和通常的模块导入路径的DJANGO_SETTINGS_MODULE环境变量,例如在bash中:
export DJANGO_SETTINGS_MODULE=mysite.settings
出口DJANGO_SETTINGS_MODULE = mysite.settings
Alternatively supply the --configuration
option when using Django management commands along the lines of Django's default --settings
command line option, e.g.:
或者,在使用Django管理命令时,根据Django的默认设置命令行选项提供—configuration选项,例如:
python manage.py runserver --settings=mysite.settings --configuration=Dev
python管理。py runserver = mysite——设置。设置——配置= Dev
To enable Django to use your configuration you now have to modify your manage.py or wsgi.py script to use django-configurations' versions of the appropriate starter functions, e.g. a typical manage.py using django-configurations would look like this:
要使Django能够使用您的配置,您现在必须修改您的管理。py或wsgi。py脚本使用django配置的适当启动函数的版本,例如一个典型的管理。使用django配置的py是这样的:
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.management import execute_from_command_line
execute_from_command_line(sys.argv)
Notice in line 10 we don't use the common tool django.core.management.execute_from_command_line
but instead configurations.management.execute_from_command_line
.
注意,在第10行,我们不使用通用工具django.core.management。execute_from_command_line而是configurations.management.execute_from_command_line。
The same applies to your wsgi.py file, e.g.:
这同样适用于您的wsgi。py文件,例如:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.wsgi import get_wsgi_application
application = get_wsgi_application()
Here we don't use the default django.core.wsgi.get_wsgi_application
function but instead configurations.wsgi.get_wsgi_application
.
这里我们不使用默认的django.core.wsgi。get_wsgi_application函数,而不是configurations.wsgi.get_wsgi_application。
That's it! You can now use your project with manage.py and your favorite WSGI enabled server.
就是这样!您现在可以使用您的项目与管理。py和您最喜欢的启用了WSGI的服务器。
#14
-2
In fact you should probably consider having the same (or almost the same) configs for your development and production environment. Otherwise, situations like "Hey, it works on my machine" will happen from time to time.
实际上,您应该考虑为您的开发和生产环境设置相同(或几乎相同)的配置。否则,像“嘿,它在我的机器上工作”这样的情况会不时发生。
So in order to automate your deployment and eliminate those WOMM issues, just use Docker.
因此,为了自动化部署并消除WOMM问题,只需使用Docker。
#1
83
Update: django-configurations has been released which is probably a better option for most people than doing it manually.
更新:django配置已经发布,对于大多数人来说,这可能是一个更好的选择,而不是手工操作。
If you would prefer to do things manually, my earlier answer still applies:
如果您喜欢手工操作,我之前的回答仍然适用:
I have multiple settings files.
我有多个设置文件。
-
settings_local.py
- host-specific configuration, such as database name, file paths, etc. - settings_local。与主机相关的配置,如数据库名、文件路径等。
-
settings_development.py
- configuration used for development, e.g.DEBUG = True
. - settings_development。py -用于开发的配置,例如DEBUG = True。
-
settings_production.py
- configuration used for production, e.g.SERVER_EMAIL
. - settings_production。py -用于生产的配置,例如SERVER_EMAIL。
I tie these all together with a settings.py
file that firstly imports settings_local.py
, and then one of the other two. It decides which to load by two settings inside settings_local.py
- DEVELOPMENT_HOSTS
and PRODUCTION_HOSTS
. settings.py
calls platform.node()
to find the hostname of the machine it is running on, and then looks for that hostname in the lists, and loads the second settings file depending on which list it finds the hostname in.
我把这些和一个设置联系在一起。首先导入settings_local的py文件。然后是另两个中的一个。它决定在settings_local中通过两个设置加载哪个。py - DEVELOPMENT_HOSTS和PRODUCTION_HOSTS。设置。py调用platform.node()来查找正在运行的机器的主机名,然后在列表中查找该主机名,并根据在哪个列表中找到主机名加载第二个设置文件。
That way, the only thing you really need to worry about is keeping the settings_local.py
file up to date with the host-specific configuration, and everything else is handled automatically.
这样,您真正需要担心的是保持settings_local。使用特定于主机的配置更新的py文件,其他所有内容都是自动处理的。
Check out an example here.
看看这里的一个例子。
#2
25
Personally, I use a single settings.py for the project, I just have it look up the hostname it's on (my development machines have hostnames that start with "gabriel" so I just have this:
就我个人而言,我只使用一个设置。项目的py,我只是让它查找主机名(我的开发机器上有以“gabriel”开头的主机名,所以我只有这个:
import socket
if socket.gethostname().startswith('gabriel'):
LIVEHOST = False
else:
LIVEHOST = True
then in other parts I have things like:
在其他部分,我有这样的东西:
if LIVEHOST:
DEBUG = False
PREPEND_WWW = True
MEDIA_URL = 'http://static1.grsites.com/'
else:
DEBUG = True
PREPEND_WWW = False
MEDIA_URL = 'http://localhost:8000/static/'
and so on. A little bit less readable, but it works fine and saves having to juggle multiple settings files.
等等。有点不太容易读,但它可以很好地工作,而且还可以保存多个设置文件。
#3
21
At the end of settings.py I have the following:
在设置的最后。我有以下几点:
try:
from settings_local import *
except ImportError:
pass
This way if I want to override default settings I need to just put settings_local.py right next to settings.py.
这样,如果我想重写默认设置,我只需要将settings_local。py就在settings.py旁边。
#4
11
I have two files. settings_base.py
which contains common/default settings, and which is checked into source control. Each deployment has a separate settings.py
, which executes from settings_base import *
at the beginning and then overrides as needed.
我有两个文件。settings_base。py包含公共/默认设置,并被检入源代码控件。每个部署都有单独的设置。py,在开始时从settings_base导入*执行,然后根据需要重写。
#5
7
The most simplistic way I found was:
我发现最简单的方法是:
1) use the default settings.py for local development and 2) create a production-settings.py starting with:
1)使用默认设置。py用于本地开发,2)创建生产设置。py:开始
import os
from settings import *
And then just override the settings that differ in production:
然后重写不同产品的设置:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
....
}
}
#6
2
Somewhat related, for the issue of deploying Django itself with multiple databases, you may want to take a look at Djangostack. You can download a completely free installer that allows you to install Apache, Python, Django, etc. As part of the installation process we allow you to select which database you want to use (MySQL, SQLite, PostgreSQL). We use the installers extensively when automating deployments internally (they can be run in unattended mode).
与此相关的是,对于使用多个数据库部署Django本身的问题,您可能想看看Djangostack。您可以下载一个完全免费的安装程序,允许您安装Apache、Python、Django等。作为安装过程的一部分,我们允许您选择要使用的数据库(MySQL、SQLite、PostgreSQL)。在内部自动部署时,我们会大量使用安装程序(它们可以在无人值守的模式下运行)。
#7
1
I have my settings.py file in an external directory. That way, it doesn't get checked into source control, or over-written by a deploy. I put this in the settings.py file under my Django project, along with any default settings:
我有我的设置。py文件在外部目录中。这样,它就不会被检查到源代码控制中,或者被部署过度。我把它放在设置里。我的Django项目下的py文件,以及任何默认设置:
import sys
import os.path
def _load_settings(path):
print "Loading configuration from %s" % (path)
if os.path.exists(path):
settings = {}
# execfile can't modify globals directly, so we will load them manually
execfile(path, globals(), settings)
for setting in settings:
globals()[setting] = settings[setting]
_load_settings("/usr/local/conf/local_settings.py")
Note: This is very dangerous if you can't trust local_settings.py.
注意:如果不能信任local_settings.py,这将非常危险。
#8
1
In addition to the multiple settings files mentioned by Jim, I also tend to place two settings into my settings.py file at the top BASE_DIR
and BASE_URL
set to the path of the code and the URL to the base of the site, all other settings are modified to append themselves to these.
除了Jim提到的多个设置文件,我还倾向于在设置中设置两个设置。将位于顶部的BASE_DIR和BASE_URL设置为代码路径的py文件,并将URL设置为站点的底部,所有其他设置都将被修改为附加到这些文件上。
BASE_DIR = "/home/sean/myapp/"
e.g. MEDIA_ROOT = "%smedia/" % BASEDIR
BASE_DIR = "/home/sean/myapp/"例如MEDIA_ROOT = "%smedia/" % BASEDIR
So when moving the project I only have to edit these settings and not search the whole file.
因此,在移动项目时,我只需编辑这些设置,而不是搜索整个文件。
I would also recommend looking at fabric and Capistrano (Ruby tool, but it can be used to deploy Django applications) which facilitate automation of remote deployment.
我还建议您看看fabric和Capistrano (Ruby工具,但它可以用于部署Django应用程序),这有助于实现远程部署的自动化。
#9
1
Well, I use this configuration:
我用这个结构:
At the end of settings.py:
在结束时。py:
#settings.py
try:
from locale_settings import *
except ImportError:
pass
And in locale_settings.py:
而在locale_settings.py:
#locale_settings.py
class Settings(object):
def __init__(self):
import settings
self.settings = settings
def __getattr__(self, name):
return getattr(self.settings, name)
settings = Settings()
INSTALLED_APPS = settings.INSTALLED_APPS + (
'gunicorn',)
# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings
#10
0
I think it depends on the size of the site as to whether you need to step up from using SQLite, I've successfully used SQLite on several smaller live sites and it runs great.
我认为这取决于站点的大小,至于是否需要使用SQLite,我已经成功地在几个较小的活动站点上使用了SQLite,它运行得很好。
#11
0
I use environment:
我使用环境:
if os.environ.get('WEB_MODE', None) == 'production' :
from settings_production import *
else :
from settings_dev import *
I believe this is a much better approach, because eventually you need special settings for your test environment, and you can easily add it to this condition.
我认为这是一种更好的方法,因为最终您需要为您的测试环境设置特殊的设置,并且您可以很容易地将其添加到这个条件中。
#12
0
So many complicated answers!
很多复杂的答案!
Every settings.py file comes with :
每一个设置。py文件附带:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
I use that directory to set the DEBUG variable like this (reaplace with the directoy where your dev code is):
我使用该目录来设置调试变量,比如这个(重新配置您的dev代码所在的directoy):
DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
DEBUG = True
Then, every time the settings.py file is moved, DEBUG will be False and it's your production environment.
然后,每次设置。py文件被移动,调试将为False,这是您的生产环境。
Every time you need different settings than the ones in your dev environment just use:
每当您需要与开发环境中的设置不同的设置时,只需使用:
if(DEBUG):
#Debug setting
else:
#Release setting
#13
0
This is an older post but I think if I add this useful library
it will simplify things.
这是一个较老的帖子,但我认为如果我添加这个有用的库,它将简化事情。
使用django-configuration
Quickstart
pip install django-configurations
Then subclass the included configurations.Configuration class in your project's settings.py or any other module you're using to store the settings constants, e.g.:
然后子类化包含的配置。项目设置中的Configuration类。py或任何其他用于存储设置常量的模块,例如:
# mysite/settings.py
from configurations import Configuration
class Dev(Configuration):
DEBUG = True
Set the DJANGO_CONFIGURATION
environment variable to the name of the class you just created, e.g. in ~/.bashrc
:
将DJANGO_CONFIGURATION环境变量设置为您刚刚创建的类的名称,例如,在~/.bashrc中:
export DJANGO_CONFIGURATION=Dev
出口DJANGO_CONFIGURATION = Dev
and the DJANGO_SETTINGS_MODULE
environment variable to the module import path as usual, e.g. in bash:
和通常的模块导入路径的DJANGO_SETTINGS_MODULE环境变量,例如在bash中:
export DJANGO_SETTINGS_MODULE=mysite.settings
出口DJANGO_SETTINGS_MODULE = mysite.settings
Alternatively supply the --configuration
option when using Django management commands along the lines of Django's default --settings
command line option, e.g.:
或者,在使用Django管理命令时,根据Django的默认设置命令行选项提供—configuration选项,例如:
python manage.py runserver --settings=mysite.settings --configuration=Dev
python管理。py runserver = mysite——设置。设置——配置= Dev
To enable Django to use your configuration you now have to modify your manage.py or wsgi.py script to use django-configurations' versions of the appropriate starter functions, e.g. a typical manage.py using django-configurations would look like this:
要使Django能够使用您的配置,您现在必须修改您的管理。py或wsgi。py脚本使用django配置的适当启动函数的版本,例如一个典型的管理。使用django配置的py是这样的:
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.management import execute_from_command_line
execute_from_command_line(sys.argv)
Notice in line 10 we don't use the common tool django.core.management.execute_from_command_line
but instead configurations.management.execute_from_command_line
.
注意,在第10行,我们不使用通用工具django.core.management。execute_from_command_line而是configurations.management.execute_from_command_line。
The same applies to your wsgi.py file, e.g.:
这同样适用于您的wsgi。py文件,例如:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.wsgi import get_wsgi_application
application = get_wsgi_application()
Here we don't use the default django.core.wsgi.get_wsgi_application
function but instead configurations.wsgi.get_wsgi_application
.
这里我们不使用默认的django.core.wsgi。get_wsgi_application函数,而不是configurations.wsgi.get_wsgi_application。
That's it! You can now use your project with manage.py and your favorite WSGI enabled server.
就是这样!您现在可以使用您的项目与管理。py和您最喜欢的启用了WSGI的服务器。
#14
-2
In fact you should probably consider having the same (or almost the same) configs for your development and production environment. Otherwise, situations like "Hey, it works on my machine" will happen from time to time.
实际上,您应该考虑为您的开发和生产环境设置相同(或几乎相同)的配置。否则,像“嘿,它在我的机器上工作”这样的情况会不时发生。
So in order to automate your deployment and eliminate those WOMM issues, just use Docker.
因此,为了自动化部署并消除WOMM问题,只需使用Docker。