添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
忐忑的灯泡  ·  Missing support for ...·  4 周前    · 
鼻子大的松鼠  ·  django中ajax的GET, ...·  2 周前    · 
瘦瘦的野马  ·  SQL ...·  5 月前    · 
怕老婆的卤蛋  ·  16. ...·  5 月前    · 

在docker容器中创建django超级用户,无需输入密码

43 人关注

我想在django docker容器中用fabric创建超级用户。

为了在django中创建超级用户,我需要在django的交互模式下运行这个程序。

./manage.py createsuperuser

而且因为我想让它在一个织物脚本中运行,所以我发现this命令可以避免输入密码

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'pass')" | ./manage.py shell

Then I put this together with "docker exec"在我的django容器中运行它

docker exec container_django echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'pass')" | ./manage.py shell

问题出在linux管道上,管道(|)左边的所有内容(包括docker exec)到右边(./manage.py shell)。

这不仅是困难的部分,考虑到要把所有这些垃圾放入一个织物运行,这意味着他们需要两端的报价。这将使整个事情变得非常紧迫。

fabric run:
run("docker exec container_django {command to create django super user}")

我还在苦苦思索如何至少让垃圾在织物运行中发挥作用,但我不知道该如何做。

python
django
shell
docker
fabric
Liao Zhuodi
Liao Zhuodi
发布于 2015-05-04
12 个回答
SuperNova
SuperNova
发布于 2021-08-29
已采纳
0 人赞同

获取容器ID并运行命令。

docker exec -it container_id python manage.py createsuperuser
    
This doesn't solve the problem
dkarchmer
dkarchmer
发布于 2021-08-29
0 人赞同

我建议添加一个新的管理命令,如果没有用户存在,就自动创建一个超级用户。

请看我在以下网站创建的小例子 https://github.com/dkarchmer/aws-eb-docker-django .特别是,请看我有一个 python manage.py initadmin ,它是如何运行的。

class Command(BaseCommand):
    def handle(self, *args, **options):
        if Account.objects.count() == 0:
            for user in settings.ADMINS:
                username = user[0].replace(' ', '')
                email = user[1]
                password = 'admin'
                print('Creating account for %s (%s)' % (username, email))
                admin = Account.objects.create_superuser(email=email, username=username, password=password)
                admin.is_active = True
                admin.is_admin = True
                admin.save()
        else:
            print('Admin accounts can only be initialized if no Accounts exist')

(见认证/管理/命令)。

你可以看到Docker文件是如何运行CMD到 runserver.sh的,它基本上是运行

python manage.py migrate --noinput
python manage.py initadmin
python manage.py runserver 0.0.0.0:8080

很明显,这是假设管理员在服务器启动后立即去修改他们的密码。这对你来说可能足够好,也可能不够好。

请注意,你也可以用 docker run --rm python manage.py initadmin 手动运行initadmin,这很容易从你的fabfile中完成。
为了使其更加安全,也许你可以通过环境变量来输入默认的管理员密码,就像你在 settings.py 中的数据库凭证一样。
从什么地方更安全?这只是第一个版本的问题。即使有人知道并在你之前登录并更改了密码,你也只是把网站重新关闭并重新做一遍。试想一下,如果有人知道你正在发布你的第一个网站,并在登录时击败了你,那就有可能。这就是没有问题的定义。
我相信以下命令是不需要的。 admin.is_active = True , admin.is_admin = True admin.save() 。你正在使用 create_superuser()
user2579823
user2579823
发布于 2021-08-29
0 人赞同

使用环境变量和非交互式模式。因此,你在你的环境文件中添加类似这样的东西。

DJANGO_SUPERUSER_PASSWORD=**********
DJANGO_SUPERUSER_EMAIL=example@example.com
DJANGO_SUPERUSER_USERNAME=admin

然后,在你的docker入口文件中,添加这些命令。

python manage.py makemigrations
python manage.py migrate
python manage.py createcachetable
if [ "$DJANGO_SUPERUSER_USERNAME" ]
    python manage.py createsuperuser \
        --noinput \
        --username $DJANGO_SUPERUSER_USERNAME \
        --email $DJANGO_SUPERUSER_USERNAME

注意,不需要写上密码,因为Django的creasuperuser脚本在非交互式模式下默认从DJANGO_SUPERUSER_PASSWORD中获取。

这将运行迁移,并在使用环境变量启动容器时根据需要创建管理员用户。

