Browse Source

Add Dockerfile (Updated) (#290)

This is the successor or a revised version of https://github.com/matrix-org/sydent/pull/80
From the original PR I picked the two essential / sensible commits.
Instead of using the environment variables at runtime, you can now overwrite the defaults. In particular, it's all about `SYDENT_DB_PATH`.

A build on top of v2.0.0 can be found here: https://github.com/tristanlins/sydent/tree/feature-docker-v2.0.0
A pre-build image can be found on docker hub: https://hub.docker.com/r/tril/matrixdotorg-sydent/tags

# Changelog

(non docker file related changes)

- Improve the database migration logging.
- The environment variables `SYDENT_SERVER_NAME`, `SYDENT_PID_FILE` and `SYDENT_DB_PATH` can be used to adapt the automatically created configuration at startup.

Signed-off-by: Tristan Lins <tristan@lins.io>
Co-authored-by: Travis Ralston <travpc@gmail.com>
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Tristan Lins 3 years ago
parent
commit
de80990a95
7 changed files with 122 additions and 5 deletions
  1. 7 0
      .dockerignore
  2. 5 1
      .gitignore
  3. 59 0
      Dockerfile
  4. 45 0
      README.rst
  5. 1 0
      changelog.d/290.feature
  6. 2 1
      sydent/db/sqlitedb.py
  7. 3 3
      sydent/sydent.py

+ 7 - 0
.dockerignore

@@ -0,0 +1,7 @@
+*.pyc
+.idea/
+.vscode/
+
+sydent.conf
+sydent.db
+.git

+ 5 - 1
.gitignore

@@ -1,7 +1,11 @@
+# Development files
 *.pyc
 .idea/
+.vscode/
+*.iml
+_trial_temp
 
+# Runtime files
 sydent.conf
 sydent.db
 /matrix_is_test/sydent.stderr
-_trial_temp

+ 59 - 0
Dockerfile

@@ -0,0 +1,59 @@
+#
+# Step 1: Build sydent and install dependencies
+#
+FROM docker.io/python:3.8-alpine as builder
+
+# Install dev packages
+RUN apk add --no-cache \
+        build-base \
+        libressl-dev \
+        libffi-dev
+
+# Add user sydent
+RUN addgroup -S -g 993 sydent \
+    && adduser -D --home /sydent -S -u 993 -G sydent -s /bin/ash sydent \
+    && echo "sydent:$(dd if=/dev/random bs=32 count=1 | base64)" | chpasswd
+
+# Copy resources
+COPY --chown=sydent:sydent ["res", "/sydent/res"]
+COPY --chown=sydent:sydent ["scripts", "/sydent/scripts"]
+COPY --chown=sydent:sydent ["sydent", "/sydent/sydent"]
+COPY --chown=sydent:sydent ["README.rst", "setup.cfg", "setup.py", "/sydent/"]
+
+# Install dependencies
+RUN cd /sydent \
+    && su sydent -c 'pip install --user --upgrade pip setuptools sentry-sdk' \
+    && su sydent -c 'pip install --user -e .' \
+    && rm -rf /sydent/.cache \
+    && find /sydent -name '*.pyc' -delete
+
+#
+# Step 2: Reduce image size and layers
+#
+
+FROM docker.io/python:3.8-alpine
+
+# Install packages
+RUN apk add --no-cache \
+        libressl \
+        libffi
+
+# Add user sydent and create /data directory
+RUN addgroup -S -g 993 sydent \
+    && adduser -D --home /sydent -S -u 993 -G sydent -s /bin/ash sydent \
+    && echo "sydent:$(dd if=/dev/random bs=32 count=1 | base64)" | chpasswd \
+    && mkdir /data \
+    && chown sydent:sydent /data
+
+# Copy sydent
+COPY --from=builder ["/sydent", "/sydent"]
+
+ENV SYDENT_CONF=/data/sydent.conf
+ENV SYDENT_PID_FILE=/data/sydent.pid
+ENV SYDENT_DB_PATH=/data/sydent.db
+
+WORKDIR /sydent
+USER sydent:sydent
+VOLUME ["/data"]
+EXPOSE 8090/tcp
+CMD [ "python", "-m", "sydent.sydent" ]

+ 45 - 0
README.rst

@@ -74,6 +74,51 @@ US/Canada, a short code for the UK and an alphanumertic originator for everywher
     originators.44 = short:12345
     originators.default = alpha:Matrix
 
+Docker
+======
+
+A Dockerfile is provided for sydent. To use it, run ``docker build -t sydent .`` in a sydent checkout.
+To run it, use ``docker run --env=SYDENT_SERVER_NAME=my-sydent-server -p 8090:8090 sydent``.
+
+Caution: All data will be lost when the container is terminated!
+
+Persistent data
+---------------
+
+By default, all data is stored in ``/data``.
+The best method is to put the data in a Docker volume.
+
+.. code-block:: shell
+
+   docker volume create sydent-data
+   docker run ... --mount type=volume,source=sydent-data,destination=/data sydent
+
+But you can also bind a local directory to the container.
+However, you then have to pay attention to the file permissions.
+
+.. code-block:: shell
+
+   mkdir /path/to/sydent-data
+   chown 993:993 /path/to/sydent-data
+   docker run ... --mount type=bind,source=/path/to/sydent-data,destination=/data sydent
+
+Environment variables
+---------------------
+
+.. warning:: These variables are only taken into account at first start and are written to the configuration file.
+
++--------------------+-----------------+-----------------------+
+| Variable Name      | Sydent default  | Dockerfile default    |
++====================+=================+=======================+
+| SYDENT_SERVER_NAME | *empty*         | *empty*               |
++--------------------+-----------------+-----------------------+
+| SYDENT_CONF        | ``sydent.conf`` | ``/data/sydent.conf`` |
++--------------------+-----------------+-----------------------+
+| SYDENT_PID_FILE    | ``sydent.pid``  | ``/data/sydent.pid``  |
++--------------------+-----------------+-----------------------+
+| SYDENT_DB_PATH     | ``sydent.db``   | ``/data/sydent.db``   |
++--------------------+-----------------+-----------------------+
+
 Testing
 =======
 

+ 1 - 0
changelog.d/290.feature

@@ -0,0 +1 @@
+Add a Dockerfile and allow environment variables `SYDENT_SERVER_NAME`, `SYDENT_PID_FILE` and `SYDENT_DB_PATH` to modify default configuration values.

+ 2 - 1
sydent/db/sqlitedb.py

@@ -51,9 +51,10 @@ class SqliteDatabase:
             scriptPath = os.path.join(schemaDir, f)
             fp = open(scriptPath, 'r')
             try:
+                logger.info("Importing %s", scriptPath)
                 c.executescript(fp.read())
             except:
-                logger.error("Error importing %s", f)
+                logger.error("Error importing %s", scriptPath)
                 raise
             fp.close()
 

+ 3 - 3
sydent/sydent.py

@@ -76,10 +76,10 @@ logger = logging.getLogger(__name__)
 
 CONFIG_DEFAULTS = {
     'general': {
-        'server.name': '',
+        'server.name': os.environ.get('SYDENT_SERVER_NAME', ''),
         'log.path': '',
         'log.level': 'INFO',
-        'pidfile.path': 'sydent.pid',
+        'pidfile.path': os.environ.get('SYDENT_PID_FILE', 'sydent.pid'),
         'terms.path': '',
         'address_lookup_limit': '10000',  # Maximum amount of addresses in a single /lookup request
 
@@ -96,7 +96,7 @@ CONFIG_DEFAULTS = {
         'delete_tokens_on_bind': 'true',
     },
     'db': {
-        'db.file': 'sydent.db',
+        'db.file': os.environ.get('SYDENT_DB_PATH', 'sydent.db'),
     },
     'http': {
         'clientapi.http.bind_address': '::',