.. _deployment:
Deployment
==========
When Scout is run from the command-line, it will use the multi-threaded
Werkzeug WSGI server. While this server is perfect for development and small
installations, you may want to use a high-performance WSGI server to deploy
Scout.
Scout provides a WSGI app, so you can use any WSGI server for deployment.
Popular choices are:
* `Gevent `_
* `Gunicorn `_
* `uWSGI `_
The Flask documentation also provides a list of popular WSGI servers and how to
integrate them with Flask apps. Since Scout is a Flask application, all of
these examples should work with minimal modification:
https://flask.palletsprojects.com/en/latest/deploying/
Environment variables
---------------------
The following environment variables can be used to configure Scout in any deployment scenario:
* ``SCOUT_DATABASE``: path to the SQLite database file. Equivalent to passing
the database path as a command-line argument.
* ``SCOUT_CONFIG``: path to a Python configuration file. Equivalent to
the ``-c`` / ``--config`` command-line option. See :ref:`config-file` for details.
* ``SCOUT_MAX_CONNECTIONS``: maximum number of concurrent connections for the
built-in gevent server. Defaults to 128. Only applies when using ``scout_wsgi``.
Gevent
------
Scout comes with a production-ready gevent WSGI server. To run this server:
.. code-block:: console
$ scout_wsgi /path/to/database.db
The built-in gevent server uses a connection pool to limit concurrency. You can
control the pool size via the ``SCOUT_MAX_CONNECTIONS`` environment variable:
.. code-block:: console
$ SCOUT_MAX_CONNECTIONS=256 scout_wsgi /path/to/database.db
If you wish to have more control over the server implementation, this example
wrapper script can get you started:
.. code-block:: python
from gevent import monkey
monkey.patch_all()
from gevent.pywsgi import WSGIServer
from scout.server import parse_options
# Parse command-line options and return a Flask app.
app = parse_options()
# Run the WSGI server on localhost:8000.
WSGIServer(('127.0.0.1', 8000), app).serve_forever()
You could then run the wrapper script using a tool like `supervisord `_
or another process manager.
Gunicorn
--------
Here is an example wrapper script for running Scout using Gunicorn.
.. code-block:: python
# Wrapper script to initialize database.
from scout.server import parse_options
app = parse_options()
Here is how to run gunicorn using the above wrapper script:
.. code-block:: console
$ gunicorn --workers=4 --bind=127.0.0.1:8000 --worker-class=gevent wrapper:app
.. note::
The ``--worker-class=gevent`` option requires `gevent `_
to be installed (``pip install gevent``). You can omit this flag to use
Gunicorn's default synchronous workers instead.
uWSGI
-----
Here is an example wrapper script for uWSGI.
.. code-block:: python
# Wrapper script to initialize database.
from scout.server import parse_options
app = parse_options()
Here is how you might run using the above wrapper script:
.. code-block:: console
$ uwsgi --http :8000 --wsgi-file wrapper.py --master --processes 4 --threads 2
It is common to run uWSGI behind Nginx. For more information `check out the uWSGI docs `_.
Docker
------
Scout includes a ``Dockerfile`` for containerized deployments. The default
image uses the built-in gevent server on port 9004 with a volume-mounted
database.
Building the image:
.. code-block:: console
$ docker build -t scout .
Running the container:
.. code-block:: console
$ docker run -d \
-p 8000:9004 \
-v /path/to/data:/data \
--name scout \
scout
The database file is stored at ``/data/search-index.db`` inside the container
(controlled by the ``SCOUT_DATABASE`` environment variable). Logs are written
to ``/data/scout.log``.
You can override any Scout option by appending flags to the ``docker run``
command:
.. code-block:: console
$ docker run -d \
-p 8000:9004 \
-v /path/to/data:/data \
-e SCOUT_DATABASE=/data/my-index.db \
scout \
--api-key secret --paginate-by 100
The image includes a health check that polls the index list endpoint every 30
seconds.
To use a custom configuration file, mount it into the container and set the
``SCOUT_CONFIG`` environment variable:
.. code-block:: console
$ docker run -d \
-p 8000:9004 \
-v /path/to/data:/data \
-v /path/to/config.py:/etc/scout/config.py \
-e SCOUT_CONFIG=/etc/scout/config.py \
scout