Avoid network_mode: host for Docker

I do faced the same problem.
I have created a network and my docker compose spawns puts all my services under that network so traefik will expose it. Unfortunately I had to use traefik in host mode as homeassistant won’t work well without host mode.
Particularly my xiaomi sensor wouldn’t work…

I’ve deal this situation by manual creating toml file for traefik. I’ve defined backed with default gateway in my docker network.

@Lapatoc Can you share your toml config to do that?

[frontends]
  [frontends.homeassistant]
    backend="homeassistant"
    entryPoints = ["http", "https"]
    passHostHeader = true
    proirity = 20
    [frontends.homeassistant.routes.docker_host]
      rule="Host:hass.homelab.loc"
 [backends]
   [backends.homeassistant]
     [backends.homeassistant.servers.host]
       url = "http://172.17.0.1:8123"
       weight = 10

I have just been looking at this, I am using a slightly different approach:

  • I tired bridge mode using a docker-compose default network and the traefik_proxy network but ran into the usual problems with discovery

  • I am already using a macvlan network for certain hosts so decided to put hass docker onto the macvlan AND the traefik_proxy network and for good measure the default docker-compose network

  • Bizzarely this seems to work - I cannot use the macvlan to talk to containers bridged off the docker host - this is a macvlan restriction but I can use the default network to talk to these

  • I am using the traefik_proxy network to link everything that needs to be proxied

So far everything seems to be working well. I am still finding references in my configuration to the docker host but am replacing them with hosts on the default network to restore connectivity ie. node-red.dockerhost.com:1880 simply becomes node-red:1880 using the default docker-compose network.

its a little more complex than I would like, maybe I should move everything to macvlan??

I finally got this working too @Lapatoc’s method; docker running with --host, the port mapped, and adding the traefik provider manually.
Make sure to also add [file] to traefik.toml, to enable the non-docker traefik provider.

The log doesn’t seem to load in developer tools -> info -> log. Does that work for anyone that is running with net=host and static backend configuration?

It works if I directly access it via IP

Could you please share your complete config? Do you have a docker-compose.yml and a traefik.toml right?

Thanks!

I use Ansible instead of docker-compose, which is fairly similar in terms of syntax (both YAML), but not the same.
You can probably figure out how your docker-compose.yml would look like, by looking at my Ansible config though:

- name: "Create Home Assistant container"
  docker_container:
    name: homeassistant
    image: homeassistant/home-assistant
    privileged: yes
    volumes:
      - /opt/homeassistant/config:/config
    ports:
      - "8123:8123"
    network_mode: host
    restart_policy: always
    restart: yes
    state: started
    labels:
      traefik.enable: "false"

My traefik.toml looks like this:

debug = false
logLevel = "INFO"

defaultEntryPoints = ["http", "https"]

[api]
# traefik dashboard
  entryPoint = "traefik"
  dashboard = true

[entryPoints]
  [entryPoints.traefik]
    address = ":8080"

  [entryPoints.http]
    address = ":80"
# forward all HTTP traffic to HTTPS
    [entryPoints.http.redirect]
      entryPoint = "https"

  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]

# watch Docker, when new containers are created with label create mapping.
[docker]
  endpoint = "unix:///var/run/docker.sock"
  domain = "<your domain>"
  watch = true

[file]
[frontends]
  [frontends.frontend-home-assistant]
  backend = "backend-home-assistant"
    [frontends.frontend-home-assistant.routes.test_1]
    rule = "Host: home.<your-domain>"

[backends]
  [backends.backend-home-assistant]
    [backends.backend-home-assistant.servers.server1]
    url = "http://<your HA IP>:8123"

[acme]
email = "<your email>"
storage = "acme.json"
caServer = "https://acme-v02.api.letsencrypt.org/directory"
entryPoint = "https"
  [acme.dnsChallenge]
  provider = "transip"
  
[[acme.domains]]
# note: wild cards like the one below only work with DNS challenge
  main = "*.your-domain.com"

Note, I’m using a DNS challenge for LetsEncrypt, you should probably replace that for a HTTP challenge, unless there’s a reason for you to use a DNS challenge. See Traefik examples.

Thank you so much for the tidbit about the [file] parameter! I have been going mad over the past 2 days wondering why I could not get Traefik to read the config from my toml file! This was the ticket.

Has anyone managed to get this working with the iOS App? I get numerous authentication errors and cannot enable notifications. I did find some extra Traefik parameters on www.smarthomebeginner.com however not having much luck with these nor the default configurations above.

1 Like

Could it be possible to share you docker-compose file?

I’ll try and break it down:

version: "3.6"

