-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A Docker image #198
Comments
Cool! The default Docker image doesn't have to cover advanced use cases. I'd say we should expected the application to be mounted to import argparse
import functools
import importlib
import multiprocessing
import bjoern
def load_app(app_module):
try:
app_module_name, app_obj_name = app_module.rsplit(":", 1)
except ValueError:
app_module_name = app_module
app_obj_name = "application"
app_module = importlib.import_module(app_module_name)
try:
return getattr(app_module, app_obj_name)
except AttributeError as err:
raise ImportError(
f"cannot import name {app_obj_name!r} from {app_module_name!r} ({app_module.__file__})"
) from err
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--bind", "-b", type=str, default="127.0.0.1:8000")
parser.add_argument("--workers", "-w", type=int, default=1)
parser.add_argument("app_module")
args = parser.parse_args()
app_obj = load_app(args.app_module)
host, port = args.bind.rsplit(":")
port = int(port)
workers = [
multiprocessing.Process(
target=functools.partial(bjoern.run, app_obj, host, port, reuse_port=True),
daemon=True,
)
for _ in range(args.workers)
]
for w in workers:
w.start()
for w in workers:
w.join()
if __name__ == "__main__":
main() Usage is similar to Gunicorn, eg. |
Hello, thank you to have redirected me here, I read some other issues (mainly related to SIGTERM/SIGKILL) but didn't read this one. Beware that using a single Also there are applications that parse the command line arguments too, there can be a clash between bjoern's options and the application's options. In my branch I use I have some concern about starting multiple workers and to join them afterward. In the current situation I think that if you start the application with 4 workers but 3 fails (outstanding exception, sys.exit, signal, ...) then you are left with just 1 worker going. At work, we have our own (complicated) wsgi server implementation, it is a pre-fork model and it is about 600 python LoC long because it needs to handle signals, resurrect dead workers, and to do other "process management" stuff. As Bjoern advertise itself to be lightweight, I don't know if it is worth to implement multi-workers capabilities (but hey, I discovered your work last night), in a docker environment (often behind kubernetes) there is already all the necessary to start an application in multiple containers (achieving multi-processing). In just did a few research and it appears it is not too much pain to start multiple workers using systemd either see https://unix.stackexchange.com/questions/288236/have-systemd-spawn-n-processes Regards, |
For the multi worker implementation, we should not add anything complex. If you want resiliency etc. you usually have other requirements specific to your setup that you need to implement anyways. I'm happy to add more robustness as long as it's simple to understand for people not familiar with bjoern or server deployment. As for the command line design I've just copied whatever Gunicorn has. |
If you're looking for a no thrills slightly configurable image to run in a containerized cluster (like kubernetes) where you don't care about workers and the like because you just want to spin up more containers to handle scale (or just to use in a docker-compose file for local dev), then I have ones I built from the base python images to work with WSGI Django projects (I've also tested it with Flask and Bottle). It's not exactly fancy pants, but has enough config options that I hopefully documented clearly and it works well for me. Hopefully someone will find it of use as well. https://hub.docker.com/r/tecktron/python-bjoern/ |
@Tecktron any reason for using the large python base image instead of python:alpine mentioned in this ticket? |
@pykler I've often run into issues in alpine with system packages that some libraries require suddenly disappearing, unexpectedly moving repos and suddenly becoming an incompatible version. Due to these experiences I found it not stable enough for my own production needs. Maybe it's matured since then idk. You're welcome to make a PR for it. However, this is a discussion I do not wish to have in an issue of another repo, please kindly open an issue in my repo if you wish to further discuss. Cheers. |
Just in the case if anyone interested in a bit modified @jonashaag script for Django: import argparse
from os import environ
import bjoern
from django.core.wsgi import get_wsgi_application
from pathos.multiprocessing import ProcessingPool as Pool
environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
application = get_wsgi_application()
def run_worker(port):
print(f"Starting worker on port {port}...")
bjoern.run(application, '0.0.0.0', port, reuse_port=True)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--port", "-p", type=int, default=8000)
parser.add_argument("--workers", "-w", type=int, default=1)
args = parser.parse_args()
pool = Pool(nodes=args.workers)
try:
pool.map(run_worker, [args.port] * args.workers)
except KeyboardInterrupt:
pool.terminate()
pool.join()
finally:
print("Exiting...")
if __name__ == "__main__":
main() Note that a |
Could you add instructions as to how to use the docker image? |
In #153 you suggested to create a Docker image. Supposedly to be able to run
bjoern
. Here's the starting point:I could download the latest release:
But it doesn't come with submodules. Although it contains
.gitignore
, and.gitmodules
, so if I dogit init
... that would probably still fail.And what do you expect to happen when one does
docker run --rm bjoern
? And how do I feed an application to it? With e.g.nginx
, by default it shows the welcome page. And to put it to practical use you replace the config, and add a directory with static files.The text was updated successfully, but these errors were encountered: