dockertraefikicecast

502 for OPTIONS in Traefik 1.7


I'm testing a local Icecast server on Ubuntu, using Traefik 1.7 in Docker containers.

When manually going to a page on a subdomain, all CORS headers are set:

enter image description here

But accessing the page from another local domain always gives 502 errors on OPTIONS.

I've managed to get some debug info from the Traefik container, but I'm stuck as to how to solve this.

everse-proxy    | time="2022-11-11T21:08:01Z" level=debug msg="vulcand/oxy/forward/http: begin ServeHttp on request" Request="{\"Method\":\"OPTIONS\",\"URL\":{\"Scheme\":\"http\",\"Opaque\":\"\",\"User\":null,\"Host\":\"10.10.1.8:8000\",\"Path\":\"\",\"RawPath\":\"\",\"ForceQuery\":false,\"RawQuery\":\"\",\"Fragment\":\"\",\"RawFragment\":\"\"},\"Proto\":\"HTTP/2.0\",\"ProtoMajor\":2,\"ProtoMinor\":0,\"Header\":{\"Accept\":[\"*/*\"],\"Accept-Encoding\":[\"gzip, deflate, br\"],\"Accept-Language\":[\"en-US,en;q=0.9,nl;q=0.8\"],\"Access-Control-Request-Headers\":[\"icy-metadata\"],\"Access-Control-Request-Method\":[\"GET\"],\"Cache-Control\":[\"no-cache\"],\"Origin\":[\"https://gsr.localhost.traefik.me\"],\"Pragma\":[\"no-cache\"],\"Referer\":[\"https://gsr.localhost.traefik.me/\"],\"Sec-Fetch-Dest\":[\"empty\"],\"Sec-Fetch-Mode\":[\"cors\"],\"Sec-Fetch-Site\":[\"same-site\"],\"User-Agent\":[\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"]},\"ContentLength\":0,\"TransferEncoding\":null,\"Host\":\"radio.localhost.traefik.me\",\"Form\":null,\"PostForm\":null,\"MultipartForm\":null,\"Trailer\":null,\"RemoteAddr\":\"127.0.0.1:53784\",\"RequestURI\":\"/radio\",\"TLS\":null}"
reverse-proxy    | time="2022-11-11T21:08:01Z" level=debug msg="Upstream ResponseWriter of type *pipelining.writerWithoutCloseNotify does not implement http.CloseNotifier. Returning dummy channel."
reverse-proxy    | time="2022-11-11T21:08:01Z" level=debug msg="'502 Bad Gateway' caused by: EOF"
reverse-proxy    | time="2022-11-11T21:08:01Z" level=debug msg="vulcand/oxy/forward/http: Round trip: http://10.10.1.8:8000, code: 502, Length: 11, duration: 5.960359ms tls:version: 303, tls:resume:true, tls:csuite:c02f, tls:server:radio.localhost.traefik.me"

The docker-compose.yml:

version: "3.1"

networks:
  db_default:
    external: true

services:
  reverse-proxy:
    container_name: reverse-proxy
    image: traefik:v1.7-alpine # The official Traefik docker image
    network_mode: "host"
    command: --api  --docker # Enables the web UI and tells Tr  fik to listen to docker
    volumes:
      - ./docker:/certs:ro
      - ./docker/traefik.toml:/etc/traefik/traefik.toml
      - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events

  gsr2:
      container_name: gsrdev2
      build: docker
      volumes:
        - .bash_history:/root/.bash_history
        - ./:/var/www
        - ./log:/tmp/audit
      environment:
        #PHP_IDE_CONFIG: "serverName=gsr2.localhost.xip.io"
        XDEBUG_CONFIG: "start_with_request=yes"
      labels:
        - traefik.enable=true
        - "traefik.frontend.rule=Host:gsr.localhost.traefik.me"
      networks:
        - db_default

  icecast2:
    image: pltnk/icecast2
    container_name: icecast2
    expose:
      - 8000
    volumes:
      - ./icecast.xml:/etc/icecast2/icecast.xml
      - ./log:/var/log/icecast2
      - ./docker/bundle.pem:/etc/icecast2/bundle.pem
    labels:
      - traefik.enable=true
      - "traefik.frontend.rule=Host:radio.localhost.traefik.me"
    networks:
      - db_default

The traefik.toml:


defaultEntryPoints = ["http","https"]

loglevel="DEBUG"

[api]
    dashboard = false

[entryPoints]

[entryPoints.http]
    address = ":80"
#[entryPoints.http.redirect]
#    regex = "^http://(www.)*(.*)"
#    replacement = "https://$2"
#    permanent = true

[entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]
       [[entryPoints.https.tls.certificates]]
           certFile = "/certs/cert.pem"
           keyFile = "/certs/key.pem"

[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "localhost.traefik.me"
watch = true
exposedbydefault = false
network = "proxy"

Header config in Icecast server:

    <http-headers>
        <header name="Access-Control-Allow-Origin" value="*" />
        <header name="Vary" value="Origin" />
        <header name="Access-Control-Allow-Methods" value="GET, OPTIONS, PUT, POST" />
        <header name="Access-Control-Allow-Headers" value="Content-Type, Icy-Metadata" />
        <header name="Access-Control-Expose-Headers" value="Icy-MetaInt, Icy-Br, Icy-Description, Icy-Genre, Icy-Name, Ice-Audio-Info, Icy-Url, Icy-Sr, Icy-Vbr, Icy-Pub" />

    </http-headers>

Solution

  • I fixed it! First I migrated to Traefik 2. Then, according to the Traefik docs, I can just include some middleware to set the headers for CORS directly on my container, like this:

      icecast2:
        image: pltnk/icecast2
        container_name: icecast2
        expose:
          - 8000
        volumes:
          - ./icecast.xml:/etc/icecast2/icecast.xml
          - ./log:/var/log/icecast2
        labels:
          - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
          - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=*"
          - "traefik.http.middlewares.testheader.headers.accessControlAllowHeaders=Content-Type, Icy-Metadata"
          - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
          - "traefik.http.middlewares.testheader.headers.addvaryheader=true"
          - traefik.enable=true
          - traefik.http.routers.icecast2.middlewares=testheader
          - "traefik.http.routers.icecast2.entrypoints=http,https"
          - "traefik.http.routers.icecast2.tls=true"
          - traefik.http.routers.icecast2.rule=Host(`radio.localhost.traefik.me`)