Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ labels:
> A network named `frontend` in a project folder `myapp` becomes
> `myapp_frontend`.

### Network aliases

If a container has the label `traefik.aliases` these aliases are set for
traefik when it is added to the network. `traefik.aliases` must be a
comma-separated list. Having aliases on traefik is useful to separate stacks
but still letting a container from one stack talk through traefik to the other
stack.

```yaml
labels:
- "traefik.enable=true"
- "traefik.aliases=myotherapp.domain"
- "traefik.docker.network=myapp_frontend"
- "traefik.http.routers.myapp.rule=Host(`myapp.${DOMAIN}`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
```

---

## ⚙️ Configuration
Expand Down
11 changes: 9 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ def connect_traefik_to_network(container):
# Retrieve allowed networks from the container's labels, if specified
allowed_networks_label = container.labels.get(config.traefik.networkLabel, "")
allowed_networks = allowed_networks_label.split(",")


# add alias labels
alias_label = container.labels.get("traefik.aliases")
aliases = [a.strip() for a in alias_label.split(",") if a.strip()] if alias_label else []

app_logger.debug(f"Allowed networks: {allowed_networks}")

for net in target_networks:
Expand All @@ -130,7 +134,10 @@ def connect_traefik_to_network(container):
if allowed_networks == [''] or net in allowed_networks:
if net not in traefik_container.attrs["NetworkSettings"]["Networks"]:
app_logger.debug(f"Connecting Traefik to network {net}.")
network.connect(traefik_container)
if aliases and net in allowed_networks:
Comment thread
obeone marked this conversation as resolved.
Outdated
network.connect(traefik_container, aliases=aliases)
else:
network.connect(traefik_container)
app_logger.info(f"Successfully connected Traefik to network {net}.")
else:
app_logger.info(f"Traefik is already connected to network {net}, skipping connection.")
Expand Down
108 changes: 108 additions & 0 deletions tests/unit/test_main_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,113 @@ def test_compose_network_resolution(self, mock_docker_client, mock_config, mock_

network.connect.assert_called_once_with(traefik)

def test_no_alias_set(self, mock_docker_client, mock_config, mock_logger):
"""
When traefik.aliases is not set, the container should not get an alias
"""
container = MagicMock()
container.name = "web-app"
container.attrs = {
"NetworkSettings": {"Networks": {"app_net": {}}}
}
container.labels = {}

traefik = MagicMock()
traefik.attrs = {"NetworkSettings": {"Networks": {"bridge": {}}}}
mock_docker_client.containers.get.return_value = traefik

network = MagicMock()
network.attrs = {"Name": "app_net", "Labels": {}}
mock_docker_client.networks.get.return_value = network

main.connect_traefik_to_network(container)

network.connect.assert_called_once()
assert("aliases" not in network.connect.call_args.kwargs.keys())

def test_single_alias_set(self, mock_docker_client, mock_config, mock_logger):
"""
When traefik.aliases is set to a single value, the network connect call
should have that value as alias
"""
container = MagicMock()
container.name = "web-app"
container.attrs = {
"NetworkSettings": {"Networks": {"app_net": {}}}
}
container.labels = {
"traefik.aliases": "app",
"traefik.docker.network": "app_net",
}

traefik = MagicMock()
traefik.attrs = {"NetworkSettings": {"Networks": {"bridge": {}}}}
mock_docker_client.containers.get.return_value = traefik

network = MagicMock()
network.attrs = {"Name": "app_net", "Labels": {}}
mock_docker_client.networks.get.return_value = network

main.connect_traefik_to_network(container)

network.connect.assert_called_once_with(traefik, aliases=["app"])

def test_multiple_aliases_set(self, mock_docker_client, mock_config, mock_logger):
"""
When traefik.aliases is set to a comma separated string, the network
connect call should have a list of strings value as aliases value
"""
container = MagicMock()
container.name = "web-app"
container.attrs = {
"NetworkSettings": {"Networks": {"app_net": {}}}
}
container.labels = {
"traefik.aliases": "app, app2, app3",
"traefik.docker.network": "app_net",
}

traefik = MagicMock()
traefik.attrs = {"NetworkSettings": {"Networks": {"bridge": {}}}}
mock_docker_client.containers.get.return_value = traefik

network = MagicMock()
network.attrs = {"Name": "app_net", "Labels": {}}
mock_docker_client.networks.get.return_value = network

main.connect_traefik_to_network(container)

network.connect.assert_called_once_with(
traefik, aliases=["app", "app2", "app3"])

def test_aliases_with_additional_whitespace(self, mock_docker_client, mock_config, mock_logger):
"""
When traefik.aliases is set to a comma separated string, the network
connect call should have a list of strings value as aliases value
"""
container = MagicMock()
container.name = "web-app"
container.attrs = {
"NetworkSettings": {"Networks": {"app_net": {}}}
}
container.labels = {
"traefik.aliases": " app one, app2, app3 ",
"traefik.docker.network": "app_net",
}

traefik = MagicMock()
traefik.attrs = {"NetworkSettings": {"Networks": {"bridge": {}}}}
mock_docker_client.containers.get.return_value = traefik

network = MagicMock()
network.attrs = {"Name": "app_net", "Labels": {}}
mock_docker_client.networks.get.return_value = network

main.connect_traefik_to_network(container)

network.connect.assert_called_once_with(
traefik, aliases=["app one", "app2", "app3"])


# ---------------------------------------------------------------------------
# disconnect_traefik_from_network
Expand Down Expand Up @@ -462,3 +569,4 @@ def get_container(name):

# connect should have been called for both containers' networks
assert network.connect.call_count == 2

Loading