feat(directus): mount per-project extensions folder into Directus ser…#10
Merged
Conversation
…vice
Add an absolute bind mount `${projectsDir}/${container.id}/extensions ->
/directus/extensions` to the generated Directus service compose so custom
Directus extensions can be provided per project without a custom image.
- Absolute path because Swarm bind mounts do not resolve relative paths.
- Docker auto-creates the (empty, root-owned) folder on deploy; an empty
folder means "no extensions" = unchanged behaviour for existing services.
- Directus loads extensions read-only, so root ownership is fine for that.
To let the Directus Marketplace write installs here, chown the folder to
1000:1000 (the node/directus container user).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the API’s Directus Docker Compose generator to bind-mount a per-project extensions directory from the host into the Directus container, enabling custom Directus extensions without requiring a custom image.
Changes:
- Add
envConfigusage to locate the configured projects directory at compose-generation time. - Mount
${projectsDir}/${container.id}/extensionsto/directus/extensionsin the generated Directus service compose.
…t reject
Docker Swarm does NOT auto-create a missing bind-mount source (unlike
standalone `docker run`); it rejects the task with "invalid mount config
... bind source path does not exist". Verified in a local single-node swarm.
createDockerComposeFile() now mkdir's `${projectsDir}/${container.id}/extensions`
before deploy, so the Directus extensions bind mount added in the previous
commit does not break existing/new Directus services on redeploy.
Also corrects the compose comment (the folder is created by deploy.party, not
automatically by Docker) and documents that the Marketplace needs the folder
chowned to 1000:1000 (verified: uid 1000 gets "Permission denied" otherwise).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines
+121
to
+123
| // Swarm rejects a service whose bind-mount source path is missing, so the | ||
| // per-project extensions folder (see getDirectus) must exist before deploy. | ||
| await fs.mkdir(`${envConfig.projectsDir}/${container.id}/extensions`, { recursive: true }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Was
Fügt dem generierten Directus-Service-Compose einen absoluten Bind-Mount
${projectsDir}/${container.id}/extensions → /directus/extensionshinzu, damit eigene Directus-Extensions pro Projekt bereitgestellt werden können — ohne Custom-Image.Wichtig: Swarm legt den Ordner NICHT selbst an
Anders als standalone
docker run -verstellt Docker Swarm eine fehlende Bind-Mount-Quelle nicht, sondern lehnt den Task ab (invalid mount config … bind source path does not exist— im lokalen Single-Node-Swarm verifiziert). Deshalb legtcreateDockerComposeFile()denextensions-Ordner vor demstack deployperfs.mkdir(..., { recursive: true })an. Ein leerer Ordner = „keine Extensions" = unverändertes Verhalten für bestehende Services.Marketplace
Directus lädt Extensions lesend → der (deploy.party-owned) Ordner reicht dafür. Der Marketplace schreibt Installs aber als uid 1000 in den Ordner und braucht ihn daher auf
1000:1000gechownt (verifiziert: uid 1000 bekommt sonstPermission denied). Aktuell manueller Schritt.Directus-Services, die aktuell Store-Extensions installiert haben, halten diese nur ephemer. Beim ersten Redeploy nach diesem Change überschattet der leere Host-Ordner sie → sie verschwinden. Vorher
docker cp <task>:/directus/extensions/. /data/projects/<id>/extensions/sichern oder neu installieren. Betrifft alle Directus-Services der Instanz.Verifiziert
tsc -p tsconfig.build.json --noEmit→ Exit 0mkdirstartet der Service sauber