Initial commit
Drone CI steps, Dockerfile for ENV arguments and README.md
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
.git
|
||||
.gitignore
|
||||
.drone.yml
|
||||
docker-compose.yml
|
||||
README.md
|
||||
build-and-tag.sh
|
||||
build-and-tag.ps1
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
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:
|
||||
- echo "Building redirect image on host Docker daemon..."
|
||||
- docker build -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
|
||||
echo "Tagged redirect:$SHORT_SHA"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DRONE_TAG" ]; then
|
||||
docker tag redirect:latest redirect:$DRONE_TAG
|
||||
echo "Tagged redirect:$DRONE_TAG"
|
||||
fi
|
||||
- echo "Build complete. Images registered on host Docker engine:"
|
||||
- docker images | grep redirect || true
|
||||
|
||||
volumes:
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
FROM nginxinc/nginx-unprivileged:alpine-slim
|
||||
|
||||
# Set default environment variables
|
||||
ENV REDIRECT_TARGET="https://example.com" \
|
||||
REDIRECT_CODE="301" \
|
||||
LISTEN_PORT="8080" \
|
||||
NGINX_ENVSUBST_FILTER="REDIRECT_TARGET REDIRECT_CODE LISTEN_PORT"
|
||||
|
||||
# Copy template for automatic envsubst rendering on startup
|
||||
COPY templates/default.conf.template /etc/nginx/templates/default.conf.template
|
||||
|
||||
# Default unprivileged port
|
||||
EXPOSE 8080
|
||||
@@ -0,0 +1,150 @@
|
||||
# Unprivileged Nginx Redirect Docker Image
|
||||
|
||||
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 -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
|
||||
volumes:
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
```
|
||||
|
||||
> **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:<short_sha>`).
|
||||
|
||||
---
|
||||
|
||||
## 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"
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
param (
|
||||
[string]$ImageName = "redirect",
|
||||
[string]$Tag = "latest"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Host "Building Docker image: ${ImageName}:${Tag}"
|
||||
docker build -t "${ImageName}:${Tag}" .
|
||||
|
||||
Write-Host "Build complete. Image ${ImageName}:${Tag} is registered on host Docker engine."
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
IMAGE_NAME="${1:-redirect}"
|
||||
TAG="${2:-latest}"
|
||||
|
||||
echo "Building Docker image: ${IMAGE_NAME}:${TAG}"
|
||||
docker build -t "${IMAGE_NAME}:${TAG}" .
|
||||
|
||||
echo "Build complete. Image ${IMAGE_NAME}:${TAG} is registered on host Docker engine."
|
||||
@@ -0,0 +1,33 @@
|
||||
services:
|
||||
# Example 1: Simple domain redirect (301 Permanent Redirect)
|
||||
redirect-example:
|
||||
image: redirect:latest
|
||||
container_name: redirect-example
|
||||
ports:
|
||||
- "8081:8080"
|
||||
environment:
|
||||
- REDIRECT_TARGET=https://example.com
|
||||
- REDIRECT_CODE=301
|
||||
restart: unless-stopped
|
||||
|
||||
# Example 2: Redirect preserving full request path and query string (302 Temporary Redirect)
|
||||
redirect-with-path:
|
||||
image: redirect:latest
|
||||
container_name: redirect-with-path
|
||||
ports:
|
||||
- "8082:8080"
|
||||
environment:
|
||||
- REDIRECT_TARGET=https://newsite.com$request_uri
|
||||
- REDIRECT_CODE=302
|
||||
restart: unless-stopped
|
||||
|
||||
# Example 3: Redirect to a specific subpath (307 Temporary Redirect)
|
||||
redirect-subpath:
|
||||
image: redirect:latest
|
||||
container_name: redirect-subpath
|
||||
ports:
|
||||
- "8083:8080"
|
||||
environment:
|
||||
- REDIRECT_TARGET=https://example.com/landing-page
|
||||
- REDIRECT_CODE=307
|
||||
restart: unless-stopped
|
||||
@@ -0,0 +1,16 @@
|
||||
server {
|
||||
listen ${LISTEN_PORT};
|
||||
server_name _;
|
||||
|
||||
# Health check endpoint for container orchestrator probes
|
||||
location = /healthz {
|
||||
access_log off;
|
||||
default_type text/plain;
|
||||
return 200 "OK\n";
|
||||
}
|
||||
|
||||
# Redirect all other incoming traffic
|
||||
location / {
|
||||
return ${REDIRECT_CODE} ${REDIRECT_TARGET};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user