Skip to content

Commit

Permalink
feat(traefik-docker-proxy): add initial image
Browse files Browse the repository at this point in the history
  • Loading branch information
f-bn committed Feb 5, 2025
1 parent 07afe9f commit c30a4f5
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/build-traefik-docker-proxy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: Build Traefik Docker Proxy image
on:
push:
branches:
- main
paths:
- 'traefik-docker-proxy/**'
- '!traefik-docker-proxy/README.md'
- '!traefik-docker-proxy/examples/**'
- '.github/workflows/build-traefik-docker-proxy.yml'
workflow_dispatch:
schedule:
- cron: '35 4 * * 6' # Every Saturday at 04:35am
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
version: ['0.1.0']
caddy_version: ['2.9.1']
steps:
- name: Check-out repository
uses: actions/checkout@v4

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

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

- name: Build and push image to registry
uses: docker/build-push-action@v5
with:
platforms: linux/amd64
context: ./traefik-docker-proxy
file: ./traefik-docker-proxy/Dockerfile
push: true
build-args: |
CADDY_VERSION=${{ matrix.caddy_version }}
tags: |
ghcr.io/f-bn/traefik-docker-proxy:${{ matrix.version }}
ghcr.io/f-bn/traefik-docker-proxy:latest
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This repository contains my personal custom OCI containers images.
- [pgbouncer](./pgbouncer/)
- [postgresql](./postgresql/)
- [traefik](./traefik/)
- [traefik-docker-proxy](./traefik-docker-proxy/)
- [valkey](./valkey/)
- [watchtower](./watchtower/)

Expand Down
19 changes: 19 additions & 0 deletions traefik-docker-proxy/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
admin off
auto_https off
persist_config off
skip_install_trust
grace_period 5s
}

http://localhost:2375 {
route {
@allowed_paths {
method GET
protocol http
path_regexp ^(/v[0-9\.]+)?/(info|events|networks|containers/json|containers/[^/]+/json|version)$
}
reverse_proxy @allowed_paths unix//var/run/docker.sock
respond "Forbidden" 403
}
}
31 changes: 31 additions & 0 deletions traefik-docker-proxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# --- Build stage ---
FROM docker.io/golang:1.23.5 AS build

ARG TARGETOS
ARG TARGETARCH
ARG CADDY_VERSION="2.9.1"

WORKDIR /build

RUN go install github.com/caddyserver/xcaddy/cmd/[email protected]

RUN xcaddy build "v${CADDY_VERSION}" --output traefik-docker-proxy

# --- Final stage ---
FROM cgr.dev/chainguard/wolfi-base:latest

COPY --from=build --chown=0:0 --chmod=0755 \
/build/traefik-docker-proxy /usr/bin/traefik-docker-proxy

COPY Caddyfile /etc/Caddyfile

ENTRYPOINT [ "/usr/bin/traefik-docker-proxy" ]

CMD [ "run", "--config", "/etc/Caddyfile" ]

LABEL \
org.opencontainers.image.title="traefik-docker-proxy" \
org.opencontainers.image.source="https://github.com/f-bn/containers-images/traefik" \
org.opencontainers.image.description="Custom Caddy image for limiting Traefik access to the Docker API through the socket" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.authors="Florian Bobin <[email protected]>"
27 changes: 27 additions & 0 deletions traefik-docker-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## General informations

Custom Caddy image built from sources with specific configuration for proxying Docker socket to limit access to Docker API.

Built with Go 1.23.5

## Why creating this image ?

The image goal is to provide the most simple solution for limiting Traefik access to the Docker API through the socket. Therefore, this allows to not running Traefik as root and not mounting the Docker socket inside the Traefik container (that could lead to a pretty bad privilege escalation if Traefik is compromised).

For a more flexible solution for multiple other use-cases, prefer [docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) from Tecnativa.

## Image configuration

This image come with a specific Caddy configuration for the use-case described above. The reverse proxy server listens on `http://localhost:2375` and will forward request to the Docker UNIX domain socket mounted inside this container.

However only `GET` method on a specific set of Docker API endpoints are allowed:
- `/info`
- `/events`
- `/networks`
- `/containers/json`
- `/containers/<container id>/json`
- `/version`

For any other methods and/or endpoints called, a 403 error is returned. Moreover, endpoints required for Docker Swarm are not considered.

You can find a basic [docker-compose.yml](./examples/docker-compose.yml) in the `examples` folder showing a barebone configuration using this container image (i.e absolutely not production-ready).
39 changes: 39 additions & 0 deletions traefik-docker-proxy/examples/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
services:
traefik:
container_name: traefik
image: ghcr.io/f-bn/traefik:3.3.3
ports:
- 80:80
- 443:443
- 8080:8080
command:
- '--log.level=DEBUG'
- '--entrypoints.web.address=:80'
- '--entrypoints.websecure.address=:443'
- '--api'
- '--api.dashboard'
- '--api.insecure'
- '--providers.docker'
- '--providers.docker.endpoint=http://localhost:2375'
- '--providers.docker.exposedbydefault=false'
cap_drop: ['ALL']

traefik-docker-proxy:
container_name: traefik-docker-proxy
image: ghcr.io/f-bn/traefik-docker-proxy:0.1.0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
network_mode: container:traefik # note: join Traefik netns to strictly limit access of the proxy to the Traefik container
depends_on:
- traefik

demo:
container_name: demo
image: docker.io/nginx:latest
labels:
- traefik.enable=true
- traefik.http.routers.demo.rule=Host(`demo.domain.local`)
depends_on:
- traefik
- traefik-docker-proxy

0 comments on commit c30a4f5

Please sign in to comment.