web-dev-qa-db-fra.com

Créer Django super utilisateur dans un conteneur Docker sans entrer de mot de passe

Je vais essayer de créer un superutilisateur dans un Django conteneur docker avec du tissu.

Pour créer le super utilisateur dans Django, je dois l'exécuter dans un Django mode interactif:

./manage.py createsuperuser

Et parce que je veux le faire fonctionner dans un script Fabric, je trouve donc que la commande this pourrait éviter de saisir le mot de passe

echo "from Django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | ./manage.py Shell

Ensuite, j'ai mis cela avec "docker exec" pour l'exécuter dans mon Django conteneur

docker exec container_Django echo "from Django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | ./manage.py Shell

Le problème vient avec le pipe linux, le pipe (|) tout le contenu à sa gauche (y compris le docker exec) à sa droite (./ manage.py Shell)

Et ce n'est pas seulement une partie difficile, compte tenu de mettre toutes ces jonques dans un cycle de fabrication, ce qui signifie qu'elles ont besoin de devis aux deux extrémités. Cela rendra le tout très urgent.

fabric run:
run("docker exec container_Django {command to create Django super user}")

Je me bats toujours sur la façon de faire fonctionner au moins la camelote dans un tissu, mais je ne sais pas comment le faire.

19
Liao Zhuodi

Je recommande d'ajouter une nouvelle commande de gestion qui créera automatiquement un superutilisateur si aucun utilisateur n'existe.

Voir le petit exemple que j'ai créé sur https://github.com/dkarchmer/aws-eb-docker-Django . En particulier, voyez comment j'ai un python manage.py initadmin qui s'exécute:

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')

(Voir Authentification/gestion/commandes).

Vous pouvez voir comment le Dockerfile exécute ensuite CMD vers runserver.sh qui fonctionne essentiellement

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

Évidemment, cela suppose que les administrateurs modifient immédiatement leurs mots de passe une fois le serveur opérationnel. Cela peut ou peut ne pas être suffisant pour vous.

9
dkarchmer

Obtenez l'ID de conteneur et exécutez la commande.

docker exec -it container_id python manage.py createsuperuser
13
SuperNova

Avertissement:

Le stockage du texte en clair des mots de passe dans le Dockerfile n'est pas sûr car les mots de passe peuvent être extraits de l'image à tout moment et les Dockerfiles sont généralement validés pour le contrôle de version. Cependant, cette réponse ne concerne pas la sécurité des mots de passe, mais plutôt l'automatisation de la commande createsuperuser; si vous cherchez un moyen approprié de stocker le mot de passe du superutilisateur, jetez un œil à cette SO question: Docker et sécurisation des mots de passe .


Je gère cela en évaluant la ligne de code python dans Dockerfile.

ENV Django_DB_NAME=default
ENV Django_SU_NAME=admin
ENV [email protected]
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')"

Notez que c'est différent d'appeler

User.objects.create_superuser('admin', '[email protected]', 'pass')

comme Django.contrib.auth.get_user_model fonctionnera très bien avec modèle utilisateur personnalisé si vous devez en avoir (ce qui est assez courant), tandis qu'avec User.objects.create vous créez uniquement une entité utilisateur standard, en ignorant tout modèle utilisateur personnalisé.

De plus, c'est le même appel que la commande createsuperuser de Django le fait sous le capot , donc cela devrait être assez sûr.

8
hoefling

Je suggérerais d'exécuter un Data Migration , donc lorsque vous démarrez vos services Docker (par exemple, app & db) via docker-compose up, vous pouvez exécuter toutes les migrations une seule fois docker-compose exec web python code/manage.py migrate

Ainsi, votre migration ressemblerait à ceci (en supposant que vous stockiez les informations d'identification, etc. dans les variables d'environnement)

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),
    ]

Cela vous permet d'utiliser un conteneur intégré pour exécuter une base de données, qu'il s'agisse d'une base de données locale dans le même conteneur ou d'un service distinct. Et cela n'est pas fait à chaque fois que vous reconstruisez votre conteneur, mais uniquement lorsque la migration est nécessaire.

3
Hendrik F

J'utilise cette commande lorsque j'utilise compose

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

<web> est le nom du service docker (dans docker-compose.yml) https://docs.docker.com/compose/reference/run/

Lorsqu'il est exécuté avec Dockerfile

docker exec -it <container_id> python manage.py createsuperuser
2
anmolakhilesh

Pourrait être plus simple de simplement assembler un script Python pour créer le Django superutilisateur pour vous, au lieu d'essayer de nourrir toutes ces commandes via manage.py Shell. Pouvez-vous mettre vos commandes dans un fichier .py, disons yourfile.py:

#!/usr/bin/env python

from Django.contrib.auth.models import User
User.objects.create_superuser('admin', '[email protected]', 'pass')

Et puis, après avoir fait chmod +x yourfile.py:

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

Selon votre configuration, vous devrez peut-être vous assurer que le Django_SETTINGS_MODULE la variable d'environnement est définie de manière appropriée pour cette commande run ().

2

Aucune des réponses n'avait fonctionné dans mon projet. Cela a fonctionné:

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')"
1
Carmen Jara

J'ai pris @ réponse de hoefling , et je l'ai un peu changé.

J'ai eu besoin de créer un super utilisateur [~ # ~] après [~ # ~] l'étape de construction. Je l'ai donc mis dans un script de superviseur. Cela signifie qu'il sera exécuté chaque fois que j'exécuterai le conteneur. J'ai donc ajouté un simple contrôle if/else pour vérifier si le superutilisateur est déjà créé. Cela réduit le temps d'exécution. Et nous devons définir Django_SETTINGS_MODULE variable d'environnement également.

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...'"
1
alix