services:

  hass:
    container_name: 'hass'
    image: 'homeassistant/home-assistant:latest'
    restart: 'unless-stopped'
    ports:
      - 8123:8123
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./volumes/home-assistant:/config
      - /dev/ttyACM0:/dev/ttyACM0
    environment:
      - TZ=Europe/London
    privileged: true
    networks:
      macvlan:
          ipv4_address: 192.168.1.22
      traefik_proxy:
      default:
    labels:
      - "traefik.enable=true"
      - "traefik.frontend.rule=Host:hass.xxx.com"
      - "traefik.port=8123"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.browserXSSFilter=true"
      - "traefik.frontend.headers.contentTypeNosniff=true"
      - "traefik.frontend.headers.forceSTSHeader=true"
      - "traefik.frontend.headers.SSLHost=xxx.com"
      - "traefik.frontend.headers.STSIncludeSubdomains=true"
      - "traefik.frontend.headers.STSPreload=true"
      - "traefik.frontend.headers.frameDeny=true"

here are the networks:

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  macvlan:
    external: true
  default:
    driver: bridge

here is one of the other containers:

  node-red:
    container_name: 'node-red'
    depends_on:
      - hass
    image: 'nodered/node-red-docker:v8'
    restart: 'unless-stopped'
    hostname: 'node-red.xxx.com'
    user: 'root'
    ports:
      - 1880:1880
    volumes:
      - ./volumes/node-red:/data
    networks:
      - traefik_proxy
      - default
    labels:
      - "traefik.enable=true"
      - "traefik.backend=node-red"
      - "traefik.frontend.rule=Host:node-red.xxx.com"
      - "traefik.port=1880"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.browserXSSFilter=true"
      - "traefik.frontend.headers.contentTypeNosniff=true"
      - "traefik.frontend.headers.forceSTSHeader=true"
      - "traefik.frontend.headers.SSLHost=xxx.com"
      - "traefik.frontend.headers.STSIncludeSubdomains=true"
      - "traefik.frontend.headers.STSPreload=true"
      - "traefik.frontend.headers.frameDeny=true"

Here is the mtacvlan setup from my ubuntu docker host. It creates me a /28 network range I can use for docker containers on my local network:

docker network create -d macvlan --subnet=192.168.1.0/24 --ip-range=192.168.1.16/28 --gateway=192.168.1.1 -o parent=ens33 macvlan

And here is the traefik:

version: '2'

services:
  traefik:
    image: traefik:latest
    restart: always
    domainname: xxx.com
    dns: 8.8.8.8
    ports:
      - 80:80
      - 443:443
#      - 7070:8080
    networks:
      - default
      - traefik_proxy
    environment:
      - [email protected]
      - CLOUDFLARE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    labels:
      - "traefik.enable=true"
      - "traefik.backend=traefik"
      - "traefik.frontend.rule=Host:traefik.xxxx.com"
#      - "traefik.frontend.rule=Host:${DOMAINNAME}; PathPrefixStrip: /traefik"
      - "traefik.frontend.auth.basic.users=yyyyyy:$$xxxxxxxxxxxxxxxxxxxxx"
      - "traefik.port=8080"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.browserXSSFilter=true"
      - "traefik.frontend.headers.contentTypeNosniff=true"
      - "traefik.frontend.headers.forceSTSHeader=true"
      - "traefik.frontend.headers.SSLHost=xxx,com"
      - "traefik.frontend.headers.STSIncludeSubdomains=true"
      - "traefik.frontend.headers.STSPreload=true"
      - "traefik.frontend.headers.frameDeny=true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./volumes/traefik:/etc/traefik
      - ./volumes/shared:/shared
    container_name: traefik

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  default:
    driver: bridge

The big challenge with mtacvlan is that the container cannot talk to the host on the mtacvlan network. I have got around this by using the traffic_proxy network to hook the hass front end into traefik, using the default network to allow the hass containers including db (not shown), influxdb (not shown) etc… to talk to each other .

I might try and simplify this by running every container in the mtacvlan network. The /28 gives me 16 usable addresses on the LAN for containers, I could increase this with a /27 or event a /26.

Not sure I have explained this entirely well.

1 Like

Thanks for the fast reply

When I do the changes and validated the config with docker-compose config, I get the following error: services.homeassistant.networks contains {"macvlan": {"ipv4_address": "192.168.0.200"}}, which is an invalid type, it should be a string

Config: https://pastebin.com/CtZ0ieB3

I removed the ‘ipv4_address’ line and managed to get it started, though HA isn’t able to connect to any thing.

How did you define the mtacvlan network.

Adrian

I used the following command:

docker network create -d macvlan --subnet=192.168.0.0/24 --ip-range=192.168.0.200/29 --gateway=192.168.0.1 -o parent=eth0 macvlan

I’m unable to ping to the ip of the docker server. The rest same to work as intended.

In order to make the port available on the macvlan IP I followed this guide: https://docs.docker.com/v17.09/engine/userguide/networking/get-started-macvlan/#macvlan-bridge-mode-example-usage

There is a requirement for mtacvlan to have your adapter in promiscuous mode. How to do that will depend on your setup

Did you find a solution to this, particularly a way to use bluetooth inside a container without host networking? I run my containers with macvlan networking, so using host networking isn’t an option for me.

2 Likes

Thanks! Nice trick to get this to work.

Did you manage to get this working with the iOS app ? I’m getting a homeassistant | 2019-09-17 18:48:27 WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from 172.18.0.2

Even though Traefik (172.18.0.2) is in trusted proxies