我的Django的creasuperuser脚本没有从DJANGO_SUPERUSER_PASSWORD获取密码。我如何测试?
Taciano Morais Silva
记得用export命令或在docker环境中导出到环境变量DJANGO_SUPERUSER_PASSWORD。我用 source .env 加载它,它把值设置到变量中,但docker-compose.yml找不到它。至于USERNAME和EMAIL, source 起作用了。
@TacianoMoraisSilva this is works only for Django >= 3.0
似乎在 --email $DJANGO_SUPERUSER_USERNAME 中应该说 --email $DJANGO_SUPERUSER_EMAIL
hoefling
hoefling
发布于 2021-08-29
0 人赞同

Disclaimer:

将密码明文存储在Docker文件中是不安全的,因为密码可以随时从镜像中提取出来,而且Docker文件通常会提交给版本控制。然而,这个答案不是关于密码安全的,而是关于自动执行 createsuperuser 命令的;如果你正在寻找存储超级用户密码的正确方法,可以看看这个SO问题。 Docker和保障密码安全

我通过评估Dockerfile中的python代码行来处理这个问题。

ENV DJANGO_DB_NAME=default
ENV DJANGO_SU_NAME=admin
ENV DJANGO_SU_EMAIL=admin@my.company
ENV DJANGO_SU_PASSWORD=mypass
RUN python -c "import django; django.setup(); \
   from django.contrib.auth.management.commands.createsuperuser import get_user_model; \
   get_user_model()._default_manager.db_manager('$DJANGO_DB_NAME').create_superuser( \
   username='$DJANGO_SU_NAME', \
   email='$DJANGO_SU_EMAIL', \
   password='$DJANGO_SU_PASSWORD')"

请注意,这与调用

User.objects.create_superuser('admin', 'admin@example.com', 'pass')

如同django.contrib.auth.get_user_model一样,可以用custom user model如果你应该有的话(这很常见),而用User.objects.create你只创建一个标准的用户实体,忽略任何自定义用户模型。

另外,这也是django的createsuperuser命令的调用方式。does under the hood因此,它应该是相当安全的做法。

因此,通常Docker文件会被提交到版本控制中,这也会暴露那里的证书,所以我不认为这种特殊的方式是一个好主意。环境变量应该单独处理(如cmd行或.env文件)。
环境变量本身是不安全的,通过命令行或dotenv文件传递环境变量也是不安全的;然而,你是对的,至少必须在答案中加入一个免责声明,以警告盲目复制。
anmolakhilesh
anmolakhilesh
发布于 2021-08-29
0 人赞同

我在使用compose时使用这个命令

docker-compose run <web> python manage.py createsuperuser

其中<web>是docker服务的名称(在docker-compose.yml中)。 https://docs.docker.com/compose/reference/run/

When run with Dockerfile

docker exec -it <container_id> python manage.py createsuperuser
    
Hendrik F
Hendrik F
发布于 2021-08-29
0 人赞同

我建议运行一个 数据迁移 , so when you startup your Docker services (e.g. app & db) via docker-compose up , you can execute all migrations exactly once docker-compose exec web python code/manage.py migrate

所以你的迁移会是这样的(假设你在环境变量中存储了证书等)。

