Docker + docker compose support
This commit is contained in:
		
							parent
							
								
									3e7ad917e2
								
							
						
					
					
						commit
						fe88481431
					
				
					 10 changed files with 141 additions and 29 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -4,4 +4,4 @@ __pycache__/ | |||
| .pytest_cache/ | ||||
| docs/dist/ | ||||
| requirements.txt | ||||
| app/scss/_vars.scss | ||||
| app/_version.py | ||||
|  |  | |||
							
								
								
									
										28
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Dockerfile
									
										
									
									
									
										Normal 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
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
										
									
									
									
										Normal 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 | ||||
|  | @ -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 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								docker-compose.yml
									
										
									
									
									
										Normal 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" | ||||
							
								
								
									
										28
									
								
								misc/docker-supervisord.conf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								misc/docker-supervisord.conf
									
										
									
									
									
										Normal 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
									
									
									
								
							
							
						
						
									
										28
									
								
								poetry.lock
									
										
									
										generated
									
									
									
								
							|  | @ -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"}, | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
							
								
								
									
										47
									
								
								tasks.py
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								tasks.py
									
										
									
									
									
								
							|  | @ -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 .") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue