diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile index 5200d1f..9a63219 100644 --- a/ci/Jenkinsfile +++ b/ci/Jenkinsfile @@ -51,5 +51,21 @@ pipeline { } } } + + stage('Build Container') { + steps { + container('podman') { + sh '. ci/build-container.sh' + } + } + } + + stage('Publish Container') { + steps { + container('podman') { + sh '. ci/publish-container.sh' + } + } + } } } diff --git a/ci/build-container.sh b/ci/build-container.sh new file mode 100644 index 0000000..133b5f2 --- /dev/null +++ b/ci/build-container.sh @@ -0,0 +1,7 @@ +#!/bin/sh -ex + +. ci/container-common.sh + +cp -r svc/dist container/wheels +cp -r ui/dist container/ui +podman build -t hudctrl:$(tag_name ${BUILD_TAG}) container diff --git a/ci/container-common.sh b/ci/container-common.sh new file mode 100644 index 0000000..506b03e --- /dev/null +++ b/ci/container-common.sh @@ -0,0 +1,10 @@ +# shellcheck: shell=sh + +tag_name() { + echo "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g' -e 's/^[.-]/_/' +} + +push() { + tag=$(tag_name $1) + podman push hudctrl:${BUILD_TAG} registry.pyrocufflink.blue/hudctrl:${tag} +} diff --git a/ci/podTemplate.yaml b/ci/podTemplate.yaml index 8018237..42912aa 100644 --- a/ci/podTemplate.yaml +++ b/ci/podTemplate.yaml @@ -27,3 +27,10 @@ spec: securityContext: readOnlyRootFilesystem: true runAsUser: 1000 + - name: podman + image: quay.io/containers/podman:v3.4 + command: + - sleep + - infinity + securityContext: + privileged: true diff --git a/ci/publish-container.sh b/ci/publish-container.sh new file mode 100644 index 0000000..2e7ba42 --- /dev/null +++ b/ci/publish-container.sh @@ -0,0 +1,9 @@ +#!/bin/sh -ex + +. ci/container-common.sh + +push ${BUILD_TAG} +push ${BRANCH_NAME} +if [ "${BRANCH_NAME}" = master ]; then + push latest +fi diff --git a/container/.gitignore b/container/.gitignore new file mode 100644 index 0000000..6224957 --- /dev/null +++ b/container/.gitignore @@ -0,0 +1,2 @@ +ui/ +wheels/ diff --git a/container/Containerfile b/container/Containerfile new file mode 100644 index 0000000..2719b82 --- /dev/null +++ b/container/Containerfile @@ -0,0 +1,19 @@ +FROM docker.io/python:3.10-slim AS build + +COPY wheels /tmp/wheels +COPY requirements.txt /tmp +RUN python -m venv /usr/local/hudctrl +RUN /usr/local/hudctrl/bin/python -m \ + pip install -f /tmp/wheels -r /tmp/requirements.txt + +COPY ui /usr/local/hudctrl/ui + +FROM docker.io/python:3.10-slim +RUN apt-get update && \ + apt-get install -y nginx tini && \ + rm -rf /var/cache/apt /var/lib/apt +COPY nginx.conf /etc/nginx/nginx.conf +COPY --from=build /usr/local/hudctrl /usr/local/hudctrl +COPY run.sh / + +CMD ["tini", "--", "/run.sh"] diff --git a/container/nginx.conf b/container/nginx.conf new file mode 100644 index 0000000..cd491a4 --- /dev/null +++ b/container/nginx.conf @@ -0,0 +1,42 @@ +# vim: set sw=4 ts=4 sts=4 et : + +user www-data; +worker_processes auto; +pid /run/nginx.pid; + +events { + worker_connections 768; +} + +http { + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log /dev/stderr; + error_log /var/log/nginx/error.log; + + gzip on; + + server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + root /usr/local/hudctrl/ui; + index index.html; + + location /api/ { + proxy_pass http://127.0.0.1:8000/; + + real_ip_header X-Forwarded-For; + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + real_ip_recursive on; + proxy_set_header Host $proxy_host; + } + } +} diff --git a/container/requirements.txt b/container/requirements.txt new file mode 100644 index 0000000..5b79bc8 --- /dev/null +++ b/container/requirements.txt @@ -0,0 +1,3 @@ +gunicorn +hudctrl +uvicorn diff --git a/container/run.sh b/container/run.sh new file mode 100755 index 0000000..4e2b242 --- /dev/null +++ b/container/run.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# vim: set sw=4 ts=4 sts=4 et : + +nginx || exit $? +exec /usr/local/hudctrl/bin/gunicorn \ + -k uvicorn.workers.UvicornWorker \ + hudctrl.api:app