mirror of
https://github.com/netbox-community/netbox-docker.git
synced 2025-12-10 13:52:38 +00:00
Switch server to Granian
Because the development of Nginx Unit has been stopped, switch the server to Granian which still allows to serve the Python application and the static files from one server.
This commit is contained in:
parent
c89fd3331b
commit
b38ce536b0
1
.github/workflows/push.yml
vendored
1
.github/workflows/push.yml
vendored
|
|
@ -42,6 +42,7 @@ jobs:
|
||||||
VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
|
VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
|
||||||
VALIDATE_GITLEAKS: false
|
VALIDATE_GITLEAKS: false
|
||||||
VALIDATE_JSCPD: false
|
VALIDATE_JSCPD: false
|
||||||
|
VALIDATE_PYTHON_PYLINT: false
|
||||||
VALIDATE_TRIVY: false
|
VALIDATE_TRIVY: false
|
||||||
FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*)
|
FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*)
|
||||||
EDITORCONFIG_FILE_NAME: .editorconfig-checker.json
|
EDITORCONFIG_FILE_NAME: .editorconfig-checker.json
|
||||||
|
|
|
||||||
16
Dockerfile
16
Dockerfile
|
|
@ -27,7 +27,7 @@ ARG NETBOX_PATH
|
||||||
COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt /
|
COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt /
|
||||||
ENV VIRTUAL_ENV=/opt/netbox/venv
|
ENV VIRTUAL_ENV=/opt/netbox/venv
|
||||||
RUN \
|
RUN \
|
||||||
# Gunicorn is not needed because we use Nginx Unit
|
# Gunicorn is not needed because we use Granian
|
||||||
sed -i -e '/gunicorn/d' /requirements.txt && \
|
sed -i -e '/gunicorn/d' /requirements.txt && \
|
||||||
# We need 'social-auth-core[all]' in the Docker image. But if we put it in our own requirements-container.txt
|
# We need 'social-auth-core[all]' in the Docker image. But if we put it in our own requirements-container.txt
|
||||||
# we have potential version conflicts and the build will fail.
|
# we have potential version conflicts and the build will fail.
|
||||||
|
|
@ -46,8 +46,6 @@ RUN \
|
||||||
ARG FROM
|
ARG FROM
|
||||||
FROM ${FROM} AS main
|
FROM ${FROM} AS main
|
||||||
|
|
||||||
COPY docker/unit.list /etc/apt/sources.list.d/unit.list
|
|
||||||
ADD --chmod=444 --chown=0:0 https://unit.nginx.org/keys/nginx-keyring.gpg /usr/share/keyrings/nginx-keyring.gpg
|
|
||||||
RUN export DEBIAN_FRONTEND=noninteractive \
|
RUN export DEBIAN_FRONTEND=noninteractive \
|
||||||
&& apt-get update -qq \
|
&& apt-get update -qq \
|
||||||
&& apt-get upgrade \
|
&& apt-get upgrade \
|
||||||
|
|
@ -64,8 +62,6 @@ RUN export DEBIAN_FRONTEND=noninteractive \
|
||||||
openssl \
|
openssl \
|
||||||
python3 \
|
python3 \
|
||||||
tini \
|
tini \
|
||||||
unit-python3.12=1.34.2-1~noble \
|
|
||||||
unit=1.34.2-1~noble \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy the modified 'requirements*.txt' files, to have the files actually used during installation
|
# Copy the modified 'requirements*.txt' files, to have the files actually used during installation
|
||||||
|
|
@ -81,20 +77,20 @@ COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py
|
||||||
COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh
|
COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh
|
||||||
COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh
|
COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh
|
||||||
COPY configuration/ /etc/netbox/config/
|
COPY configuration/ /etc/netbox/config/
|
||||||
COPY docker/nginx-unit.json /etc/unit/
|
COPY docker/granian.py /opt/netbox/netbox/netbox/granian.py
|
||||||
COPY VERSION /opt/netbox/VERSION
|
COPY VERSION /opt/netbox/VERSION
|
||||||
|
|
||||||
WORKDIR /opt/netbox/netbox
|
WORKDIR /opt/netbox/netbox
|
||||||
|
|
||||||
# Must set permissions for '/opt/netbox/netbox/media' directory
|
# Must set permissions for '/opt/netbox/netbox/media' directory
|
||||||
# to g+w so that pictures can be uploaded to netbox.
|
# to g+w so that pictures can be uploaded to netbox.
|
||||||
RUN mkdir -p static media /opt/unit/state/ /opt/unit/tmp/ \
|
RUN useradd --home-dir /opt/netbox/ --no-create-home --no-user-group --system --shell /bin/false --uid 999 --gid 0 netbox \
|
||||||
&& chown -R unit:root /opt/unit/ media reports scripts \
|
&& mkdir -p static media local \
|
||||||
&& chmod -R g+w /opt/unit/ media reports scripts \
|
&& chown -R netbox:root media reports scripts \
|
||||||
|
&& chmod -R g+w media reports scripts \
|
||||||
&& cd /opt/netbox/ && SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python -m mkdocs build \
|
&& cd /opt/netbox/ && SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python -m mkdocs build \
|
||||||
--config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \
|
--config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \
|
||||||
&& DEBUG="true" SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input \
|
&& DEBUG="true" SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input \
|
||||||
&& mkdir /opt/netbox/netbox/local \
|
|
||||||
&& echo "build: Docker-$(cat /opt/netbox/VERSION)" > /opt/netbox/netbox/local/release.yaml
|
&& echo "build: Docker-$(cat /opt/netbox/VERSION)" > /opt/netbox/netbox/local/release.yaml
|
||||||
|
|
||||||
ENV LANG=C.utf8 PATH=/opt/netbox/venv/bin:$PATH VIRTUAL_ENV=/opt/netbox/venv UV_NO_CACHE=1
|
ENV LANG=C.utf8 PATH=/opt/netbox/venv/bin:$PATH VIRTUAL_ENV=/opt/netbox/venv UV_NO_CACHE=1
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@ services:
|
||||||
netbox:
|
netbox:
|
||||||
ports:
|
ports:
|
||||||
- "8000:8080"
|
- "8000:8080"
|
||||||
# If you want the Nginx unit status page visible from the
|
|
||||||
# outside of the container add the following port mapping:
|
|
||||||
# - "8001:8081"
|
|
||||||
# healthcheck:
|
# healthcheck:
|
||||||
# Time for which the health check can fail after the container is started.
|
# Time for which the health check can fail after the container is started.
|
||||||
# This depends mostly on the performance of your database. On the first start,
|
# This depends mostly on the performance of your database. On the first start,
|
||||||
|
|
@ -19,4 +16,3 @@ services:
|
||||||
# SUPERUSER_EMAIL: ""
|
# SUPERUSER_EMAIL: ""
|
||||||
# SUPERUSER_NAME: ""
|
# SUPERUSER_NAME: ""
|
||||||
# SUPERUSER_PASSWORD: ""
|
# SUPERUSER_PASSWORD: ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ services:
|
||||||
redis-cache:
|
redis-cache:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
env_file: env/netbox.env
|
env_file: env/netbox.env
|
||||||
user: "unit:root"
|
user: "netbox:root"
|
||||||
volumes:
|
volumes:
|
||||||
- ./test-configuration/test_config.py:/etc/netbox/config/test_config.py:z,ro
|
- ./test-configuration/test_config.py:/etc/netbox/config/test_config.py:z,ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ services:
|
||||||
- redis
|
- redis
|
||||||
- redis-cache
|
- redis-cache
|
||||||
env_file: env/netbox.env
|
env_file: env/netbox.env
|
||||||
user: "unit:root"
|
user: "netbox:root"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: curl -f http://localhost:8080/login/ || exit 1
|
test: curl -f http://localhost:8080/login/ || exit 1
|
||||||
start_period: 90s
|
start_period: 90s
|
||||||
|
|
|
||||||
13
docker/granian.py
Normal file
13
docker/granian.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
from granian.utils.proxies import wrap_wsgi_with_proxy_headers
|
||||||
|
from netbox.wsgi import application
|
||||||
|
|
||||||
|
application = wrap_wsgi_with_proxy_headers(
|
||||||
|
application,
|
||||||
|
trusted_hosts=[
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
"fc00::/7",
|
||||||
|
"fe80::/10",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
@ -1,57 +1,18 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
UNIT_CONFIG="${UNIT_CONFIG-/etc/unit/nginx-unit.json}"
|
exec granian \
|
||||||
# Also used in "nginx-unit.json"
|
--host "::" \
|
||||||
UNIT_SOCKET="/opt/unit/unit.sock"
|
--port "8080" \
|
||||||
|
--interface "wsgi" \
|
||||||
load_configuration() {
|
--no-ws \
|
||||||
MAX_WAIT=10
|
--workers "4" \
|
||||||
WAIT_COUNT=0
|
--backpressure "4" \
|
||||||
while [ ! -S $UNIT_SOCKET ]; do
|
--loop "uvloop" \
|
||||||
if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
|
--log \
|
||||||
echo "⚠️ No control socket found; configuration will not be loaded."
|
--log-level "info" \
|
||||||
return 1
|
--access-log \
|
||||||
fi
|
--working-dir "/opt/netbox/netbox/" \
|
||||||
|
--static-path-route "/static" \
|
||||||
WAIT_COUNT=$((WAIT_COUNT + 1))
|
--static-path-mount "/opt/netbox/netbox/static/" \
|
||||||
echo "⏳ Waiting for control socket to be created... (${WAIT_COUNT}/${MAX_WAIT})"
|
--pid-file "/tmp/granian.pid" \
|
||||||
|
"netbox.granian:application"
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
# even when the control socket exists, it does not mean unit has finished initialisation
|
|
||||||
# this curl call will get a reply once unit is fully launched
|
|
||||||
curl --silent --output /dev/null --request GET --unix-socket $UNIT_SOCKET http://localhost/
|
|
||||||
|
|
||||||
echo "⚙️ Applying configuration from $UNIT_CONFIG"
|
|
||||||
|
|
||||||
RESP_CODE=$(
|
|
||||||
curl \
|
|
||||||
--silent \
|
|
||||||
--output /dev/null \
|
|
||||||
--write-out '%{http_code}' \
|
|
||||||
--request PUT \
|
|
||||||
--data-binary "@${UNIT_CONFIG}" \
|
|
||||||
--unix-socket $UNIT_SOCKET \
|
|
||||||
http://localhost/config
|
|
||||||
)
|
|
||||||
if [ "$RESP_CODE" != "200" ]; then
|
|
||||||
echo "⚠️ Could not load Unit configuration"
|
|
||||||
kill "$(cat /opt/unit/unit.pid)"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ Unit configuration loaded successfully"
|
|
||||||
}
|
|
||||||
|
|
||||||
load_configuration &
|
|
||||||
|
|
||||||
exec unitd \
|
|
||||||
--no-daemon \
|
|
||||||
--control unix:$UNIT_SOCKET \
|
|
||||||
--pid /opt/unit/unit.pid \
|
|
||||||
--log /dev/stdout \
|
|
||||||
--statedir /opt/unit/state/ \
|
|
||||||
--tmpdir /opt/unit/tmp/ \
|
|
||||||
--user unit \
|
|
||||||
--group root
|
|
||||||
|
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
{
|
|
||||||
"listeners": {
|
|
||||||
"0.0.0.0:8080": {
|
|
||||||
"pass": "routes/main",
|
|
||||||
"forwarded": {
|
|
||||||
"client_ip": "X-Forwarded-For",
|
|
||||||
"protocol": "X-Forwarded-Proto",
|
|
||||||
"source": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"0.0.0.0:8081": {
|
|
||||||
"pass": "routes/status",
|
|
||||||
"forwarded": {
|
|
||||||
"client_ip": "X-Forwarded-For",
|
|
||||||
"protocol": "X-Forwarded-Proto",
|
|
||||||
"source": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"[::]:8080": {
|
|
||||||
"pass": "routes/main",
|
|
||||||
"forwarded": {
|
|
||||||
"client_ip": "X-Forwarded-For",
|
|
||||||
"protocol": "X-Forwarded-Proto",
|
|
||||||
"source": ["fc00::/7", "fe80::/10"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"[::]:8081": {
|
|
||||||
"pass": "routes/status",
|
|
||||||
"forwarded": {
|
|
||||||
"client_ip": "X-Forwarded-For",
|
|
||||||
"protocol": "X-Forwarded-Proto",
|
|
||||||
"source": ["fc00::/7", "fe80::/10"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"routes": {
|
|
||||||
"main": [
|
|
||||||
{
|
|
||||||
"match": {
|
|
||||||
"uri": "/static/*"
|
|
||||||
},
|
|
||||||
"action": {
|
|
||||||
"share": "/opt/netbox/netbox${uri}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": {
|
|
||||||
"pass": "applications/netbox"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"status": [
|
|
||||||
{
|
|
||||||
"match": {
|
|
||||||
"uri": "/status/*"
|
|
||||||
},
|
|
||||||
"action": {
|
|
||||||
"proxy": "http://unix:/opt/unit/unit.sock"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"applications": {
|
|
||||||
"netbox": {
|
|
||||||
"type": "python 3",
|
|
||||||
"path": "/opt/netbox/netbox/",
|
|
||||||
"module": "netbox.wsgi",
|
|
||||||
"home": "/opt/netbox/venv",
|
|
||||||
"processes": {
|
|
||||||
"max": 4,
|
|
||||||
"spare": 1,
|
|
||||||
"idle_timeout": 120
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"access_log": "/dev/stdout",
|
|
||||||
"settings": {
|
|
||||||
"http": {
|
|
||||||
"max_body_size": 104857600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] http://packages.nginx.org/unit/ubuntu/ noble unit
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
django-auth-ldap==5.2.0
|
django-auth-ldap==5.2.0
|
||||||
dulwich==0.24.10
|
dulwich==0.24.10
|
||||||
|
granian[uvloop]==2.5.7
|
||||||
python3-saml==1.16.0
|
python3-saml==1.16.0
|
||||||
--no-binary lxml
|
--no-binary lxml
|
||||||
--no-binary xmlsec
|
--no-binary xmlsec
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue