Docker and network segregation

I currently have a mixture of services, with some in VMs / LXC containers and a bunch in docker containers hosted off of a VM. I have a few VLANs for network segregation and for the VM and LXC containers, it’s pretty easy to just give them interfaces on the appropriate VLANs and off things go.

Similarly, isolation for docker-to-docker communication is pretty straightforward, but where I’ve hit a challenge is where I’ve got a docker container that I want to have access to the internal VLAN (or even just limit it to particular hosts) it’s not clear to me how best to go about doing that.

Relatedly - are there ways to do east-west segregation of docker networks within docker? A major network I have is ‘rproxy’, which is basically used by Traefik to talk to everything behind it - it would certainly make sense to prevent those services from talking to each other where I can.

Maybe I’m wrong — and most likely I am — but even if you change the internal docker subnets, the containers on the same VM (where Docker is running) will still be able to communicate with each other.
There is no firewall or anything like that.
The only way would be with Kubernetes and Calico, or something similar.

I think that even docker swarm doesn’t have any firewall feature

If I really want to isolate docker containers, I will run separate docker host VMs, with each VM on a completely different VLAN. However, I found that there are very few things I want to isolate in this manner, and it was easier to stand them up in their own LCX containers. I mainly run a cloudflare tunnel, pi hole, and crowdsec in separate LXCs each on the isolated VLAN.

If you want to put containers on a VLAN I think you need to look at the Docker IPvlans networks. I’ve not used one myself, but I have used a Macvlan network and they are similar. Not the easiest thing to get setup, but it does the job.

Ah, the good old ‘rproxy’ network. This is something I’ve seen a lot of examples use as it is simple, but as you have said, it’s not the best approach for security.

While I am no security or Docker expert, I put each container on a separate external network that Traefik also has access to. For example, a network called `traefik-freshrss` that is both on FreshRSS and Traefik containers. That way Traefik can talk to all of the containers it needs to, but the containers cannot talk to each other. If the application allows, further bonus points can be obtained by then only exposing the frontend of an app to that network and having a separate internal network between the frontend and backend containers. Brief non-working Docker Compose style example

networks:
  traefik-app1:
    name: traefik-app1
    external: true
  app1:
    name: app1
    internal: true
  traefik-app2:
    name: traefik-app2
    external: true

services:
  app1-frontend:
    image: app1fe:latest
    container_name: app1-frontend
    expose:
      - 3000
    networks:
      - traefik-app1
      - app1
    labels:
      - "traefik.enable=true"
      - ...

  app1-backend:
    image: app1be:latest
    container_name: app1-backend
    expose:
      - 1234
    networks:
      - app1

  app2:
    image: app2:latest
    container_name: app2
    expose:
      - 80
    networks:
      - traefik-app2
    labels:
      - "traefik.enable=true"
      - ...

In this example, Traefik can talk to app1-frontend and app2. app1 and app2 cannot talk to each other. Only app1-frontend can talk to app1-backend as they are both on the same network. With it also marked as internal this also means the backend cannot reach any external networks including the host. This may break things if the backend container needs internet access etc. so use with caution.

2 Likes

Thanks - this is helpful and has given me some good direction on where to look. My current setup is internal network only (but there are plans to add a DMZ + internet facing services on a separate VM once I’ve had a chance to work through the best way to do that securely).

It’s good to know not to keep looking for east-west segregation within networks - I suspect for internal I can get away with having the single rproxy internal network for Traefik but for DMZ it will be per-service networks like Acestes describes. A Macvlan network also looks like it could do one of the things I want (I can use it to grant connectivity to the DB VMs for containers where I don’t want to allow full internet connectivity).

I do find myself wondering if there’s stuff I can do with Docker IPVLAN and Proxmox Zones to integrate them, but that’s likely to be an advanced and fiddly topic and I should probably see if MACVLAN can be a satisfactory solution first before going that route.

Docker lets you create bridges which you can bind to whatever interface (or none) you want. You can associate a container to multiple networks (as seen by another user above) that need to straddle multiple networks. You can also just drop a container directly on the external / “real” network using MACVLAN while binding it to whatever interface suites you and let your firewall / router manage its access. The macvlan introduces a little challenge where if you need container > container communication you will want an internal only / backend network (basic docker network set to internal). Docker’s networking manages DNS so you can refer to them by their container_name.