Docker + docker compose support

main
Thomas Sileo 2022-07-18 20:44:55 +02:00
parent 3e7ad917e2
commit fe88481431
10 changed files with 141 additions and 29 deletions

2
.gitignore vendored
View File

@ -4,4 +4,4 @@ __pycache__/
.pytest_cache/
docs/dist/
requirements.txt
app/scss/_vars.scss
app/_version.py

28
Dockerfile 100644
View File

@ -0,0 +1,28 @@
FROM python:3.10-slim as python-base
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
POETRY_HOME="/opt/poetry" \
POETRY_VIRTUALENVS_IN_PROJECT=true \
POETRY_NO_INTERACTION=1 \
PYSETUP_PATH="/opt/venv" \
VENV_PATH="/opt/venv/.venv"
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
FROM python-base as builder-base
RUN apt-get update
RUN apt-get install -y --no-install-recommends curl build-essential gcc
RUN curl -sSL https://install.python-poetry.org | python3 -
WORKDIR $PYSETUP_PATH
COPY poetry.lock pyproject.toml ./
RUN poetry install --no-dev
FROM python-base as production
RUN groupadd --gid 1000 microblogpub \
&& useradd --uid 1000 --gid microblogpub --shell /bin/bash microblogpub
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
COPY . /app/
RUN chown -R 1000:1000 /app
USER microblogpub
WORKDIR /app
EXPOSE 8000
CMD ["supervisord", "-n", "-c", "misc/docker-supervisord.conf"]

7
Makefile 100644
View File

@ -0,0 +1,7 @@
SHELL := /bin/bash
PWD=$(shell pwd)
.PHONY: config
config:
# Run and remove instantly
-docker run --rm -it --volume `pwd`/data:/app/data microblogpub/microblogpub inv configuration-wizard

View File

@ -145,7 +145,7 @@ async def save_actor(db_session: AsyncSession, ap_actor: ap.RawObject) -> "Actor
handle=_handle(ap_actor),
)
db_session.add(actor)
await db_session.flush()
await db_session.commit()
return actor

View File

@ -1,6 +1,5 @@
import os
import secrets
import subprocess
from pathlib import Path
import bcrypt
@ -19,11 +18,13 @@ ROOT_DIR = Path().parent.resolve()
_CONFIG_FILE = os.getenv("MICROBLOGPUB_CONFIG_FILE", "profile.toml")
VERSION_COMMIT = (
subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"])
.split()[0]
.decode()
)
VERSION_COMMIT = "dev"
try:
from app._version import VERSION_COMMIT # type: ignore
except ImportError:
pass
VERSION = f"2.0.0+{VERSION_COMMIT}"
USER_AGENT = f"microblogpub/{VERSION}"

12
docker-compose.yml 100644
View File

@ -0,0 +1,12 @@
version: "3"
services:
server:
image: microblogpub/microblogpub:latest
container_name: microblogpub
user: 1000:1000
restart: always
volumes:
- ./data:/app/data
ports:
- "8000:8000"

View File

