Skip to content
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

feat(schematic): added nginx to schematic docker container #2403

Merged
merged 44 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b350762
update uwsgi
linglp Dec 11, 2023
18ce930
add main
linglp Dec 11, 2023
a29bb29
format
linglp Dec 11, 2023
55f9b98
update docker file and update nginx config files
linglp Dec 11, 2023
12b2f1b
update to use python3.10.13
linglp Dec 11, 2023
65b44c6
update config file
linglp Dec 13, 2023
60bc33b
update to use python version 3.10.13
linglp Dec 13, 2023
3697242
udate dokcer compose up
linglp Dec 13, 2023
9e07f5d
update docker file
linglp Dec 13, 2023
2458bcb
edit comment and remove unnecessary part in dockerfile
linglp Dec 15, 2023
bbe3173
slightly modify nginx conf; add error page 497
linglp Jan 11, 2024
881d1e1
combine server block; remove redirect.conf
linglp Jan 11, 2024
e92e3bb
remove unnecessary part related to arg
linglp Jan 22, 2024
b9c65cf
update docker file
linglp Jan 22, 2024
ae7295b
use image in ghcr in docker compose
linglp Jan 22, 2024
6175b8d
pull changes from main
linglp Feb 13, 2024
bcf0b9a
redirect to port 8080 and port 8443
linglp Feb 14, 2024
96ace7f
update docker compose to use port 8443
linglp Feb 14, 2024
7e98b7d
updated to use port 7443
linglp Feb 14, 2024
e8d48d7
add package environs
linglp Mar 6, 2024
36f0ae2
modify entrypoint to handle certificate and private key; also add deb…
linglp Mar 6, 2024
74ec3c1
publish docker image one time
linglp Mar 6, 2024
5ac4f3d
try publish image
linglp Mar 6, 2024
5f25577
workflow dispatch
linglp Mar 6, 2024
b2e7988
try trigger docker build again
linglp Mar 6, 2024
bb1e8eb
trigger again
linglp Mar 6, 2024
0e300c0
add one time workflow
linglp Mar 6, 2024
b6a320b
remove one time workflow
linglp Mar 6, 2024
0900cb9
remove echo
linglp Mar 7, 2024
e873bb6
update port number
linglp Mar 8, 2024
cfca2cc
add maintainer names
linglp Mar 8, 2024
8f77e64
resolve conflicts
linglp Mar 8, 2024
00a7f95
revert changes
linglp Mar 8, 2024
63af81a
revert change
linglp Mar 8, 2024
007c5c4
revert adding workflow dispatch
linglp Mar 8, 2024
812722e
modify authors
linglp Mar 11, 2024
fe0ca57
update poetry lock file and also port number
linglp Mar 13, 2024
49b1064
add dhparam.pem
linglp Mar 13, 2024
9ad465b
rename script
linglp Mar 13, 2024
eda99f2
update ReadMe
linglp Mar 13, 2024
b698645
change copy statement
linglp Mar 13, 2024
397553c
update documentation
linglp Mar 14, 2024
fbbb74b
consolidate statements in dockerfile
linglp Mar 14, 2024
766e233
update doc
linglp Mar 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
}
},
"forwardPorts": [
2432, 3000, 3306, 4200, 4211, 5017, 5200, 5432, 5601, 7010, 7080, 7200, 7888, 8010, 8071, 8000,
2432, 3000, 3306, 4200, 4211, 5017, 5200, 5432, 5601, 7010, 7443, 7200, 7888, 8010, 8071, 8000,
8080, 8081, 8082, 8083, 8084, 8085, 8086, 8090, 8091, 8092, 8200, 8787, 8888, 8889, 9090, 9104,
9200, 9411, 27017
],
Expand Down Expand Up @@ -114,7 +114,7 @@
"label": "schematic-api-docs",
"onAutoForward": "silent"
},
"7080": {
"7443": {
"label": "schematic-api",
"onAutoForward": "silent"
},
Expand Down
93 changes: 67 additions & 26 deletions apps/schematic/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,41 +1,82 @@
FROM python:3.10.12-slim-buster
FROM tiangolo/uwsgi-nginx-flask:python3.10

ENV APP_DIR=/opt/app
# add label
LABEL org.opencontainers.image.authors='Milen Nikolov <[email protected]>, Andrew Lamb <[email protected]>, Mialy DeFelice <[email protected]>, Gianna Jordan <[email protected]>, Lingling Peng <[email protected]>'

SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]
# the environment variables defined here are the default
# and can be overwritten by docker run -e VARIABLE = XX
# or can be overwritten by .env when using docker compose
ENV PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1 \
PYTHONHASHSEED=random \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=200 \
POETRY_VERSION=1.3.0 \
APP_PARENT_DIR=/app \
NGINX_CONFIG=/etc/nginx/conf.d \
APP_DIR=/app/app \
ROOT=/ \
UWSGI_INI=/app/uwsgi.ini \
NGINX_WORKER_PROCESSES=1 \
VERSION=$TAG

