Skip to content

Commit

Permalink
Merge pull request #118 from kjsanger/feature/porch-2.0.0
Browse files Browse the repository at this point in the history
Add npg_porch 2.0.0 server
  • Loading branch information
kjsanger authored Oct 8, 2024
2 parents 5e50a58 + f7f73f7 commit b174fc0
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 48 deletions.
116 changes: 68 additions & 48 deletions docker/Makefile

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions docker/porch/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

ARG BASE_IMAGE=python:3.10-slim
FROM $BASE_IMAGE as builder

ENV DEBIAN_FRONTEND="noninteractive"

RUN apt-get update && \
apt-get install -q -y --no-install-recommends \
build-essential \
gcc \
git \
libsqlite3-dev \
unattended-upgrades && \
unattended-upgrade -v

WORKDIR /app

COPY ./scripts/*.sh /app/docker/scripts/

COPY ./logging.json /app/docker/logging.json

ARG PORCH_VERSION=2.0.0

# The last 2 lines are a workaround for porch's pip install not copying the scripts
RUN python -m venv /app && \
. /app/bin/activate && \
pip install --no-cache-dir --upgrade pip && \
git clone --branch "v${PORCH_VERSION}" --single-branch https://github.com/wtsi-npg/npg_porch.git /tmp/npg_porch && \
cd /tmp/npg_porch && \
pip install --no-cache-dir . && \
mkdir /app/scripts && \
cp ./scripts/*.py /app/scripts/

FROM $BASE_IMAGE

ARG DEBIAN_FRONTEND

RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -q -y --no-install-recommends \
curl \
libsqlite3-0 \
postgresql \
sudo \
tini \
locales && \
locale-gen en_GB en_GB.UTF-8 && \
localedef -i en_GB -c -f UTF-8 -A /usr/share/locale/locale.alias en_GB.UTF-8

RUN apt-get install -q -y --no-install-recommends \
unattended-upgrades && \
unattended-upgrade -v && \
apt-get remove -q -y unattended-upgrades && \
apt-get autoremove -q -y && \
apt-get clean -q -y && \
rm -rf /var/lib/apt/lists/*

ENV LANG=en_GB.UTF-8 \
LANGUAGE=en_GB \
LC_ALL=en_GB.UTF-8 \
TZ="Etc/UTC"

ARG APP_USER=appuser
ARG APP_UID=1000
ARG APP_GID=$APP_UID

WORKDIR /app

RUN groupadd --gid $APP_GID $APP_USER && \
useradd --uid $APP_UID --gid $APP_GID --shell /bin/bash --create-home $APP_USER

COPY --from=builder --chown=$APP_USER:$APP_GID /app /app

ARG DB_HOST=localhost
ARG DB_PORT=5432
ARG DB_SCHEMA=porch_dev
ARG DB_NAME=porch_dev_db
ARG DB_USER=porch_admin
ARG DB_PASS=porch
ARG URL_SLUG="$DB_USER:$DB_PASS@$DB_HOST:$DB_PORT/$DB_NAME"

ENV DB_HOST=$DB_HOST \
DB_PORT=$DB_PORT \
DB_SCHEMA=$DB_SCHEMA \
DB_NAME=$DB_NAME \
DB_USER=$DB_USER \
DB_PASS=$DB_PASS \
DB_URL="postgresql+psycopg2://$URL_SLUG"

RUN service postgresql start && \
/app/docker/scripts/create_database.sh && \
/app/docker/scripts/configure_database_service.sh && \
. /app/bin/activate && \
/app/scripts/deploy_schema.py && \
/app/docker/scripts/insert_admin_token.sh && \
service postgresql stop

USER $APP_USER

ARG PORT=8081

ENV DB_URL="postgresql+asyncpg://$URL_SLUG" \
PORT=${PORT}

EXPOSE ${PORT}

HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=3 CMD curl -f http://localhost:${PORT} || exit 1

ENTRYPOINT ["/usr/bin/tini", "--"]

CMD ["/app/docker/scripts/entrypoint.sh"]
27 changes: 27 additions & 0 deletions docker/porch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# NPG Porch Server

**Not for use in production!**

This is a Docker image hosting both a Porch server and its PostgreSQL database
that works out of the box. To be used for running tests only.

The application is populated with a hard-coded administrator user, password and
administration token and is configured log to STDERR and STDOUT.

## Using the container
### Running

To run the container (with the Porch port published to the host network):

`docker run -d -name porch -p 8081:8081 wsinpg/python-3.10-npg-porch-[VERSION]:latest`

where [VERSION] is the required npg_porch release e.g. 2.0.0

### Connecting

The Porch server is configured to use HTTP on port 8081 and an admin token of

`00000000000000000000000000000000`

has been set in the database. See the Dockerfile for the configuration of the
backend database.
51 changes: 51 additions & 0 deletions docker/porch/logging.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"version": 1,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(levelprefix)s %(message)s",
"use_colors": null
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(levelprefix)s %(client_addr)s - \"%(request_line)s\" %(status_code)s"
}
},
"handlers": {
"stderr": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
"stdout": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"uvicorn": {
"handlers": ["access"],
"level": "INFO",
"propagate": false
},
"uvicorn.error": {
"handlers": ["stderr"],
"level": "DEBUG",
"propagate": false
},
"fastapi": {
"handlers": ["stderr"],
"level": "INFO"
}
},
"root": {
"handlers": ["stdout"],
"level": "DEBUG"
}
}
12 changes: 12 additions & 0 deletions docker/porch/scripts/configure_database_service.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

set -eo pipefail
set -x

APP_USER=${APP_USER:? The APP_USER environment variable must be set}

cat > "/etc/sudoers.d/$APP_USER" << EOF
$APP_USER ALL= NOPASSWD: /usr/sbin/service postgresql start
$APP_USER ALL= NOPASSWD: /usr/sbin/service postgresql restart
$APP_USER ALL= NOPASSWD: /usr/sbin/service postgresql stop
EOF
30 changes: 30 additions & 0 deletions docker/porch/scripts/create_database.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

set -eo pipefail
set -x

pg_isready --quiet || {
echo "PostgreSQL is not ready" >&2
exit 1
}

DB_SCHEMA=${DB_SCHEMA:? The DB_SCHEMA environment variable must be set}
DB_NAME=${DB_NAME:? The DB_NAME environment variable must be set}
DB_USER=${DB_USER:? The DB_USER environment variable must be set}
DB_PASS=${DB_PASS:? The DB_PASS environment variable must be set}

sudo -u postgres createuser -D -R -S ${DB_USER}
sudo -u postgres createdb -O ${DB_USER} ${DB_NAME}

sudo -u postgres psql -d ${DB_NAME} << EOF
ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASS}';
CREATE SCHEMA ${DB_SCHEMA};
SET search_path TO ${DB_SCHEMA}, public;
GRANT ALL PRIVILEGES ON SCHEMA ${DB_SCHEMA} TO ${DB_USER};
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA ${DB_SCHEMA} TO ${DB_USER};
GRANT USAGE ON ALL SEQUENCES IN SCHEMA ${DB_SCHEMA} TO ${DB_USER};
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA ${DB_SCHEMA} TO ${DB_USER};
EOF
16 changes: 16 additions & 0 deletions docker/porch/scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -eo pipefail

sudo service postgresql start

pg_isready --quiet --timeout=30 || {
echo "PostgreSQL is not ready" >&2
exit 1
}

PORT=${PORT:? The PORT environment variable must be set}

source /app/bin/activate

exec uvicorn npg_porch.server:app --host 0.0.0.0 --port ${PORT} --reload --log-config /app/docker/logging.json
18 changes: 18 additions & 0 deletions docker/porch/scripts/insert_admin_token.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

set -eo pipefail
set -x

pg_isready --quiet || {
echo "PostgreSQL is not ready" >&2
exit 1
}

DB_SCHEMA=${DB_SCHEMA:? The DB_SCHEMA environment variable must be set}
DB_NAME=${DB_NAME:? The DB_NAME environment variable must be set}

ADMIN_TOKEN=${ADMIN_TOKEN:="00000000000000000000000000000000"}

sudo -u postgres psql -d ${DB_NAME} << EOF
INSERT INTO ${DB_SCHEMA}."token" (token, description, date_issued) VALUES ('${ADMIN_TOKEN}', 'Admin token', NOW());
EOF

0 comments on commit b174fc0

Please sign in to comment.