import os
from django.db import migrations
class Migration(migrations.Migration):
    dependencies = [
        ('<your_app>', '<previous_migration>'),
    def generate_superuser(apps, schema_editor):
        from django.contrib.auth.models import User
        DJANGO_DB_NAME = os.environ.get('DJANGO_DB_NAME', "default")
        DJANGO_SU_NAME = os.environ.get('DJANGO_SU_NAME')
        DJANGO_SU_EMAIL = os.environ.get('DJANGO_SU_EMAIL')
        DJANGO_SU_PASSWORD = os.environ.get('DJANGO_SU_PASSWORD')
        superuser = User.objects.create_superuser(
            username=DJANGO_SU_NAME,
            email=DJANGO_SU_EMAIL,
            password=DJANGO_SU_PASSWORD)
        superuser.save()
    operations = [
        migrations.RunPython(generate_superuser),

这允许你使用一个构建的容器来针对数据库执行,无论它是同一容器中的本地db还是一个单独的服务。而且,这不是在你每次重建容器时进行的,而只是在有必要进行迁移时进行。

我们应该把这段代码放在项目的什么地方?
沿着你的其他迁移文件,最可能的是 "迁移 "文件夹
Taciano Morais Silva
Taciano Morais Silva
发布于 2021-08-29
0 人赞同

我使用decople lib从 .env 文件中加载环境变量,我做了用户名是否存在的测试。

from decouple import config
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
class Command(BaseCommand):
    def handle(self, *args, **options):
        username = config('DJANGO_SUPERUSER_USERNAME')
        email = config('DJANGO_SUPERUSER_EMAIL')
        password = config('DJANGO_SUPERUSER_PASSWORD')
        if not User.objects.filter(username=username).exists():
            print('Creating account for %s (%s)' % (username, email))
            admin = User.objects.create_superuser(
                email=email, username=username, password=password)
        else:
            print('Admin account has already been initialized.')

So I do it like this:

  source .env
  python manage.py initadmin

我的.env文件有。

DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@admin.com
DJANGO_SUPERUSER_PASSWORD=mypass
    
Josh Kupershmidt
Josh Kupershmidt
发布于 2021-08-29
0 人赞同

可能最简单的做法是直接编写一个Python脚本来为你创建Django超级用户,而不是试图通过 manage.py shell 来输入所有这些命令。你能不能把你的命令放在一个.py文件里,比方说 yourfile.py

#!/usr/bin/env python
from django.contrib.auth.models import User
User.objects.create_superuser('admin', 'admin@example.com', 'pass')

然后,在做完chmod +x yourfile.py

fabric run:
run("docker exec container_django yourfile.py")

根据你的设置,你可能需要确保DJANGO_SETTINGS_MODULE环境变量为该run()命令进行了适当的设置。

Ikon
我选择这个解决方案,并将Hashicorp Vault加入其中,只是为了使秘密对攻击者来说保持秘密。你不需要明明白白地传递密码(也许还有用户名),而是向Vault查询一个秘密密钥。
alioguzhan
alioguzhan
发布于 2021-08-29
0 人赞同

I took @霍夫林的回答 ,并对其进行了一些改变。

我需要创建超级用户 之后 构建步骤。所以我把它放在一个监督者脚本里。这意味着它将在我每次运行容器时被执行。所以我添加了一个简单的if / else控件来检查超级用户是否已经创建。这就减少了执行时间。而且我们还需要设置 DJANGO_SETTINGS_MODULE 环境变量。

python -c "import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'project_name.settings'
import django
django.setup()
from django.contrib.auth.management.commands.createsuperuser import get_user_model
if get_user_model().objects.filter(username='$DJANGO_SUPERUSER_USERNAME'): 
    print 'Super user already exists. SKIPPING...'
else:
    print 'Creating super user...'
    get_user_model()._default_manager.db_manager('$DJANGO_DB_NAME').create_superuser(username='$DJANGO_SUPERUSER_USERNAME', email='$DJANGO_SUPERUSER_EMAIL', password='$DJANGO_SUPERUSER_PASSWORD')
    print 'Super user created...'"
    
Carmen Jara
Carmen Jara
发布于 2021-08-29
0 人赞同

在我的项目中,没有一个答案是有效的。 这就成功了。

docker exec web ./manage.py shell -c "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('your_user', 'your_password')"
    
用户对象现在需要用户名、电子邮件,然后是密码,所以, User.objects.create_superuser('your_user', 'your_email', 'your_password')
josue
josue
发布于 2021-08-29
0 人赞同

创建文件 Makefile

.ONESHELL:
reset-superuser: SHELL := python
reset-superuser:
    import os
    import django
    from django.contrib.auth import get_user_model
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.develop")
    django.setup()
    User = get_user_model()
    user = User.objects.filter(is_superuser=True).first()
    if user:
        user.set_password("admin")
        user.save()
    else:
        user = User.objects.create_superuser(
            username="josuedjh",
            first_name="Josue djh",
            password="admin",
    print(f"Superuser {user.username!r} with password `admin`")

运行命令。

make reset-superuser
    
marcinros
marcinros
发布于 2021-08-29
0 人赞同

干净优雅的方法是,如果你在容器中运行Django,不要把任何额外的自定义代码或命令放到代码库中。而是使用一个bash脚本来运行任何需要的配置(例如创建超级用户)。这样你就可以更好地管理和自动化你的配置,并保持代码库的清洁和可重复使用的环境。 放入你的 docker-compose.yml

command: >
  bash -c '.. 
  && source create_superuser_prod.sh