Skip to content

Commit

Permalink
Updated python packages + custom entrypoint
Browse files Browse the repository at this point in the history
  • Loading branch information
NadavTasher committed Feb 1, 2024
1 parent 84b6e2d commit 67ed99c
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 48 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ DOCKER ?= $(shell which docker)
IMAGE_PATH := image
BUNDLE_PATH := bundle


BACKEND_PATH := $(IMAGE_PATH)/src/backend
FRONTEND_PATH := $(IMAGE_PATH)/src/frontend
ENTRYPOINT_PATH := $(IMAGE_PATH)/src/entrypoint.py

BUNDLE_BACKEND_PATH := $(BUNDLE_PATH)/application/src/backend
BUNDLE_FRONTEND_PATH := $(BUNDLE_PATH)/application/src/frontend
Expand All @@ -25,7 +27,7 @@ IMAGE_SOURCES := $(shell find $(IMAGE_PATH) -type f)
prerequisites:
$(PYTHON) -m pip install jinja2-cli yapf

format: $(wildcard $(BACKEND_PATH)/*.py) | prerequisites
format: $(wildcard $(BACKEND_PATH)/*.py) $(ENTRYPOINT_PATH) | prerequisites
$(PYTHON) -m yapf -i $^ --style "{based_on_style: google, column_limit: 400, indent_width: 4}"

image: $(IMAGE_PATH)/Dockerfile-$(IMAGE_TAG) | format $(IMAGE_SOURCES)
Expand Down
2 changes: 1 addition & 1 deletion bundle/application/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM webhood/3.8

# Copy configurations
COPY configurations/nginx.conf /etc/nginx/conf.d/nginx.conf
COPY configurations/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY configurations/entrypoint.conf /etc/entrypoint/conf.d/entrypoint.conf

# Copy sources
COPY src /application
2 changes: 2 additions & 0 deletions bundle/application/configurations/entrypoint.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[worker]
replication=1
2 changes: 0 additions & 2 deletions bundle/application/configurations/supervisord.conf

This file was deleted.

16 changes: 11 additions & 5 deletions image/Dockerfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@
FROM {{BASE_IMAGE}}

# Upgrade pip and install dependencies
RUN pip install --upgrade pip ipython flask jinja2 gunicorn runtypes fsdicts guardify
RUN pip install --upgrade pip ipython flask jinja2 gunicorn fsdicts runtypes guardify

# Install supervisor
# Install NGINX
RUN apt update
RUN apt -y install supervisor nginx
RUN apt -y install nginx

# Copy default configurations
COPY configurations/nginx.conf /etc/nginx/nginx.conf
COPY configurations/supervisord.conf /etc/supervisor/supervisord.conf
COPY configurations/entrypoint.conf /etc/entrypoint/entrypoint.conf
COPY configurations/gunicorn.conf /etc/gunicorn.conf

# Copy default sources
COPY src /application

# Change working directory to application
WORKDIR /application

# Specify stop signal
STOPSIGNAL SIGINT

# Set default command to run
CMD [ "/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf" ]
CMD [ "/usr/local/bin/python", "entrypoint.py" ]

# Create the certificate and the key
RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -subj / -keyout /etc/ssl/private/server.key -out /etc/ssl/private/server.crt
14 changes: 14 additions & 0 deletions image/configurations/entrypoint.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[nginx]
command=/usr/sbin/nginx
directory=/application/frontend

[worker]
command=/usr/local/bin/python worker.py
directory=/application/backend

[gunicorn]
command=/usr/local/bin/gunicorn --workers 4 --bind unix:/run/gunicorn.sock --log-config /etc/gunicorn.conf --access-logfile - app:router
directory=/application/backend

[include]
files = /etc/entrypoint/conf.d/*.conf
39 changes: 0 additions & 39 deletions image/configurations/supervisord.conf

This file was deleted.

85 changes: 85 additions & 0 deletions image/src/entrypoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import os
import glob
import shlex
import logging
import argparse
import subprocess
import configparser

# Setup the logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")

# Create the argument parser
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--configuration", default="/etc/entrypoint/entrypoint.conf")

# Parse the arguments
arguments = parser.parse_args()

# Create configuration parser
configuration = configparser.ConfigParser()

# Load the configuration
configuration.read(arguments.configuration)

# Check whether should include more files
if configuration.has_section("include"):
# Get the extra configuration glob
extra_files = glob.glob(configuration.get("include", "files"))

# Load all of these files
for extra_file in extra_files:
configuration.read(extra_file)

# Pop the include section
configuration.pop("include")

# Create list of processes
processes = dict()

try:
# Loop over sections and parse them
for name in configuration.sections():
# Fetch the configuration
program_configuration = configuration[name]

# Create the processes
for worker in range(int(program_configuration.get("replication", 1))):
# Create the process using the values
process = subprocess.Popen(shlex.split(program_configuration["command"]), stdin=subprocess.DEVNULL, cwd=program_configuration.get("directory"))

# Add the process to the dictionary
processes[process.pid] = ("%s_%d" % (name, worker + 1), process)

# Log the startup
logging.info("Started worker %d for %s", worker + 1, name)

# Wait for any process to finish
stopped_process_id, stopped_process_exit_code = os.wait()

# Find the stopped process
stopped_process_name, _ = processes[stopped_process_id]

# Log the killed process
logging.error("Process %s has stopped - exit code %d", stopped_process_name, stopped_process_exit_code)
finally:
# Loop over all processes
for (process_name, process) in processes.values():
# Make sure process is stopped
if process.poll() is not None:
continue

# Log termination
logging.warning("Terminating %s (%d)", process_name, process.pid)

# Stop running process
process.terminate()

# Wait for all processes to finish
for (process_name, process) in processes.values():
# Log wait for termination
if process.poll() is None:
logging.info("Waiting for %s (%d) to terminate", process_name, process.pid)

# Wait for termination
process.wait()

0 comments on commit 67ed99c

Please sign in to comment.