@ -0,0 +1,28 @@
[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=data/supervisord.pid
[fcgi-program:uvicorn]
socket=tcp://0.0.0.0:8000
command=uvicorn app.main:app --no-server-header --fd 0
numprocs=2
process_name=uvicorn-%(process_num)d
redirect_stderr=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
[program:incoming_worker]
command=inv process-incoming-activities
numproc=1
redirect_stderr=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
[program:outgoing_worker]
command=inv process-outgoing-activities
numproc=1
redirect_stderr=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0

28
poetry.lock generated
View File

@ -161,7 +161,7 @@ testing = ["pytest"]
name = "boussole"
version = "2.0.0"
description = "Commandline interface to build Sass projects using libsass-python"
category = "dev"
category = "main"
optional = false
python-versions = "*"
@ -248,7 +248,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
name = "colorlog"
version = "6.6.0"
description = "Add colours to the output of Python's logging module."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.6"
@ -489,7 +489,7 @@ python-versions = "*"
name = "invoke"
version = "1.7.1"
description = "Pythonic task execution"
category = "dev"
category = "main"
optional = false
python-versions = "*"
@ -533,7 +533,7 @@ i18n = ["Babel (>=2.7)"]
name = "libsass"
version = "0.21.0"
description = "Sass for Python: A straightforward binding of libsass for Python."
category = "dev"
category = "main"
optional = false
python-versions = "*"
@ -741,7 +741,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
name = "pyaml"
version = "21.10.1"
description = "PyYAML-based module to produce pretty and readable YAML-serialized data"
category = "dev"
category = "main"
optional = false
python-versions = "*"
@ -894,7 +894,7 @@ six = ">=1.4.0"
name = "pyyaml"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "dev"
category = "main"
optional = false
python-versions = ">=3.6"
@ -1022,6 +1022,17 @@ anyio = ">=3.4.0,<5"
[package.extras]
full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"]
[[package]]
name = "supervisor"
version = "4.2.4"
description = "A system for controlling process state under UNIX"
category = "main"
optional = false
python-versions = "*"
[package.extras]
testing = ["pytest", "pytest-cov"]
[[package]]
name = "tabulate"
version = "0.8.10"
@ -1165,7 +1176,7 @@ standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchgod (>=0.6)", "p
name = "watchdog"
version = "2.1.9"
description = "Filesystem events monitoring"
category = "dev"
category = "main"
optional = false
python-versions = ">=3.6"
@ -1202,7 +1213,7 @@ dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
[metadata]
lock-version = "1.1"
python-versions = "^3.10"
content-hash = "d0c330a9153ced7f4ba61e5354bc7bb3136a3d11f4f700bb76498c20e200c509"
content-hash = "5ee42d968baa21950366d1ca0597fb1e0e45e6e26005f93acbcf8b43cd1fb370"
[metadata.files]
aiosqlite = [
@ -2002,6 +2013,7 @@ starlette = [
{file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"},
{file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"},
]
supervisor = []
tabulate = []
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},

View File

@ -40,6 +40,9 @@ cachetools = "^5.2.0"
humanize = "^4.2.3"
tabulate = "^0.8.10"
asgiref = "^3.5.2"
supervisor = "^4.2.4"
invoke = "^1.7.1"
boussole = "^2.0.0"
[tool.poetry.dev-dependencies]
black = "^22.3.0"

View File

@ -1,7 +1,10 @@
import asyncio
import io
import subprocess
import tarfile
from contextlib import contextmanager
from pathlib import Path
from typing import Generator
from typing import Optional
import httpx
@ -13,13 +16,13 @@ from invoke import task # type: ignore
@task
def generate_db_migration(ctx, message):
# type: (Context, str) -> None
run(f'poetry run alembic revision --autogenerate -m "{message}"', echo=True)
run(f'alembic revision --autogenerate -m "{message}"', echo=True)
@task
def migrate_db(ctx):
# type: (Context) -> None
run("poetry run alembic upgrade head", echo=True)
run("alembic upgrade head", echo=True)
@task
@ -46,15 +49,15 @@ def compile_scss(ctx, watch=False):
theme_file.write_text("// override vars for theming here")
if watch:
run("poetry run boussole watch", echo=True)
run("boussole watch", echo=True)
else:
run("poetry run boussole compile", echo=True)
run("boussole compile", echo=True)
@task
def uvicorn(ctx):
# type: (Context) -> None
run("poetry run uvicorn app.main:app --no-server-header", pty=True, echo=True)
run("uvicorn app.main:app --no-server-header", pty=True, echo=True)
@task
@ -96,16 +99,11 @@ def generate_requirements_txt(ctx, where="requirements.txt"):
)
@task(generate_requirements_txt)
def build_configuration_wizard_image(ctx):
# type: (Context) -> None
run("docker build -t testmpw -f configuration_wizard.dockerfile .")
@task
def build_docs(ctx):
# type: (Context) -> None
run("PYTHONPATH=. poetry run python scripts/build_docs.py", pty=True, echo=True)
with embed_version():
run("PYTHONPATH=. python scripts/build_docs.py", pty=True, echo=True)
@task
@ -131,7 +129,7 @@ def download_twemoji(ctx):
@task(download_twemoji, compile_scss, migrate_db)
def configuration_wizard(ctx):
# type: (Context) -> None
run("PYTHONPATH=. poetry run python scripts/config_wizard.py", pty=True, echo=True)
run("PYTHONPATH=. python scripts/config_wizard.py", pty=True, echo=True)
@task
@ -152,3 +150,26 @@ def stats(ctx):
from app.utils.stats import print_stats
print_stats()
@contextmanager
def embed_version() -> Generator[None, None, None]:
version_file = Path("app/_version.py")
version_file.unlink(missing_ok=True)
version = (
subprocess.check_output(["git", "rev-parse", "--short=8", "v2"])
.split()[0]
.decode()
)
version_file.write_text(f'VERSION_COMMIT = "{version}"')
try:
yield
finally:
version_file.unlink()
@task
def build_docker_image(ctx):
# type: (Context) -> None
with embed_version():
run("docker build -t microblogpub/microblogpub .")