fix(project): support running shopware-cli inside the docker dev container#1100
fix(project): support running shopware-cli inside the docker dev container#1100bdgraue (bdgraue) wants to merge 2 commits into
Conversation
… inside a container When shopware-cli itself runs inside a container (e.g. the docker-dev image, which ships the CLI but no docker binary), a type:docker environment cannot `docker compose exec` into anything: the first executor command fails with "docker: not found". Detect this case (container marker present, docker CLI absent) and fall back to local execution, since the container is itself the target environment. A host without docker keeps the DockerExecutor so it still fails with a clear error instead of silently running on the host. Refs shopware#1096 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inside a container shopware-cli runs as the mapped host UID, which has no passwd entry, so HOME resolves to / and child tools fail with EACCES (npm cache /.npm, composer ~/.composer). Redirect HOME to a writable temp dir once at startup when it is unset or not writable, so every child process (executor npm/ composer/console and the verifier's direct npm/node calls) inherits it. Linux only; a no-op when HOME is already writable, so normal host usage is unchanged. Refs shopware#1096 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Could you provide maybe an example shopware project or give access to an private one. I would like to further understand the setup 👀 |
|
Sure! I put up a minimal, self-contained repro you can clone: https://github.com/bdgraue/shopware-cli-1100-repro It boils the setup down to a web service on ghcr.io/shopware/docker-dev running as a host UID (via user:, exactly like project create/dev generate it) plus a .shopware-project.yml with type: docker. No Shopware install needed to see the two root causes — just docker compose run: 1. environment inside the containerdocker compose run --rm web sh -lc 'id; echo "HOME=$HOME"; command -v docker || echo "(no docker CLI)"; npm config get cache' -> uid=1001 (no name), HOME=/, (no docker CLI), /.npm2. the npm EACCES (root cause: HOME=/)docker compose run --rm web sh -lc 'cd /tmp && npm install is-odd 2>&1 | head' -> EACCES, mkdir '/.npm'3. a writable HOME fixes it (what EnsureWritableHome does)docker compose run --rm -e HOME=/tmp web sh -lc 'cd /tmp && npm install is-odd && echo OK' -> added 2 packages ... OKSo inside the container: there's no docker to exec into (→ the type: docker executor would die at feature:dump with docker: not found), and HOME=/ makes npm/composer fail with EACCES. The PR handles both — local execution + a writable HOME. The README also documents the full end-to-end path with a real project and a built binary. I verified all three commands above against the real image (uid 1001). |
|
I think the real problem is that the type here is docker and not local. When the type is local, it won't do any docker command inside docker container 👀 |
Follow-up to #1097, which made
project create --docker/project devwork for any host UID by running the containers as the calling user. This PR covers the remaining case: runningshopware-cliitself inside the dev container (directly, via an alias such asdocker compose exec web shopware-cli ..., or when the CLI is shipped in theghcr.io/shopware/docker-devimage).Problem
Two issues surface when the CLI runs inside the container:
docker-devimage ships nodockerCLI, but atype: dockerenvironment unconditionally builds aDockerExecutor. The first executor command (project storefront-buildrunsfeature:dump) then fails withdocker: not found— before any build step.HOMEresolves to/. npm (~/.npm) and composer (~/.composer) then fail withEACCES(e.g.mkdir /.npm).Changes
internal/executor/factory.go— atype: dockerenvironment falls back to local execution when running inside a container that has no docker CLI (detected via/.dockerenv//run/.containerenv+dockernot onPATH). The container is the target environment, so commands run locally. A host without docker keeps theDockerExecutor, so it still fails with a clear error instead of silently running on the host; a container with docker (dind) is unaffected.internal/system/home_linux.go+cmd/root.go— at startup, whenHOMEis unset or not writable, it is redirected to a writable temp dir, so every child process (the executor's npm/composer/console and the verifier's direct npm/node calls, which all inherit the process env) can write its caches. The writability check usesaccess(2)(no probe file is written, so shell completion stays side-effect free). Linux only; a no-op whenHOMEis already writable, so normal host and macOS/Windows usage is unchanged.Resulting behaviour
exec,HOME=/tmpfrom #1097)exec)Testing
EnsureWritableHome(keeps a writable HOME, redirects when unset/unwritable).gofmt,go vet,go build(linux/windows/darwin),golangci-lint run ./...andgo test ./...all pass.ghcr.io/shopware/docker-devimage as UID 1001: the CLI resolves to local execution (exec: php bin/console ..., nodocker: not found), redirectsHOMEto/tmp, and a realnpm installsucceeds.Refs #1096
🤖 Generated with Claude Code