From ff9ec68b0b2a95ec6b32d4a8eae36ccb9ca9e2d4 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Fri, 18 Sep 2026 17:36:12 +0700 Subject: [PATCH] fix(alloy): drop read_only so the inline compose config can be created Compose materialises a configs: entry with inline content by writing it into the container and refuses to do so on a read-only service: "cannot create config ... : `file` is the sole supported option". The container was created without /etc/alloy/config.alloy and the deployment failed at start. Keeping the config inline matters more than the read-only rootfs, so the flag and its tmpfs go. Every other control stays: no privileged, cap_drop ALL with only DAC_OVERRIDE added, no-new-privileges, the socket proxy, and the limits. --- alloy/README.md | 8 +++++++- alloy/docker-compose.yml | 3 --- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/alloy/README.md b/alloy/README.md index 720f9dc..16194ec 100644 --- a/alloy/README.md +++ b/alloy/README.md @@ -77,10 +77,16 @@ What it runs instead: | --- | --- | | `cap_drop: [ALL]` + `cap_add: [DAC_OVERRIDE]` | The image's entrypoint runs as uid 0 and reads host files owned by other users — the journal, paths under `/rootfs`, `/var/log`. Dropping every capability leaves it unable to open them, and unable to create its own storage directory. `DAC_OVERRIDE` restores exactly that and nothing else; `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `MKNOD` and the rest stay dropped. | | `no-new-privileges:true` | No setuid binary in the image can regain what was dropped. | -| `read_only: true` with `tmpfs: /tmp` | Only the `alloy-data` volume is writable. | | `mem_limit: 2g`, `pids_limit: 512` | Steady state is around 900 MB; the limit stops a leak taking the host down with it. | | `dockerproxy` instead of `/var/run/docker.sock` | See below. | +`read_only: true` is deliberately absent. Compose materialises an inline +`configs:` entry by writing it into the container, and refuses to do that on a +read-only service — `cannot create config ... : \`file\` is the sole supported +option`. Keeping the config inline is worth more than the read-only rootfs +here; adding it back means moving the config to a `config.alloy` file on disk +and switching the `configs:` entry to `file:`. + `network_mode: host` stays. `/proc/net` is a symlink to `/proc/self/net` and resolves against the reading process's network namespace, so bind-mounting the host's `/proc` to `/rootproc` is not enough — without host networking the diff --git a/alloy/docker-compose.yml b/alloy/docker-compose.yml index 65da101..7f1f643 100644 --- a/alloy/docker-compose.yml +++ b/alloy/docker-compose.yml @@ -13,9 +13,6 @@ services: cap_add: [DAC_OVERRIDE] # read host files owned by other uids: journal, /rootfs, /var/log security_opt: - no-new-privileges:true - read_only: true - tmpfs: - - /tmp mem_limit: 2g pids_limit: 512 depends_on: