From a4e6d06fd11fd185650954b9ebe1de73cd7cd42c Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 12 May 2026 23:45:10 -0400 Subject: [PATCH] fix: reject app-level vector-networks and vector-image, drop bridge from joined nets The Docker daemon refuses any endpoint settings on the default bridge network and `docker compose` unconditionally attaches the service name as an alias on every joined network, so combining bridge with user-defined networks via compose's `networks:` block is impossible. When `vector-networks` is set, the compose template now joins only the configured networks; outbound to external sinks still works through user-defined network NAT. Additionally, `vector-image` and `vector-networks` are both global-only but `common.CommandPropertySet` silently accepts them at app level by merging global-only keys into the valid-property set, so both now reject explicitly in `validateSetValue`. --- docs/deployment/logs.md | 4 +++- plugins/logs/set.go | 18 +++++++++++++++++- plugins/logs/templates/compose.yml.tmpl | 4 ---- tests/unit/logs.bats | 17 +++++++++++++---- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 3bd658f24..2e6ed0772 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -182,7 +182,7 @@ dokku logs:set --global vector-image By default, the Vector container runs with `network_mode: bridge` and can only reach app containers that are also on the default bridge network. Apps deployed onto a per-app network or a custom network - typically via `dokku network:set initial-network ` - are not reachable from Vector over Docker's internal DNS, so sinks that need to talk to those apps directly (for example, an in-host log search service such as [Logpond](https://github.com/dokku/logpond)) would have to route traffic out through the external proxy. -The global `vector-networks` property accepts a comma-separated list of Docker networks that Vector should additionally join. +The global `vector-networks` property accepts a comma-separated list of Docker networks for Vector to join. ```shell dokku logs:set --global vector-networks dokku-logs @@ -194,6 +194,8 @@ Multiple networks may be specified by separating them with a comma. dokku logs:set --global vector-networks dokku-logs,observability ``` +Setting this property **replaces** the default bridge attachment: the Vector container will be on the configured user-defined networks only, not the default Docker `bridge` network. Outbound traffic continues to work through the user-defined networks' NAT, so external sinks such as Datadog or hosted HTTP endpoints remain reachable. + Each network must already exist; setting a non-existent network or the reserved `bridge` value will fail. The list can be cleared by setting an empty value, which restores the default `network_mode: bridge` configuration. ```shell diff --git a/plugins/logs/set.go b/plugins/logs/set.go index 436a67da8..f0b5c0a43 100644 --- a/plugins/logs/set.go +++ b/plugins/logs/set.go @@ -14,6 +14,10 @@ func validateSetValue(appName string, key string, value string) error { return validateMaxSize(appName, value) } + if key == "vector-image" { + return validateVectorImage(appName, value) + } + if key == "vector-networks" { return validateVectorNetworks(appName, value) } @@ -64,7 +68,19 @@ func validateVectorSink(appName string, value string) error { return nil } +func validateVectorImage(appName string, value string) error { + if appName != "--global" { + return errors.New("vector-image may only be set globally with --global") + } + + return nil +} + func validateVectorNetworks(appName string, value string) error { + if appName != "--global" { + return errors.New("vector-networks may only be set globally with --global") + } + if value == "" { return nil } @@ -76,7 +92,7 @@ func validateVectorNetworks(appName string, value string) error { } if name == "bridge" { - return errors.New("Invalid vector-networks value, \"bridge\" is attached by default and must not be listed") + return errors.New("Invalid vector-networks value, \"bridge\" is not a valid entry for vector-networks") } result, err := common.CallExecCommand(common.ExecCommandInput{ diff --git a/plugins/logs/templates/compose.yml.tmpl b/plugins/logs/templates/compose.yml.tmpl index 1bd7b1bb1..9f27e1772 100644 --- a/plugins/logs/templates/compose.yml.tmpl +++ b/plugins/logs/templates/compose.yml.tmpl @@ -15,7 +15,6 @@ services: {{- if $.VectorNetworks }} networks: - bridge: {} {{- range $name := $.VectorNetworks }} {{ $name }}: {} {{- end }} @@ -32,9 +31,6 @@ services: {{- if $.VectorNetworks }} networks: - bridge: - name: bridge - external: true {{- range $name := $.VectorNetworks }} {{ $name }}: name: {{ $name }} diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats index 2958e83af..c0802531e 100644 --- a/tests/unit/logs.bats +++ b/tests/unit/logs.bats @@ -9,6 +9,7 @@ setup() { teardown() { destroy_app + dokku logs:set --global vector-networks >/dev/null 2>/dev/null || true docker network rm test-vector-net-a >/dev/null || true docker network rm test-vector-net-b >/dev/null || true global_teardown @@ -101,13 +102,19 @@ teardown() { echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-sink" + assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-networks, vector-sink" run /bin/bash -c "dokku logs:set $TEST_APP invalid value" 2>&1 echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-sink" + assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-networks, vector-sink" + + run /bin/bash -c "dokku logs:set $TEST_APP vector-image timberio/vector:latest-debian 2>&1" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "vector-image may only be set globally with --global" } @test "(logs) logs:set app" { @@ -473,6 +480,7 @@ teardown() { echo "output: $output" echo "status: $status" assert_failure + assert_output_contains "vector-networks may only be set globally with --global" run /bin/bash -c "dokku logs:set --global vector-networks does-not-exist 2>&1" echo "output: $output" @@ -484,7 +492,7 @@ teardown() { echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "\"bridge\" is attached by default and must not be listed" + assert_output_contains "\"bridge\" is not a valid entry for vector-networks" run /bin/bash -c "dokku logs:set --global vector-networks 'test-vector-net-a,' 2>&1" echo "output: $output" @@ -548,9 +556,9 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - assert_output_contains "bridge" assert_output_contains "test-vector-net-a" assert_output_contains "test-vector-net-b" + assert_output_contains "bridge" 0 run /bin/bash -c "dokku logs:vector-stop 2>&1" echo "output: $output" @@ -569,6 +577,7 @@ teardown() { assert_success assert_output_contains "test-vector-net-a" assert_output_contains "test-vector-net-b" + assert_output_contains "bridge" 0 run /bin/bash -c "dokku logs:set --global vector-networks 2>&1" echo "output: $output"