# Unprivileged Nginx Redirect Docker Image [![Build Status](https://ci.mrose.cloud/api/badges/vincent/redirect/status.svg?ref=refs/heads/main)](https://ci.mrose.cloud/vincent/redirect) A lightweight, secure, and reusable Docker image based on `nginxinc/nginx-unprivileged:alpine-slim` designed to redirect HTTP requests to any configurable target domain/path with customizable HTTP status codes. It is designed to be built via **Drone CI** directly onto the host server's Docker daemon, allowing multiple containers to run on the host system using the single tagged image. --- ## Features - **Ultra-Lightweight & Secure**: Based on `nginxinc/nginx-unprivileged:alpine-slim` (~12 MB), running as non-root user (UID 101). - **Environment Variable Configuration**: Leverages native Nginx startup template rendering (`envsubst`). - **Path & Query String Preservation**: Support for preserving request paths (e.g. `$request_uri`). - **Built-in Health Checks**:`/healthz` endpoint returns `200 OK` for orchestrator probe support without triggering a redirect. - **Drone CI Host Integration**: Pipeline builds directly onto the host machine's Docker engine via host Docker socket binding (`/var/run/docker.sock`). --- ## Environment Variables | Variable | Default Value | Description | | :--- | :--- | :--- | | `REDIRECT_TARGET` | `https://example.com` | Target URL or domain for redirection. Add `$request_uri` to preserve path & query parameters. | | `REDIRECT_CODE` | `301` | HTTP status code for redirection (e.g. `301`, `302`, `307`, `308`). | | `LISTEN_PORT` | `8080` | Internal HTTP listening port (unprivileged standard). | --- ## Drone CI Integration The included `.drone.yml` pipeline mounts the host Docker socket (`/var/run/docker.sock`) into a `docker:cli` container step. This builds and tags the image directly on the host host's Docker daemon. ```yaml kind: pipeline type: docker name: build-host-redirect-image steps: - name: build-and-tag-host-image image: docker:cli volumes: - name: dockersock path: /var/run/docker.sock commands: - docker build --pull -t redirect:latest . - | if [ -n "$DRONE_COMMIT_SHA" ]; then SHORT_SHA=$(echo $DRONE_COMMIT_SHA | cut -c1-7) docker tag redirect:latest redirect:$SHORT_SHA fi - | if [ -n "$DRONE_TAG" ]; then docker tag redirect:latest redirect:$DRONE_TAG fi - | apk add --no-cache git 2>/dev/null || true git fetch --tags 2>/dev/null || true LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true) if [ -n "$LATEST_TAG" ]; then docker tag redirect:latest redirect:$LATEST_TAG fi volumes: - name: dockersock host: path: /var/run/docker.sock trigger: event: - push - tag - cron ``` > **Note**: Ensure your Drone runner environment allows mounting the host socket volume. ### Tagging a Release with Git When you create and push a Git tag to your repository: ```bash # Create a tag locally git tag v1.0.0 # Push the tag to your git remote git push origin v1.0.0 ``` 1. Git sends a `tag` webhook event to Drone CI. 2. Drone automatically populates `$DRONE_TAG` with the tag value (e.g. `v1.0.0`) and triggers the pipeline. 3. The pipeline builds and tags the host image as `redirect:v1.0.0` (as well as `redirect:latest` and `redirect:`). ### Weekly Scheduled Rebuilds (`weekly-build`) To keep your Docker images updated with upstream OS/Nginx security patches: 1. In the **Drone CI UI** (or via Drone CLI), navigate to **Repository Settings** -> **Cron Jobs**. 2. Add a new Cron job named `weekly-build` set to trigger weekly (e.g., `@weekly` or `0 0 * * 0`). 3. When the `cron` event triggers: - The pipeline executes `docker build --pull -t redirect:latest .` to fetch updated base layers from Alpine/Nginx. - It fetches the latest Git release tag (`git describe --tags --abbrev=0`) and automatically updates `redirect:` (e.g., `redirect:v1.0.0`) on the host daemon. --- ## Quick Start & Usage ### 1. Manual Build (Local Testing) ```bash # Bash ./build-and-tag.sh redirect latest # PowerShell .\build-and-tag.ps1 -ImageName redirect -Tag latest ``` ### 2. Run Single Containers **Basic Domain Redirect (301 Permanent Redirect)** ```bash docker run -d \ --name redirect-domain \ -p 8080:8080 \ -e REDIRECT_TARGET="https://destination.com" \ -e REDIRECT_CODE="301" \ redirect:latest ``` **Path & Query Parameter Preserving Redirect (302 Found)** ```bash docker run -d \ --name redirect-path \ -p 8081:8080 \ -e REDIRECT_TARGET="https://destination.com\$request_uri" \ -e REDIRECT_CODE="302" \ redirect:latest ``` ### 3. Multi-Container Setup with Docker Compose To deploy multiple redirect services side-by-side using the host-tagged image: ```yaml services: site-a-redirect: image: redirect:latest container_name: site-a-redirect ports: - "8081:8080" environment: - REDIRECT_TARGET=https://site-a.com - REDIRECT_CODE=301 site-b-redirect: image: redirect:latest container_name: site-b-redirect ports: - "8082:8080" environment: - REDIRECT_TARGET=https://site-b.com$request_uri - REDIRECT_CODE=302 ``` Run compose stack: ```bash docker compose up -d ``` --- ## Health Check Endpoint All requests to `/healthz` bypass redirection and return an HTTP `200 OK` response with text body `OK`. ```bash curl http://localhost:8080/healthz # Response: HTTP 200 OK -> "OK" ```