mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 09:34:36 +08:00
fix(compose): parse mode suffixes in long-form bind targets
This commit is contained in:
1 parent
cbe734c15b
commit
0d22b30910
6 files changed
+31
-6
No files matched your search
@@ -262,6 +262,7 @@ The persistent-storage implementation is the reference pattern: `Project\Service
|
||||
- Run `vendor/bin/pint --dirty --format agent` before finalizing changes
|
||||
- Every change must have tests — write or update tests, then run them. For bug fixes, follow TDD: write a failing test first, then fix the bug (see Test Enforcement below)
|
||||
- Check sibling files for conventions before creating new files
|
||||
- Nixpacks is deprecated. Never recommend it to users (issue replies, docs, UI copy, workarounds). Recommend the Dockerfile build pack, or Railpack where it fits.
|
||||
- When adding remote shell commands, account for servers using non-root SSH users: commands pass through `parseCommandsByLineForSudo()`, so test pipelines, redirects, substitutions, and `sh -c`/`bash -c` scripts with the non-root sudo parser.
|
||||
|
||||
## Git Workflow
|
||||
|
||||
@@ -148,7 +148,8 @@ function composeResourceDirectory(Application|Service $resource): string
|
||||
* Renders a long-syntax bind with its resolved source. It keeps the options that Docker Compose
|
||||
* accepts, such as read_only and bind, and removes other keys, which Compose rejects. Without
|
||||
* `bind.create_host_path`, a missing source is created, as with short syntax: Docker Compose
|
||||
* before v2.30 does not do that for long syntax.
|
||||
* before v2.30 does not do that for long syntax. A short-syntax mode in the target
|
||||
* (`/data/users.yml:ro`) becomes `read_only`, because Docker rejects it in long syntax.
|
||||
*
|
||||
* @param array<string, mixed> $volume
|
||||
* @return array<string, mixed>
|
||||
@@ -160,6 +161,10 @@ function composeLongBindVolume(array $volume, string $source): array
|
||||
fn ($key) => in_array($key, ['type', 'source', 'target', 'read_only', 'consistency', 'bind'], true) || str_starts_with((string) $key, 'x-'),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
if (preg_match('/^(.+):(ro|rw)$/', (string) ($volume['target'] ?? ''), $matches)) {
|
||||
$volume['target'] = $matches[1];
|
||||
$volume['read_only'] ??= $matches[2] === 'ro';
|
||||
}
|
||||
$volume['source'] = $source;
|
||||
$volume['bind'] = is_array($volume['bind'] ?? null) ? $volume['bind'] : [];
|
||||
$volume['bind']['create_host_path'] ??= true;
|
||||
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- type: bind
|
||||
source: ./data/users.yml
|
||||
target: /data/users.yml:ro
|
||||
target: /data/users.yml
|
||||
content: |
|
||||
users:
|
||||
# "admin" is the username
|
||||
|
||||
@@ -1138,7 +1138,7 @@
|
||||
"dozzle-with-auth": {
|
||||
"documentation": "https://dozzle.dev/?utm_source=coolify.io",
|
||||
"slogan": "Dozzle is a simple and lightweight web UI for Docker logs.",
|
||||
"compose": "c2VydmljZXM6CiAgZG96emxlOgogICAgaW1hZ2U6ICdhbWlyMjAvZG96emxlOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX0RPWlpMRV84MDgwCiAgICAgIC0gRE9aWkxFX0FVVEhfUFJPVklERVI9c2ltcGxlCiAgICB2b2x1bWVzOgogICAgICAtICcvdmFyL3J1bi9kb2NrZXIuc29jazovdmFyL3J1bi9kb2NrZXIuc29jaycKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vZGF0YS91c2Vycy55bWwKICAgICAgICB0YXJnZXQ6ICcvZGF0YS91c2Vycy55bWw6cm8nCiAgICAgICAgY29udGVudDogInVzZXJzOlxuICAjIFwiYWRtaW5cIiBpcyB0aGUgdXNlcm5hbWVcbiAgYWRtaW46XG4gICAgZW1haWw6IHRlc3RAZW1haWwuY29tXG4gICAgbmFtZTogQWRtaW5cbiAgICAjIEEgYmNyeXB0IGhhc2ggb2YgdGhlIHBhc3N3b3JkIHlvdSB3YW50IHRvIHVzZS4gQ2FuIGJlIGNvbXB1dGVkIHdpdGggXCJweXRob24zIC1jICdpbXBvcnQgYmNyeXB0O3ByaW50KGJjcnlwdC5oYXNocHcoYlwieW91ci1wYXNzd29yZFwiLGJjcnlwdC5nZW5zYWx0KDExKSkuZGVjb2RlKCkpJyBcIi4gRGVmYXVsdCBwYXNzd29yZCBpcyBcInRlc3RcIi5cbiAgICBwYXNzd29yZDogJDJhJDExJHZpdWNDdkZMbEhXdkJOT09JNnV5cHVWVS5EMDlVV2IuenN3UnhFZzBNa0RQaTFxL2JLYmRHXG4iCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gL2RvenpsZQogICAgICAgIC0gaGVhbHRoY2hlY2sKICAgICAgaW50ZXJ2YWw6IDNzCiAgICAgIHRpbWVvdXQ6IDMwcwogICAgICByZXRyaWVzOiA1Cg==",
|
||||
"compose": "c2VydmljZXM6CiAgZG96emxlOgogICAgaW1hZ2U6ICdhbWlyMjAvZG96emxlOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX0RPWlpMRV84MDgwCiAgICAgIC0gRE9aWkxFX0FVVEhfUFJPVklERVI9c2ltcGxlCiAgICB2b2x1bWVzOgogICAgICAtICcvdmFyL3J1bi9kb2NrZXIuc29jazovdmFyL3J1bi9kb2NrZXIuc29jaycKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vZGF0YS91c2Vycy55bWwKICAgICAgICB0YXJnZXQ6IC9kYXRhL3VzZXJzLnltbAogICAgICAgIGNvbnRlbnQ6ICJ1c2VyczpcbiAgIyBcImFkbWluXCIgaXMgdGhlIHVzZXJuYW1lXG4gIGFkbWluOlxuICAgIGVtYWlsOiB0ZXN0QGVtYWlsLmNvbVxuICAgIG5hbWU6IEFkbWluXG4gICAgIyBBIGJjcnlwdCBoYXNoIG9mIHRoZSBwYXNzd29yZCB5b3Ugd2FudCB0byB1c2UuIENhbiBiZSBjb21wdXRlZCB3aXRoIFwicHl0aG9uMyAtYyAnaW1wb3J0IGJjcnlwdDtwcmludChiY3J5cHQuaGFzaHB3KGJcInlvdXItcGFzc3dvcmRcIixiY3J5cHQuZ2Vuc2FsdCgxMSkpLmRlY29kZSgpKScgXCIuIERlZmF1bHQgcGFzc3dvcmQgaXMgXCJ0ZXN0XCIuXG4gICAgcGFzc3dvcmQ6ICQyYSQxMSR2aXVjQ3ZGTGxIV3ZCTk9PSTZ1eXB1VlUuRDA5VVdiLnpzd1J4RWcwTWtEUGkxcS9iS2JkR1xuIgogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIC9kb3p6bGUKICAgICAgICAtIGhlYWx0aGNoZWNrCiAgICAgIGludGVydmFsOiAzcwogICAgICB0aW1lb3V0OiAzMHMKICAgICAgcmV0cmllczogNQo=",
|
||||
"tags": [
|
||||
"dozzle",
|
||||
"docker",
|
||||
@@ -3509,7 +3509,7 @@
|
||||
"category": "messaging",
|
||||
"logo": "svgs/mosquitto.svg",
|
||||
"minversion": "0.0.0",
|
||||
"template_last_updated_at": "2026-01-05T18:25:15+01:00",
|
||||
"template_last_updated_at": "2026-10-23T22:58:59+02:00",
|
||||
"port": "1883"
|
||||
},
|
||||
"n8n-with-postgres-and-worker": {
|
||||
|
||||
@@ -1138,7 +1138,7 @@
|
||||
"dozzle-with-auth": {
|
||||
"documentation": "https://dozzle.dev/?utm_source=coolify.io",
|
||||
"slogan": "Dozzle is a simple and lightweight web UI for Docker logs.",
|
||||
"compose": "c2VydmljZXM6CiAgZG96emxlOgogICAgaW1hZ2U6ICdhbWlyMjAvZG96emxlOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9ET1paTEVfODA4MAogICAgICAtIERPWlpMRV9BVVRIX1BST1ZJREVSPXNpbXBsZQogICAgdm9sdW1lczoKICAgICAgLSAnL3Zhci9ydW4vZG9ja2VyLnNvY2s6L3Zhci9ydW4vZG9ja2VyLnNvY2snCiAgICAgIC0KICAgICAgICB0eXBlOiBiaW5kCiAgICAgICAgc291cmNlOiAuL2RhdGEvdXNlcnMueW1sCiAgICAgICAgdGFyZ2V0OiAnL2RhdGEvdXNlcnMueW1sOnJvJwogICAgICAgIGNvbnRlbnQ6ICJ1c2VyczpcbiAgIyBcImFkbWluXCIgaXMgdGhlIHVzZXJuYW1lXG4gIGFkbWluOlxuICAgIGVtYWlsOiB0ZXN0QGVtYWlsLmNvbVxuICAgIG5hbWU6IEFkbWluXG4gICAgIyBBIGJjcnlwdCBoYXNoIG9mIHRoZSBwYXNzd29yZCB5b3Ugd2FudCB0byB1c2UuIENhbiBiZSBjb21wdXRlZCB3aXRoIFwicHl0aG9uMyAtYyAnaW1wb3J0IGJjcnlwdDtwcmludChiY3J5cHQuaGFzaHB3KGJcInlvdXItcGFzc3dvcmRcIixiY3J5cHQuZ2Vuc2FsdCgxMSkpLmRlY29kZSgpKScgXCIuIERlZmF1bHQgcGFzc3dvcmQgaXMgXCJ0ZXN0XCIuXG4gICAgcGFzc3dvcmQ6ICQyYSQxMSR2aXVjQ3ZGTGxIV3ZCTk9PSTZ1eXB1VlUuRDA5VVdiLnpzd1J4RWcwTWtEUGkxcS9iS2JkR1xuIgogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIC9kb3p6bGUKICAgICAgICAtIGhlYWx0aGNoZWNrCiAgICAgIGludGVydmFsOiAzcwogICAgICB0aW1lb3V0OiAzMHMKICAgICAgcmV0cmllczogNQo=",
|
||||
"compose": "c2VydmljZXM6CiAgZG96emxlOgogICAgaW1hZ2U6ICdhbWlyMjAvZG96emxlOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9ET1paTEVfODA4MAogICAgICAtIERPWlpMRV9BVVRIX1BST1ZJREVSPXNpbXBsZQogICAgdm9sdW1lczoKICAgICAgLSAnL3Zhci9ydW4vZG9ja2VyLnNvY2s6L3Zhci9ydW4vZG9ja2VyLnNvY2snCiAgICAgIC0KICAgICAgICB0eXBlOiBiaW5kCiAgICAgICAgc291cmNlOiAuL2RhdGEvdXNlcnMueW1sCiAgICAgICAgdGFyZ2V0OiAvZGF0YS91c2Vycy55bWwKICAgICAgICBjb250ZW50OiAidXNlcnM6XG4gICMgXCJhZG1pblwiIGlzIHRoZSB1c2VybmFtZVxuICBhZG1pbjpcbiAgICBlbWFpbDogdGVzdEBlbWFpbC5jb21cbiAgICBuYW1lOiBBZG1pblxuICAgICMgQSBiY3J5cHQgaGFzaCBvZiB0aGUgcGFzc3dvcmQgeW91IHdhbnQgdG8gdXNlLiBDYW4gYmUgY29tcHV0ZWQgd2l0aCBcInB5dGhvbjMgLWMgJ2ltcG9ydCBiY3J5cHQ7cHJpbnQoYmNyeXB0Lmhhc2hwdyhiXCJ5b3VyLXBhc3N3b3JkXCIsYmNyeXB0LmdlbnNhbHQoMTEpKS5kZWNvZGUoKSknIFwiLiBEZWZhdWx0IHBhc3N3b3JkIGlzIFwidGVzdFwiLlxuICAgIHBhc3N3b3JkOiAkMmEkMTEkdml1Y0N2RkxsSFd2Qk5PT0k2dXlwdVZVLkQwOVVXYi56c3dSeEVnME1rRFBpMXEvYktiZEdcbiIKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSAvZG96emxlCiAgICAgICAgLSBoZWFsdGhjaGVjawogICAgICBpbnRlcnZhbDogM3MKICAgICAgdGltZW91dDogMzBzCiAgICAgIHJldHJpZXM6IDUK",
|
||||
"tags": [
|
||||
"dozzle",
|
||||
"docker",
|
||||
@@ -3509,7 +3509,7 @@
|
||||
"category": "messaging",
|
||||
"logo": "svgs/mosquitto.svg",
|
||||
"minversion": "0.0.0",
|
||||
"template_last_updated_at": "2026-01-05T18:25:15+01:00",
|
||||
"template_last_updated_at": "2026-10-23T22:58:59+02:00",
|
||||
"port": "1883"
|
||||
},
|
||||
"n8n-with-postgres-and-worker": {
|
||||
|
||||
@@ -235,3 +235,22 @@ it('keeps a ${VAR:-default} long-form bind source for Docker Compose when the va
|
||||
'variable reference' => ['$BASE_DIR/ao.yaml'],
|
||||
'vault reference' => ['{{vault.AO_CONFIG_FILE}}'],
|
||||
]);
|
||||
|
||||
it('moves a mode suffix from the target of a long-form bind to read_only', function (string $kind, string $mode, bool $readOnly) {
|
||||
$result = parseLongBind($kind, <<<YAML
|
||||
services:
|
||||
probe:
|
||||
image: alpine:3.22
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./data/users.yml
|
||||
target: /fixture:{$mode}
|
||||
content: 'users: {}'
|
||||
YAML);
|
||||
|
||||
expect($result['volume']['target'])->toBe('/fixture')
|
||||
->and($result['volume']['read_only'])->toBe($readOnly);
|
||||
})->with(['service', 'application'])->with([
|
||||
'read-only' => ['ro', true],
|
||||
'read-write' => ['rw', false],
|
||||
]);
|
||||
Reference in new issue
Block a user