# hadolint ignore=DL3008
RUN apt-get update -qq -y \
&& apt-get install --no-install-recommends -qq -y \
build-essential \
gosu \
libpcre3 \
libpcre3-dev \
python3-dev \
# run open ssl and generate certificate
RUN apt update \
&& apt-get -y autoclean \
&& apt-get -y autoremove \
&& rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/* \
&& apt-get update \
&& apt-get install -y openssl jq

WORKDIR ${APP_DIR}
COPY schematic_api schematic_api/
COPY pyproject.toml poetry.lock uwsgi.ini ./
# add dhparam.pem
# dhparam.pem was used in ssl-params.conf
COPY ./dhparam.pem /etc/ssl/dhparam.pem

# copy all nginx config files
WORKDIR ${NGINX_CONFIG}
COPY ./self-signed.conf ./ssl-params.conf ./certificate.conf ./

# copy to use custom uwsgi.ini
WORKDIR /app
COPY ./uwsgi.ini ./

# copy files relevant for schematic apis
WORKDIR /app/app
COPY schematic_api ./schematic_api
COPY pyproject.toml poetry.lock ./

# install dependencies
RUN pip install poetry \
&& poetry config --local virtualenvs.create false \
&& poetry run pip install "cython<3.0.0" \
&& poetry run pip install --no-build-isolation pyyaml==5.4.1 \
&& poetry install --with prod --no-root --no-interaction --no-ansi \
&& pip cache purge
&& poetry install --with prod --no-root --no-interaction --no-ansi

# Update file permission
RUN mkdir /root/.synapseCache
RUN mkdir /app/app/manifests
# temporary here to ensure .synapseCache is not empty
RUN echo "This is a test file." > /root/.synapseCache/test.txt
# temporary here until we move .synapseCache to a different path
RUN chmod -R 777 /root /app

WORKDIR /
COPY docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh
# Modify entrypoint script to allow SSL private key and certificate to be saved
WORKDIR ${ROOT}
COPY ./uwsgi-nginx-entrypoint.sh ./entrypoint2.sh
COPY ./uwsgi-nginx-entrypoint.sh ./uwsgi-nginx-entrypoint2.sh
COPY ./save_key_certificate.py ./save_key_certificate.py
RUN chmod +x uwsgi-nginx-entrypoint2.sh
RUN chmod +x entrypoint2.sh
RUN chown -R nginx /uwsgi-nginx-entrypoint2.sh
RUN chown -R nginx /entrypoint2.sh

EXPOSE 7080
WORKDIR ${APP_DIR}

ENTRYPOINT ["/docker-entrypoint.sh"]
# specify entrypoint again to generate config
# have to respecify CMD too
ENTRYPOINT ["/entrypoint2.sh"]
CMD ["/start.sh"]

# Run server in development mode
# CMD ["python", "-m", "openapi_server"]
# Run server in production mode
CMD ["uwsgi", "--ini", "uwsgi.ini", "--lazy", "--http", ":7080"]
# Expose ports
EXPOSE 7443
28 changes: 28 additions & 0 deletions apps/schematic/api/certificate.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
server {
# listen to port 80 for http requests
listen 80 http2 default_server;
# listen to port 7443 for https requests
listen 7443 ssl http2 default_server;
listen [::]:7443 ssl http2 default_server;
include /etc/nginx/conf.d/self-signed.conf;
include /etc/nginx/conf.d/ssl-params.conf;
server_name 127.0.0.1;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
error_page 497 https://$http_host$request_uri;
location / {
try_files $uri @app;
}
location @app {
include uwsgi_params;
uwsgi_pass unix:///tmp/uwsgi.sock;
}
location /static {
alias /app/static;
}
location /health {
return 200 'alive';
add_header Content-Type text/plain;
}
}
76 changes: 76 additions & 0 deletions apps/schematic/api/debug_key_cert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from environs import Env
import subprocess
import json
import base64
import os

# Create an instance of Env
env = Env()

# Load the .env file
env.read_env(path=".env")

# Define key and certificate file path
test_private_key_file_path = "test_private_key.key"
test_certificate_key_file_path = "test_certificate.crt"

# Access the variables
secret_manager_secrets = os.environ["SECRETS_MANAGER_SECRETS"]

ssl_private_key = json.loads(secret_manager_secrets)["SSL_PRIVATE_KEY"]
ssl_certificate_key = json.loads(secret_manager_secrets)["SSL_CERTIFICATE"]

# delete preivous results if necessary
if os.path.exists(test_private_key_file_path):
os.remove(test_private_key_file_path)
if os.path.exists(test_certificate_key_file_path):
os.remove(test_certificate_key_file_path)

# make sure that key and certificate can be decoded in correct format
with open(test_private_key_file_path, "wb") as file:
decoded_private_key = base64.b64decode(ssl_private_key)
file.write(decoded_private_key)

with open(test_certificate_key_file_path, "wb") as file:
decoded_ssl_certificate_key = base64.b64decode(ssl_certificate_key)
file.write(decoded_ssl_certificate_key)


# Make sure that certificate and key match each other
def get_md5_cert(file):
openssl_x509_command = ["openssl", "x509", "-noout", "-modulus", "-in", file]
openssl_md5_command = ["openssl", "md5"]

x509_process = subprocess.Popen(openssl_x509_command, stdout=subprocess.PIPE)
md5_process = subprocess.Popen(
openssl_md5_command, stdin=x509_process.stdout, stdout=subprocess.PIPE
)

output, error = md5_process.communicate()

if error:
print("error getting md5", error.decode("utf-8"))

return output.decode("utf-8").strip()


def get_md5_private_key(file):
openssl_rsa_command = ["openssl", "rsa", "-noout", "-modulus", "-in", file]
openssl_md5_command = ["openssl", "md5"]

rsa_process = subprocess.Popen(openssl_rsa_command, stdout=subprocess.PIPE)
md5_process = subprocess.Popen(
openssl_md5_command, stdin=rsa_process.stdout, stdout=subprocess.PIPE
)

output, error = md5_process.communicate()

if error:
print(error.decode("utf-8"))
return output.decode("utf-8").strip()


md5_key = get_md5_private_key(test_private_key_file_path)
md5_cert = get_md5_cert(test_certificate_key_file_path)

assert md5_key == md5_cert
13 changes: 13 additions & 0 deletions apps/schematic/api/dhparam.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN DH PARAMETERS-----
MIICCAKCAgEAwzcUARDhjqW74+OsC8quGIJhkuL60o9GHuR3feEOky1cY1D/Qm0I
s32FFsm5PutkJ6ZUFf86Uae+ARrQlsidsryHF+bHZpIBe12h/4pcQhH9ghdmHcq6
lqJiD55Gb+uzqe/rmOCInEjl7WXxLvYDzndRbP9gY7I5tVQCdfMTYm7ZYK+Xt53X
ufIkwwkxj3qXimFIEeTJEqK837u7VM9Q5H+nZR+W/lAw8IvYp3wH3IrOmBflWBi/
AaHCemd+gwaS8nZFrNSWffOd9Gg+tuFehlnCSMb4FudEbLk+AyvDAq1RMI1bH1SO
+go/i/iX3u616eXi83/U7JUMNj655Iyoc5F02GlDjyvRRauV50S4nIB7t/mxgGEZ
B7C1wce23PwhsRLxsT5xlti7T3QWgvO0w/P+jnCvwfyu9jUzP87qozAYAV8jCMzx
Henya27o3Qewhr6IuMm7tqo5Bz28AJMm+/DL+XQfF4ceP4XzA4OJVKfQzDKXh4PI
BSw8qY85esWJ3yQjwITygdOMHIxRVQA7Et7kKee3D3iDKeHdRu1m4hLtqRbHesrc
QMdhbZBW6WwYQPeqDhkYKBFbAFrrQHkNAOsduq6/OpWoOuu4yL4K4Sfkd8wQ/3At
e6lfZimHDEHlCIfKM3+MS91zkeOHlBVFVI+H2LiBk6tVcPm1hSK9c+sCAQI=
-----END DH PARAMETERS-----
4 changes: 2 additions & 2 deletions apps/schematic/api/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "3.8"
version: "3.10"

services:
schematic-api:
Expand All @@ -13,7 +13,7 @@ services:
networks:
- schematic
ports:
- "${SERVER_PORT}:7080"
- "7443:7443"

# volumes:
# openchallenges-mariadb:
Expand Down
38 changes: 36 additions & 2 deletions apps/schematic/api/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/schematic/api/prepare-python.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

PYTHON_VERSION="3.10.12"
PYTHON_VERSION="3.10.13"

pyenv install --skip-existing $PYTHON_VERSION

Expand Down
60 changes: 60 additions & 0 deletions apps/schematic/api/prepare_key_certificate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import base64
import json
import subprocess


# Define the paths to your SSL certificate and key
cert_file_path = "private_localhost_certificate.crt"
key_file_path = "private_localhost.key"
env_file_path = ".env" # Path to your .env file

# Define the OpenSSL command
openssl_command = [
"openssl",
"req",
"-x509",
"-nodes",
"-days",
"365",
"-subj",
"/C=US/ST=WA/O=SAGE",
"-newkey",
"rsa:2048",
"-keyout",
key_file_path,
"-out",
cert_file_path,
]

# Run the OpenSSL command
try:
subprocess.run(openssl_command, check=True)
print("SSL certificate and key generated successfully.")
except subprocess.CalledProcessError as e:
print(f"Error generating SSL certificate and key: {e}")


# Function to read a file and encode its contents to Base64
# Certificate has to be in base64 format otherwise can't be parse properly as environment variables
def encode_file_to_base64(file_path):
with open(file_path, "rb") as file:
return base64.b64encode(file.read()).decode("utf-8")


# Encode the SSL certificate and key
ssl_certificate_base64 = encode_file_to_base64(cert_file_path)
ssl_private_key_base64 = encode_file_to_base64(key_file_path)

# Combine into a JSON object
ssl_config_json = json.dumps(
{
"SSL_CERTIFICATE": ssl_certificate_base64,
"SSL_PRIVATE_KEY": ssl_private_key_base64,
}
)

# Append to .env file
with open(env_file_path, "a") as env_file:
env_file.write(f"SECRETS_MANAGER_SECRETS={ssl_config_json}\n")

print("SSL certificate and key have been encoded and appended to the .env file.")
Loading
Loading