Archived
fix(docker): synchronize dev dependency volume
This commit is contained in:
+20
-2
@@ -36,12 +36,22 @@ WORKDIR /workspace
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
COPY scripts/install-git-hooks.mjs scripts/install-git-hooks.mjs
|
||||
# Keep an immutable dependency seed outside /workspace, which is hidden by the
|
||||
# checkout bind mount at runtime. A cached generation is added after custom
|
||||
# image hooks so it identifies the final dependency tree.
|
||||
RUN npm ci \
|
||||
&& ln -sf /workspace/node_modules/.bin/pi /usr/local/bin/pi \
|
||||
&& install -d -m 0755 /opt/pi-web-dev-dependencies \
|
||||
&& cp package.json package-lock.json /opt/pi-web-dev-dependencies/ \
|
||||
&& chmod -R a+rwX /workspace/node_modules \
|
||||
&& mv /workspace/node_modules /opt/pi-web-dev-dependencies/node_modules \
|
||||
&& ln -s /opt/pi-web-dev-dependencies/node_modules /workspace/node_modules \
|
||||
&& ln -sf /opt/pi-web-dev-dependencies/node_modules/.bin/pi /usr/local/bin/pi \
|
||||
&& npm cache clean --force \
|
||||
&& chmod -R a+rwX /workspace/node_modules /data \
|
||||
&& chmod -R a+rwX /data \
|
||||
&& chmod 0777 /workspace
|
||||
|
||||
COPY --chmod=0755 docker/internal/dev/sync-node-modules /usr/local/sbin/pi-web-dev-sync-node-modules
|
||||
|
||||
COPY --from=docker-cli /usr/local/bin/docker /usr/local/bin/docker
|
||||
COPY --from=docker-cli /usr/local/libexec/docker/cli-plugins /usr/local/libexec/docker/cli-plugins
|
||||
COPY docker/internal/bin/hostexec /usr/local/bin/hostexec
|
||||
@@ -49,6 +59,8 @@ COPY docker/pi-web-docker /usr/local/bin/pi-web-docker
|
||||
RUN chmod 0755 /usr/local/bin/hostexec /usr/local/bin/pi-web-docker
|
||||
|
||||
COPY docker/custom-image.d/ /tmp/pi-web-custom-image.d/
|
||||
# Image hooks use the temporary /workspace/node_modules symlink. Leave an empty
|
||||
# directory afterward so Compose can mount and populate the dependency volume.
|
||||
RUN bash -euxo pipefail -c '\
|
||||
shopt -s nullglob; \
|
||||
for script in /tmp/pi-web-custom-image.d/*.sh; do \
|
||||
@@ -56,9 +68,15 @@ RUN bash -euxo pipefail -c '\
|
||||
bash "${script}"; \
|
||||
done; \
|
||||
rm -rf /tmp/pi-web-custom-image.d; \
|
||||
test -L /workspace/node_modules; \
|
||||
rm /workspace/node_modules; \
|
||||
install -d -m 0777 /workspace/node_modules; \
|
||||
zypper clean --all; \
|
||||
rm -rf /var/cache/zypp/* \
|
||||
'
|
||||
# Cache the generation with the completed seed. Changes to any preceding layer,
|
||||
# including custom image hooks, rerun this step and refresh the named volume.
|
||||
RUN node -e 'process.stdout.write(`${require("node:crypto").randomUUID()}\n`)' > /opt/pi-web-dev-dependencies/generation
|
||||
|
||||
EXPOSE 8504 8505
|
||||
|
||||
|
||||
+2
-6
@@ -327,13 +327,9 @@ Use this shared directory to switch between runtime and dev mode, not to run bot
|
||||
|
||||
For sessions to appear under the same workspace in both modes, use the same project path in PI WEB. On Linux, prefer host-mounted paths such as `/home/core/<repo>`, `/srv/<project>`, or `/opt/<project>`. On Mac, prefer paths under `/Users/<you>/...`. The dev container also exposes this checkout as `/workspace` so the PI WEB dev server can run from it, but sessions started against `/workspace` are organized under that different working-directory path and will not line up with runtime sessions for the host-mounted path.
|
||||
|
||||
When `package-lock.json` changes, rebuild the dev image and recreate the `node_modules` volume so the bind-mounted checkout sees the new dependency tree:
|
||||
Development startup keeps the persistent `node_modules` volume synchronized with the dependency tree built into the dev image. When `package.json`, `package-lock.json`, the Node image, or another dependency-build input changes, `start` or `update` rebuilds the image and `data-init` refreshes the volume before `sessiond` starts. Manual volume removal is not required.
|
||||
|
||||
```bash
|
||||
./docker/pi-web-docker --dev stop
|
||||
docker volume rm pi-web-dev_node_modules
|
||||
./docker/pi-web-docker --dev start
|
||||
```
|
||||
If Compose is invoked directly without rebuilding after a manifest change, `data-init` stops with a mismatch message instead of starting against stale dependencies. Run `./docker/pi-web-docker --dev start` or `./docker/pi-web-docker --dev update` to rebuild and synchronize it.
|
||||
|
||||
## Local checkout validation
|
||||
|
||||
|
||||
@@ -56,14 +56,14 @@ services:
|
||||
set -euo pipefail
|
||||
mkdir -p /data/home /data/config /data/npm-cache /data/pi-web /data/pi-agent
|
||||
chown -R "${PI_WEB_UID:-1000}:${PI_WEB_GID:-1000}" /data
|
||||
/usr/local/sbin/pi-web-dev-sync-node-modules
|
||||
user: "0:0"
|
||||
security_opt:
|
||||
- label=disable
|
||||
environment:
|
||||
PI_WEB_UID: ${PI_WEB_UID:-1000}
|
||||
PI_WEB_GID: ${PI_WEB_GID:-1000}
|
||||
volumes:
|
||||
- *pi-web-dev-data-volume
|
||||
volumes: *pi-web-dev-volumes
|
||||
|
||||
sessiond:
|
||||
build: *pi-web-dev-build
|
||||
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
export PATH
|
||||
|
||||
log() {
|
||||
printf '%s\n' "$*" >&2
|
||||
}
|
||||
|
||||
die() {
|
||||
log "pi-web Docker dev dependencies: $*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
workspace_dir=${PI_WEB_DEV_WORKSPACE_DIR:-/workspace}
|
||||
seed_dir=${PI_WEB_DEV_DEPENDENCY_SEED_DIR:-/opt/pi-web-dev-dependencies}
|
||||
target_dir=$workspace_dir/node_modules
|
||||
generation_file=$seed_dir/generation
|
||||
marker_file=$target_dir/.pi-web-dev-dependency-generation
|
||||
|
||||
# A direct Compose invocation may skip the image rebuild. Fail closed rather
|
||||
# than copying dependencies for different checkout manifests.
|
||||
for manifest in package.json package-lock.json; do
|
||||
source_manifest=$workspace_dir/$manifest
|
||||
image_manifest=$seed_dir/$manifest
|
||||
[ -f "$source_manifest" ] || die "checkout is missing $source_manifest"
|
||||
[ -f "$image_manifest" ] || die "development image is missing $image_manifest"
|
||||
if ! cmp -s "$source_manifest" "$image_manifest"; then
|
||||
die "development image dependencies do not match the checkout; run ./docker/pi-web-docker --dev start or update to rebuild the image"
|
||||
fi
|
||||
done
|
||||
|
||||
[ -d "$seed_dir/node_modules" ] || die "development image is missing the dependency seed at $seed_dir/node_modules"
|
||||
[ -s "$generation_file" ] || die "development image is missing its dependency generation at $generation_file"
|
||||
[ ! -L "$target_dir" ] || die "refusing to synchronize through the node_modules symlink at $target_dir"
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
expected_generation=$(cat "$generation_file")
|
||||
current_generation=
|
||||
if [ -f "$marker_file" ]; then
|
||||
current_generation=$(cat "$marker_file")
|
||||
fi
|
||||
|
||||
if [ "$current_generation" = "$expected_generation" ]; then
|
||||
log "PI WEB Docker dev dependencies are current."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Synchronizing PI WEB Docker dev dependencies from the rebuilt image ..."
|
||||
# Write the marker only after a complete copy so a failed init retries next time.
|
||||
find "$target_dir" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
|
||||
cp -a "$seed_dir/node_modules/." "$target_dir/"
|
||||
printf '%s\n' "$expected_generation" >"$marker_file"
|
||||
chmod 0666 "$marker_file"
|
||||
log "PI WEB Docker dev dependencies synchronized."
|
||||
Reference in New Issue
Block a user