public/new-github-repos/docs/pages/template/production-checklist.rst

187 lines
5.6 KiB
ReStructuredText

.. _`going-to-production`:
Going to production
===================
This section covers everything you need to know before going to production.
Django
------
Checks
~~~~~~
Before going to production make sure you have checked everything:
1. Migrations are up-to-date
2. Static files are all present
3. There are no security or other ``django`` warnings
Checking migrations, static files,
and security is done inside ``ci.sh`` script.
We check that there are no unapplied migrations:
.. code :: bash
python manage.py makemigrations --dry-run --check
If you have forgotten to create a migration and changed the model,
you will see an error on this line.
We also check that static files can be collected:
.. code :: bash
DJANGO_ENV=production python manage.py collectstatic --no-input --dry-run
However, this check does not cover all the cases.
Sometimes ``ManifestStaticFilesStorage`` will fail on real cases,
but will pass with ``--dry-run`` option.
You can disable ``--dry-run`` option if you know what you are doing.
Be careful with this option, when working with auto-uploading
your static files to any kind of CDNs.
That's how we check ``django`` warnings:
.. code:: bash
DJANGO_ENV=production python manage.py check --deploy --fail-level WARNING
These warnings are raised by ``django``
when it detects any configuration issues.
This command should give not warnings or errors.
It is bundled into `docker`, so the container will not work with any warnings.
Static and media files
~~~~~~~~~~~~~~~~~~~~~~
We use ``/var/www/django`` folder to store our media
and static files in production as ``/var/www/django/static``
and ``/var/www/django/media``.
Docker uses these two folders as named volumes.
And later these volumes are also mounted to ``caddy``
with ``ro`` mode so it possible to read their contents.
To find the exact location of these files on your host
you will need to do the following:
.. code:: bash
docker volume ls # to find volumes' names
docker volume inspect VOLUME_NAME
Sometimes storing your media files inside a container is not a good idea.
Use ``CDN`` when you have a lot of user content
or it is very important not to lose it.
There are `helper libraries <http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html>`_
to bind ``django`` and these services.
If you don't need ``media`` files support, just remove the volumes.
Migrations
~~~~~~~~~~
We do run migration in the ``gunicorn.sh`` by default.
Why do we do this? Because that's probably the easiest way to do it.
But it clearly has some disadvantages:
- When scaling your container for multiple nodes you will have multiple
threads running the same migrations. And it might be a problem since
migrations do not guarantee that it will work this way.
- You can perform some operations multiple times
- Possible other evil things may happen
So, what to do in this case?
Well, you can do whatever it takes to run migrations in a single thread.
For example, you can create a separate container to do just that.
Other options are fine as well.
Postgres
--------
Sometimes using ``postgres`` inside a container
`is not a good idea <https://myopsblog.wordpress.com/2017/02/06/why-databases-is-not-for-containers/>`_.
So, what should be done in this case?
First of all, move your database ``docker`` service definition
inside ``docker-compose.override.yml``.
Doing so will not affect development,
but will remove database service from production.
Next, you will need to specify `extra_hosts <https://docs.docker.com/compose/compose-file/#extra_hosts>`_
to contain your ``postgresql`` address.
Lastly, you would need to add new hosts to ``pg_hba.conf``.
`Here <http://winstonkotzan.com/blog/2017/06/01/connecting-to-external-postgres-database-with-docker.html>`_
is a nice tutorial about this topic.
Caddy
-----
Let's Encrypt
~~~~~~~~~~~~~
We are using ``Caddy`` and ``Let's Encrypt`` for HTTPS.
The Caddy webserver used in the default configuration will get
you a valid certificate from ``Let's Encrypt`` and update it automatically.
All you need to do to enable this is to make sure
that your DNS records are pointing to the server Caddy runs on.
Read more: `Automatic HTTPS <https://caddyserver.com/docs/automatic-https>`_
in Caddy docs.
Caddyfile validation
~~~~~~~~~~~~~~~~~~~~
You can also run ``-validate`` command to validate ``Caddyfile`` contents.
Here's it would look like:
.. code:: bash
docker-compose -f docker-compose.yml -f docker/docker-compose.prod.yml
run --rm caddy -validate
This check is not included in the pipeline by default,
because it is quite long to start all the machinery for this single check.
Disabling HTTPS
~~~~~~~~~~~~~~~
You would need to `disable <https://caddyserver.com/docs/tls>`_
``https`` inside ``Caddy`` and in production settings for Django.
Because Django itself also redirects to `https`.
See `docs <https://docs.djangoproject.com/en/2.2/ref/settings/#secure-ssl-redirect>`_.
You would also need to disable ``manage.py check``
in ``docker/ci.sh``.
Otherwise, your application won't start,
it would not pass ``django``'s security checks.
Disabling WWW subdomain
~~~~~~~~~~~~~~~~~~~~~~~
If you for some reason do not require ``www.`` subdomain,
then delete ``www.{$DOMAIN_NAME}`` section from ``Caddyfile``.
Third-Level domains
~~~~~~~~~~~~~~~~~~~
You have to disable ``www`` subdomain if
your app works on third-level domains like:
- ``kira.wemake.services``
- ``support.myapp.com``
Otherwise, ``Caddy`` will server redirects to ``www.example.yourdomain.com``.
Further reading
---------------
- Django's deployment `checklist <https://docs.djangoproject.com/en/dev/howto/deployment/checklist/#deployment-checklist>`_