mirror of
https://github.com/netbox-community/netbox-docker.git
synced 2025-12-10 05:42:36 +00:00
Switch server to Granian (#1561)
Some checks failed
push / Checks syntax of our code (push) Has been cancelled
push / Builds new NetBox Docker Images (./build-latest.sh, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build-latest.sh, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh feature, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh feature, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh main, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh main, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (PRERELEASE=true ./build-latest.sh, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (PRERELEASE=true ./build-latest.sh, ubuntu-24.04-arm) (push) Has been cancelled
Some checks failed
push / Checks syntax of our code (push) Has been cancelled
push / Builds new NetBox Docker Images (./build-latest.sh, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build-latest.sh, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh feature, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh feature, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh main, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (./build.sh main, ubuntu-24.04-arm) (push) Has been cancelled
push / Builds new NetBox Docker Images (PRERELEASE=true ./build-latest.sh, ubuntu-24.04) (push) Has been cancelled
push / Builds new NetBox Docker Images (PRERELEASE=true ./build-latest.sh, ubuntu-24.04-arm) (push) Has been cancelled
* 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. * Addressed review comments * Update docker/launch-netbox.sh Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com> * Update docker/launch-netbox.sh Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com> --------- Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com>
This commit is contained in:
parent
c89fd3331b
commit
07fcb205b4
1
.github/workflows/push.yml
vendored
1
.github/workflows/push.yml
vendored
|
|
@ -42,6 +42,7 @@ jobs:
|
|||
VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
|
||||
VALIDATE_GITLEAKS: false
|
||||
VALIDATE_JSCPD: false
|
||||
VALIDATE_PYTHON_PYLINT: false
|
||||
VALIDATE_TRIVY: false
|
||||
FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*)
|
||||
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 /
|
||||
ENV VIRTUAL_ENV=/opt/netbox/venv
|
||||
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 && \
|
||||
# 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.
|
||||
|
|
@ -46,8 +46,6 @@ RUN \
|
|||
ARG FROM
|
||||
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 \
|
||||
&& apt-get update -qq \
|
||||
&& apt-get upgrade \
|
||||
|
|
@ -64,8 +62,6 @@ RUN export DEBIAN_FRONTEND=noninteractive \
|
|||
openssl \
|
||||
python3 \
|
||||
tini \
|
||||
unit-python3.12=1.34.2-1~noble \
|
||||
unit=1.34.2-1~noble \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 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/launch-netbox.sh /opt/netbox/launch-netbox.sh
|
||||
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
|
||||
|
||||
WORKDIR /opt/netbox/netbox
|
||||
|
||||
# Must set permissions for '/opt/netbox/netbox/media' directory
|
||||
# to g+w so that pictures can be uploaded to netbox.
|
||||
RUN mkdir -p static media /opt/unit/state/ /opt/unit/tmp/ \
|
||||
&& chown -R unit:root /opt/unit/ media reports scripts \
|
||||
&& chmod -R g+w /opt/unit/ media reports scripts \
|
||||
RUN useradd --home-dir /opt/netbox/ --no-create-home --no-user-group --system --shell /bin/false --uid 999 --gid 0 netbox \
|
||||
&& mkdir -p static media local \
|
||||
&& 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 \
|
||||
--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 \
|
||||
&& mkdir /opt/netbox/netbox/local \
|
||||
&& 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
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ services:
|
|||
netbox:
|
||||
ports:
|
||||
- "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:
|
||||
# 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,
|
||||
|
|
@ -19,4 +16,3 @@ services:
|
|||
# SUPERUSER_EMAIL: ""
|
||||
# SUPERUSER_NAME: ""
|
||||
# SUPERUSER_PASSWORD: ""
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ services:
|
|||
redis-cache:
|
||||
condition: service_healthy
|
||||
env_file: env/netbox.env
|
||||
user: "unit:root"
|
||||
user: "netbox:root"
|
||||
volumes:
|
||||
- ./test-configuration/test_config.py:/etc/netbox/config/test_config.py:z,ro
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ services:
|
|||
- redis
|
||||
- redis-cache
|
||||
env_file: env/netbox.env
|
||||
user: "unit:root"
|
||||
user: "netbox:root"
|
||||
healthcheck:
|
||||
test: curl -f http://localhost:8080/login/ || exit 1
|
||||
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,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
UNIT_CONFIG="${UNIT_CONFIG-/etc/unit/nginx-unit.json}"
|
||||
# Also used in "nginx-unit.json"
|
||||
UNIT_SOCKET="/opt/unit/unit.sock"
|
||||
|
||||
load_configuration() {
|
||||
MAX_WAIT=10
|
||||
WAIT_COUNT=0
|
||||
while [ ! -S $UNIT_SOCKET ]; do
|
||||
if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
|
||||
echo "⚠️ No control socket found; configuration will not be loaded."
|
||||
return 1
|
||||
fi
|
||||
|
||||
WAIT_COUNT=$((WAIT_COUNT + 1))
|
||||
echo "⏳ Waiting for control socket to be created... (${WAIT_COUNT}/${MAX_WAIT})"
|
||||
|
||||
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
|
||||
exec granian \
|
||||
--host "::" \
|
||||
--port "8080" \
|
||||
--interface "wsgi" \
|
||||
--no-ws \
|
||||
--workers "${GRANIAN_WORKERS:-4}" \
|
||||
--respawn-failed-workers \
|
||||
--backpressure "${GRANIAN_BACKPRESSURE:-${GRANIAN_WORKERS:-4}}" \
|
||||
--loop "uvloop" \
|
||||
--log \
|
||||
--log-level "info" \
|
||||
--access-log \
|
||||
--working-dir "/opt/netbox/netbox/" \
|
||||
--static-path-route "/static" \
|
||||
--static-path-mount "/opt/netbox/netbox/static/" \
|
||||
--pid-file "/tmp/granian.pid" \
|
||||
"${GRANIAN_EXTRA_ARGS[@]}" \
|
||||
"netbox.granian:application"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
2
env/netbox.env
vendored
2
env/netbox.env
vendored
|
|
@ -15,6 +15,8 @@ EMAIL_USERNAME=netbox
|
|||
# EMAIL_USE_SSL and EMAIL_USE_TLS are mutually exclusive, i.e. they can't both be `true`!
|
||||
EMAIL_USE_SSL=false
|
||||
EMAIL_USE_TLS=false
|
||||
GRANIAN_BACKPRESSURE=4
|
||||
GRANIAN_WORKERS=4
|
||||
GRAPHQL_ENABLED=true
|
||||
MEDIA_ROOT=/opt/netbox/netbox/media
|
||||
METRICS_ENABLED=false
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
django-auth-ldap==5.2.0
|
||||
dulwich==0.24.10
|
||||
granian[uvloop]==2.5.7
|
||||
python3-saml==1.16.0
|
||||
--no-binary lxml
|
||||
--no-binary xmlsec
|
||||
|
|
|
|||
Loading…
Reference in a new issue