Build 060.30: finalize Market Data Acquisition documentation

This commit is contained in:
2026-08-03 23:30:41 +03:00
parent 8c98de9acc
commit 64a5bdd04c
61 changed files with 13980 additions and 1873 deletions

View File

@@ -1,12 +1,41 @@
FROM python:3.12-slim
FROM python:3.12.13-slim-bookworm@sha256:d50fb7611f86d04a3b0471b46d7557818d88983fc3136726336b2a4c657aa30b
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
ENV PIP_NO_CACHE_DIR=1
ENV PIP_ROOT_USER_ACTION=ignore
WORKDIR /project
COPY app /project/app
RUN pip install --no-cache-dir -r /project/app/requirements.txt
RUN groupadd --gid 10001 dzentra \
&& useradd --uid 10001 \
--gid dzentra \
--no-create-home \
--home-dir /nonexistent \
--shell /usr/sbin/nologin \
dzentra \
&& install -d \
-m 0700 \
-o dzentra \
-g dzentra \
/var/lib/dzentra \
&& install \
-m 0600 \
-o dzentra \
-g dzentra \
/dev/null \
/var/lib/dzentra/runtime.env
WORKDIR /project/app
COPY app/requirements.lock ./requirements.lock
RUN python -m pip install \
--require-hashes \
--requirement requirements.lock
COPY --chown=10001:10001 app/src ./src
USER 10001:10001
STOPSIGNAL SIGINT
CMD ["python", "-m", "src.main"]

View File

@@ -0,0 +1,9 @@
FROM postgres:16.14-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
COPY --chmod=0555 \
infra/docker/postgres/init-application-role.sh \
/docker-entrypoint-initdb.d/20-init-application-role.sh
COPY --chmod=0555 \
infra/docker/postgres/healthcheck-application-role.sh \
/usr/local/bin/dzentra-postgres-healthcheck

View File

@@ -0,0 +1,48 @@
#!/bin/sh
set -eu
role_status="$(
psql \
--no-psqlrc \
--set ON_ERROR_STOP=1 \
--tuples-only \
--no-align \
--username "$POSTGRES_USER" \
--dbname "$POSTGRES_DB" <<'SQL'
\getenv app_user APP_DB_USER
SELECT CASE
WHEN :'app_user' <> current_user
AND EXISTS (
SELECT 1
FROM pg_catalog.pg_roles
WHERE rolname = :'app_user'
AND rolcanlogin
AND NOT rolsuper
AND NOT rolcreatedb
AND NOT rolcreaterole
AND rolinherit
AND NOT rolreplication
AND NOT rolbypassrls
)
AND pg_catalog.pg_get_userbyid((
SELECT datdba
FROM pg_catalog.pg_database
WHERE datname = current_database()
)) = :'app_user'
AND NOT EXISTS (
SELECT 1
FROM pg_catalog.pg_auth_members AS membership
JOIN pg_catalog.pg_roles AS member_role
ON member_role.oid = membership.member
WHERE member_role.rolname = :'app_user'
)
THEN 1
ELSE 0
END;
SQL
)"
test "$role_status" = "1"

View File

@@ -0,0 +1,130 @@
#!/bin/sh
set -eu
read_secret_file() {
secret_path=$1
if [ ! -r "$secret_path" ]; then
echo "Не удалось прочитать обязательный PostgreSQL secret file" >&2
return 1
fi
# Маркер сохраняет переводы строк внутри command substitution.
secret_with_marker="$(cat "$secret_path"; printf '\001')"
secret=${secret_with_marker%?}
carriage_return="$(printf '\r')"
newline='
'
case "$secret" in
*"${carriage_return}${newline}")
secret=${secret%"${carriage_return}${newline}"}
;;
*"${newline}")
secret=${secret%"${newline}"}
;;
*"${carriage_return}")
secret=${secret%"${carriage_return}"}
;;
esac
if [ -z "$(printf '%s' "$secret" | tr -d '[:space:]')" ]; then
echo "PostgreSQL secret file содержит пустое значение" >&2
return 1
fi
printf '%s' "$secret"
}
if [ -z "${APP_DB_USER:-}" ]; then
echo "APP_DB_USER должен содержать имя роли приложения" >&2
exit 1
fi
if [ "$APP_DB_USER" = "$POSTGRES_USER" ]; then
echo "APP_DB_USER не должен совпадать с PostgreSQL admin role" >&2
exit 1
fi
app_db_password="$(read_secret_file /run/secrets/db_password)"
# Официальный entrypoint уже прочитал secret file и применил собственную
# нормализацию конечных переводов строк. Сравниваем именно фактический пароль.
if [ -z "$(printf '%s' "${POSTGRES_PASSWORD:-}" | tr -d '[:space:]')" ]; then
echo "POSTGRES_PASSWORD должен содержать пароль admin role" >&2
exit 1
fi
postgres_admin_password=$POSTGRES_PASSWORD
if [ "$app_db_password" = "$postgres_admin_password" ]; then
echo "Пароли PostgreSQL admin и application roles должны различаться" >&2
exit 1
fi
export DZENTRA_APP_DB_PASSWORD="$app_db_password"
psql \
--no-psqlrc \
--single-transaction \
--set ON_ERROR_STOP=1 \
--username "$POSTGRES_USER" \
--dbname "$POSTGRES_DB" <<'SQL'
\getenv app_user APP_DB_USER
\getenv app_password DZENTRA_APP_DB_PASSWORD
SELECT format(
'CREATE ROLE %I LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB '
'NOCREATEROLE INHERIT NOREPLICATION NOBYPASSRLS',
:'app_user',
:'app_password'
)
WHERE NOT EXISTS (
SELECT 1
FROM pg_catalog.pg_roles
WHERE rolname = :'app_user'
)
\gexec
SELECT format(
'ALTER ROLE %I WITH LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB '
'NOCREATEROLE INHERIT NOREPLICATION NOBYPASSRLS',
:'app_user',
:'app_password'
)
\gexec
SELECT format(
'ALTER DATABASE %I OWNER TO %I',
current_database(),
:'app_user'
)
\gexec
SELECT format(
'REVOKE ALL ON DATABASE %I FROM PUBLIC',
current_database()
)
\gexec
SELECT format(
'GRANT CONNECT, TEMPORARY ON DATABASE %I TO %I',
current_database(),
:'app_user'
)
\gexec
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
SELECT format(
'GRANT USAGE, CREATE ON SCHEMA public TO %I',
:'app_user'
)
\gexec
SQL
unset DZENTRA_APP_DB_PASSWORD
unset app_db_password
unset postgres_admin_password