I am tring to createsuperuser in a django docker container with fabric.
To create the super user in django, I need run this in a django interactive mode:
./manage.py createsuperuser
And because I want to make it run in a fabric script, so I find this command could avoid inputing password
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" to run it in my django container
docker exec container_django echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'pass')" | ./manage.py shell
The problem comes out with the linux pipe, the pipe(|) all the contents on its left(including the docker exec) to its right(./manage.py shell)
And this is not only difficult part, considering to put all these junks into a fabric run, which means they need quotes on both end. It will make whole thing very urgly.
fabric run:
run("docker exec container_django {command to create django super user}")
I am still struggling on how to make at least the junk work in a fabric run, but I don't know how to do it.
I recommend adding a new management command that will automatically create a superuser if no Users exist.
See small example I created at https://github.com/dkarchmer/aws-eb-docker-django. In particular, see how I have a
python manage.py initadmin
which runs:(See Authentication/management/commands).
You can see how the Dockerfile then just runs CMD to runserver.sh which basically runs
Obviously, this assumes the Admins immediately go change their passwords after the server is up. That may or may not be good enough for you.
Might be easiest to just put together a Python script to create the Django superuser for you, instead of trying to feed all those commands through
manage.py shell
. Can you put your commands in a .py file, let's sayyourfile.py
:And then, after doing
chmod +x yourfile.py
:Depending on your setup you may need to make sure that the
DJANGO_SETTINGS_MODULE
environment variable is set appropriately for that run() command.I took @hoefling's answer, and changed it a little.
I needed to create super user AFTER the build step. So i put it inside a supervisor script. That means it will be executed every time i run the container. So i added a simple if / else control to check if superuser is already created. That reduces the execution time. And we need to set
DJANGO_SETTINGS_MODULE
environment variable as well.I handle this by evaluating the python code line in Dockerfile.
Note that this is different from calling
as
django.contrib.auth.get_user_model
will work fine with custom user model if you should have any (which is quite common), while withUser.objects.create
you only create a standard user entity, ignoring any custom user model.Also, it's the same call that django's
createsuperuser
command does under the hood, so it should be pretty safe to do.I would suggest running a Data Migration, so when you startup your Docker services (e.g. app & db) via
docker-compose up
, you can execute all migrations exactly oncedocker-compose exec web python code/manage.py migrate
So your migration would look like this (assuming you store credentials etc. in environment variables)
This allows you to use a built container to execute against a database, whether it's a local db in the same container or a separate service. And it's not done every time you rebuild your container, but only when the migration is necessary.
Get the container ID and run the command.