Source code for betty.extension.nginx.serve

"""
Integrate the nginx extension with Betty's Serve API.
"""
import logging
from pathlib import Path
from typing import Any

import docker
from aiofiles.tempfile import TemporaryDirectory, AiofilesContextManagerTempDir
from docker.errors import DockerException

from betty.app import App
from betty.extension.nginx.artifact import generate_dockerfile_file, generate_configuration_file
from betty.extension.nginx.docker import Container
from betty.project import Project
from betty.serve import NoPublicUrlBecauseServerNotStartedError, AppServer


[docs] class DockerizedNginxServer(AppServer): def __init__(self, app: App) -> None: from betty.extension import Nginx project = Project(ancestry=app.project.ancestry) project.configuration.autowrite = False project.configuration.configuration_file_path = app.project.configuration.configuration_file_path project.configuration.update(app.project.configuration) project.configuration.debug = True app = App(app.configuration, project) # Work around https://github.com/bartfeenstra/betty/issues/1056. app.extensions[Nginx].configuration.https = False super().__init__(app) self._container: Container | None = None self._output_directory: AiofilesContextManagerTempDir[None, Any, Any] | None = None
[docs] async def start(self) -> None: await super().start() logging.getLogger(__name__).info('Starting a Dockerized nginx web server...') self._output_directory = TemporaryDirectory() output_directory_name = await self._output_directory.__aenter__() nginx_configuration_file_path = Path(output_directory_name) / 'nginx.conf' docker_directory_path = Path(output_directory_name) dockerfile_file_path = docker_directory_path / 'Dockerfile' await generate_configuration_file( self._app, destination_file_path=nginx_configuration_file_path, https=False, www_directory_path='/var/www/betty', ) await generate_dockerfile_file( self._app, destination_file_path=dockerfile_file_path, ) self._container = Container( self._app.project.configuration.www_directory_path, docker_directory_path, nginx_configuration_file_path, ) await self._container.start() await self.assert_available()
[docs] async def stop(self) -> None: if self._container is not None: await self._container.stop() if self._output_directory is not None: await self._output_directory.__aexit__(None, None, None)
@property def public_url(self) -> str: if self._container is not None: return 'http://%s' % self._container.ip raise NoPublicUrlBecauseServerNotStartedError()
[docs] @classmethod def is_available(cls) -> bool: try: docker.from_env().info() return True except DockerException as e: logging.getLogger(__name__).warning(e) return False