Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
target/
.git/
.idea/
.vscode/
ex/
docs/
tests/
.DS_Store
.env
19 changes: 18 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,21 @@ jobs:
with:
name: tiny-proxy-linux
path: target/release/tiny-proxy
if-no-files-found: error
if-no-files-found: error

docker:
name: Docker build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image (linux/amd64)
uses: docker/build-push-action@v5
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
55 changes: 55 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Docker

on:
push:
tags:
- "v*.*.*"
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
name: Build & Push Docker Image
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}

- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ ex/
docs/
.env
.DS_Store
certs/
43 changes: 43 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Multi-stage build for tiny-proxy
#
# Build stage — compiles a static binary with musl on Alpine
# Runtime — minimal Alpine image with CA certificates (~7 MB)

# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------
FROM rust:1.85-alpine AS builder

RUN apk add --no-cache musl-dev cmake make gcc nasm perl

WORKDIR /build

# Cargo.toml references benches/ and examples/ — provide stubs so --locked resolves
COPY Cargo.toml Cargo.lock ./
COPY benches/ benches/
COPY examples/ examples/
RUN mkdir src && echo "" > src/lib.rs && echo "fn main() {}" > src/main.rs

RUN cargo build --release --all-features --locked 2>/dev/null || true
RUN rm -rf src

COPY src/ src/
RUN touch src/main.rs src/lib.rs && cargo build --release --all-features --locked

RUN strip /build/target/release/tiny-proxy

# ---------------------------------------------------------------------------
# Runtime
# ---------------------------------------------------------------------------
FROM alpine:3.21

RUN apk add --no-cache ca-certificates

COPY --from=builder /build/target/release/tiny-proxy /usr/local/bin/tiny-proxy

# Config and certs mount points
VOLUME /etc/tiny-proxy
VOLUME /etc/ssl/tiny-proxy

ENTRYPOINT ["tiny-proxy"]
CMD ["-c", "/etc/tiny-proxy/config.caddy"]
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,52 @@ Add to your `Cargo.toml`:
tiny-proxy = "0.3"
```

## Docker

### Quick Start

```bash
# Pull from GitHub Container Registry
docker pull ghcr.io/denislituev/tiny-proxy:latest

# Run with a local config
docker run -d \
-p 8080:8080 \
-v $(pwd)/config.caddy:/etc/tiny-proxy/config.caddy:ro \
ghcr.io/denislituev/tiny-proxy:latest

# With TLS
docker run -d \
-p 8443:8443 \
-v $(pwd)/config.caddy:/etc/tiny-proxy/config.caddy:ro \
-v $(pwd)/certs:/etc/ssl/tiny-proxy:ro \
ghcr.io/denislituev/tiny-proxy:latest
```

### Docker Compose

```yaml
services:
proxy:
image: ghcr.io/denislituev/tiny-proxy:latest
ports:
- "8080:8080"
volumes:
- ./config.caddy:/etc/tiny-proxy/config.caddy:ro
```

See [`docker-compose.yml`](docker-compose.yml) for a full example with TLS + echo backends.

### Build from Source

```bash
git clone https://github.com/denislituev/tiny-proxy.git
cd tiny-proxy
docker build -t tiny-proxy .
```

The image is based on Alpine Linux with CA certificates (~7 MB), so HTTPS backends work out of the box.

## Usage

### CLI Mode
Expand Down
24 changes: 24 additions & 0 deletions config.caddy
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# tiny-proxy configuration for docker-compose example
#
# HTTPS site on :8443 with TLS termination
# HTTP redirect on :8080 (automatic: 8443 - 443 + 80 = 8080)
#
# Generate self-signed certs:
# mkdir -p certs
# openssl req -x509 -newkey rsa:2048 \
# -keyout certs/key.pem -out certs/cert.pem \
# -days 365 -nodes -subj "/CN=localhost"

localhost:8443 {
tls /etc/ssl/tiny-proxy/cert.pem /etc/ssl/tiny-proxy/key.pem

handle_path /users/* {
reverse_proxy backend-users:8080
}
handle_path /orders/* {
reverse_proxy backend-orders:8080
}
handle_path /health {
respond 200 "OK"
}
}
44 changes: 44 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example stack: tiny-proxy (TLS + HTTP→HTTPS redirect) with internal echo backends.
#
# Backends are reachable only inside the compose network (no host ports).
# Config: config.caddy — HTTPS :8443, redirect :8080 (8443 - 443 + 80).
#
# Usage:
# mkdir -p certs
# openssl req -x509 -newkey rsa:2048 \
# -keyout certs/key.pem -out certs/cert.pem \
# -days 365 -nodes -subj "/CN=localhost"
# docker compose up --build
#
# Test:
# curl -k https://localhost:8443/health
# curl -k https://localhost:8443/users/123
# curl -k https://localhost:8443/orders/456
# curl -sI http://localhost:8080/health # 301 → https://localhost:8443/health

services:
proxy:
build: .
ports:
- "8443:8443" # HTTPS (TLS termination)
- "8080:8080" # HTTP → HTTPS redirect
volumes:
- ./config.caddy:/etc/tiny-proxy/config.caddy:ro
- ./certs:/etc/ssl/tiny-proxy:ro
depends_on:
backend-users:
condition: service_started
backend-orders:
condition: service_started

backend-users:
image: hashicorp/http-echo
command: ["-text=Hello from User Service", "-listen=:8080"]
expose:
- "8080"

backend-orders:
image: hashicorp/http-echo
command: ["-text=Hello from Order Service", "-listen=:8080"]
expose:
- "8080"
Loading