From 36390a4d713b210870b6f5dbfbda8e467efde9ca Mon Sep 17 00:00:00 2001 From: DaanSelen <80752476+DaanSelen@users.noreply.github.com> Date: Tue, 9 Dec 2025 13:16:18 +0100 Subject: [PATCH] refac: rework tailing of logs in the Docker entrypoint (#1021) * chore: add debug workflow * chore: testing fix * chore: try next option * refac: tailing logs --------- Co-authored-by: DaanSelen --- .github/workflows/docker-debug.yml | 106 +++++++++++++++++++++++++++++ docker/Dockerfile | 2 +- docker/entrypoint.sh | 56 ++++++++++----- src/gunicorn.conf.py | 2 +- 4 files changed, 148 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/docker-debug.yml diff --git a/.github/workflows/docker-debug.yml b/.github/workflows/docker-debug.yml new file mode 100644 index 00000000..14707657 --- /dev/null +++ b/.github/workflows/docker-debug.yml @@ -0,0 +1,106 @@ +name: Docker Build and Push + +on: + workflow_dispatch: + +env: + DOCKERHUB_PREFIX: docker.io + GITHUB_CONTAINER_PREFIX: ghcr.io + DOCKER_IMAGE: WGDashboard + +jobs: + docker_build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + fail-fast: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKERHUB_PREFIX }} + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_CONTAINER_PREFIX }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract Docker metadata from environment + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.DOCKERHUB_PREFIX }}/donaldzou/${{ env.DOCKER_IMAGE }} + ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha,format=short,prefix= + + - name: Build and export Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 + + docker_scan: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: docker_build + steps: + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKERHUB_PREFIX }} + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_CONTAINER_PREFIX }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker Scout CVEs + uses: docker/scout-action@v1 + with: + command: cves + image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:main + only-severities: critical,high + only-fixed: true + write-comment: true + github-token: ${{ secrets.GITHUB_TOKEN }} + exit-code: true + + - name: Docker Scout Compare + uses: docker/scout-action@v1 + with: + command: compare + # Set to Github for maximum compat + image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:main + to: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:latest + only-severities: critical,high + ignore-unchanged: true + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/docker/Dockerfile b/docker/Dockerfile index 80e32b8c..52a6eb05 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -76,7 +76,7 @@ RUN apk add --no-cache \ # Copy the requirements file into the build layer. COPY ./src/requirements.txt /opt/wgdashboard/src RUN if [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \ - sed -i 's|psycopg\[binary\]|psycopg[c]|' /opt/wgdashboard/src/requirements.txt; \ + sed -i 's|psycopg\[binary\]|psycopg[c]|' /opt/wgdashboard/src/requirements.txt; \ fi; \ cat /opt/wgdashboard/src/requirements.txt diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 232b3480..078daccb 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -22,7 +22,7 @@ set_ini() { if grep -q "^[[:space:]]*${key}[[:space:]]*=" "$config_file"; then current_value=$(grep "^[[:space:]]*${key}[[:space:]]*=" "$config_file" | cut -d= -f2- | xargs) - # Don't display actual value if it's a password field + # Dont display actual value if it's a password field if [[ "$key" == *"password"* ]]; then if [ "$current_value" = "$value" ]; then echo "- $key is already set correctly (value hidden)" @@ -180,7 +180,6 @@ set_envvars() { # Start service and monitor logs start_and_monitor() { - local logdir="${WGDASH}/src/log" printf "\n---------------------- STARTING CORE -----------------------\n" # Due to some instances complaining about this, making sure its there every time. @@ -190,30 +189,55 @@ start_and_monitor() { # Actually starting WGDashboard echo "Starting WGDashboard directly with Gunicorn..." - /opt/wgdashboard/src/venv/bin/python3 /opt/wgdashboard/src/venv/bin/gunicorn --config /opt/wgdashboard/src/gunicorn.conf.py + + [[ ! -d ${WGDASH}/src/log ]] && mkdir ${WGDASH}/src/log + ${WGDASH}/src/venv/bin/gunicorn --config ${WGDASH}/src/gunicorn.conf.py if [ $? -ne 0 ]; then echo "Loading WGDashboard failed... Look above for details." fi # Wait a second before continuing, to give the python program some time to get ready. echo -e "\nEnsuring container continuation." - while [[ ! -d $logdir ]]; do - echo "Logging directory not yet present..." - sleep 1s + + max_rounds="10" + round="0" + + # Hang in there for 10s for Gunicorn to get ready + while true; do + round=$((round + 1)) + latest_error=$(ls -t ${WGDASH}/src/log/error_*.log 2> /dev/null | head -n 1) + + if [[ $round -eq $max_rounds ]]; then + echo "Reached breaking point!" + break + + fi + + if [[ -z $latest_error ]]; then + echo -e "Logs not yet present! Retrying in 1 second!" + sleep 1s + + else + break + + fi + done - # Find and monitor log file - latestErrLog=$(find "$logdir" -name "error_*.log" -type f -print | sort -r | head -n 1) - - # Only tail the logs if they are found - if [ -n "$latestErrLog" ]; then - tail -f "$latestErrLog" & - # Wait for the tail process to end. - wait $! - else - echo "No log files found to tail. Something went wrong, exiting..." + if [[ -z $latest_error ]]; then + echo -e "No error logs founds... Please investigate.\nExiting in 3 minutes..." + sleep 180s exit 1 + + else + tail -f "$latest_error" & + wait $! + fi + + echo "The blocking command has been broken! Script will exit in 3 minutes... Investigate!" + sleep 180s + exit 1 } # Main execution flow diff --git a/src/gunicorn.conf.py b/src/gunicorn.conf.py index 1385a2ee..cba84b21 100644 --- a/src/gunicorn.conf.py +++ b/src/gunicorn.conf.py @@ -23,4 +23,4 @@ pythonpath = "., ./modules" print(f"[Gunicorn] WGDashboard w/ Gunicorn will be running on {bind}", flush=True) print(f"[Gunicorn] Access log file is at {accesslog}", flush=True) -print(f"[Gunicorn] Error log file is at {errorlog}", flush=True) \ No newline at end of file +print(f"[Gunicorn] Error log file is at {errorlog}", flush=True)