Retry listen(0)/bind(0) when the preferred port is taken, gated by BARE_OS_BIND_FALLBACK (default on; set 0/false for strict bind). - Add lib/bare-os-bind-fallback.js and use it from bare-os-www-initd and bare-openssh (including privilege-path + holesail actual port). - POSIX socket bridge in index.js: TCP listen and UDP bind fallbacks. - bare-holesail + bare-holesail-managed: retry Holesail ready(); persist resolved listen port in managed state when it changes. - Add test.bare-os-bind-fallback.js.
106 lines
4.4 KiB
Docker
106 lines
4.4 KiB
Docker
# Pear-published bare-os booter (consumer). Build (use --progress=plain to see all steps):
|
||
# docker build --progress=plain -t bare-os-booter .
|
||
#
|
||
# Pear CLI + Pear/Bare runtime are installed during the image build under /opt/pear-home.
|
||
# That tree is chowned to user `booter` because the runtime refuses to run unless the
|
||
# active user owns the Pear config directory.
|
||
#
|
||
# Runtime env: HOME must stay /opt/pear-home (Pear runtime lives there). bare-os state uses
|
||
# BARE_OS_HOST_DATA=/data (volume). Do not set HOME=/data — Pear will not boot the app.
|
||
#
|
||
# Entrypoint runs `pear run --no-ask pear://…` so non-interactive starts skip Pear’s TRUST prompt.
|
||
#
|
||
# Run — interactive / attachable (needs TTY + stdin for the shell REPL):
|
||
# docker run --rm -it -v bare-os-booter-data:/data --name bare-os-booter bare-os-booter
|
||
#
|
||
# Detached, then attach to the same session:
|
||
# docker run -dit --name bare-os-booter -v bare-os-booter-data:/data bare-os-booter
|
||
# docker attach bare-os-booter
|
||
#
|
||
# Or: docker compose -f docker-compose.yaml up -d booter && docker compose attach booter
|
||
#
|
||
# The booter needs a Hyperswarm peer (seeder on topic bare-os-v1) within BARE_OS_BOOT_TIMEOUT_MS,
|
||
# or set BARE_OS_OFFLINE_LKG_BOOT + BARE_OS_LKG_SYSTEM_KEY_HEX — see bare-os docs.
|
||
#
|
||
# If peers never appear: UDP/hole-punch often fails behind Docker NAT — on Linux use
|
||
# docker-compose.host-network.yaml (merge) so the container uses the host network stack.
|
||
# Pear terminal expectations: https://docs.pears.com/guide/making-a-pear-terminal-app.html
|
||
|
||
FROM node:22-bookworm-slim
|
||
|
||
RUN apt-get update \
|
||
&& apt-get install -y --no-install-recommends \
|
||
bash \
|
||
bsdutils \
|
||
ca-certificates \
|
||
libatomic1 \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
# Bootstrap CLI + runtime under a fixed HOME so paths stay inside the image.
|
||
ENV HOME=/opt/pear-home
|
||
|
||
RUN mkdir -p /opt/pear-home \
|
||
&& set -ex \
|
||
&& echo "=== npm: global pear CLI ===" \
|
||
&& npm install -g pear@latest \
|
||
&& npm ls -g --depth=0 pear \
|
||
&& PEAR_CLI="$(command -v pear)" \
|
||
&& echo "pear CLI path: ${PEAR_CLI}" \
|
||
&& ls -la "${PEAR_CLI}" \
|
||
&& echo "=== pear run pear://runtime (Pear/Bare runtime; requires network during build) ===" \
|
||
&& pear run pear://runtime \
|
||
&& echo "=== Runtime tree ===" \
|
||
&& ls -la /opt/pear-home/.config/pear \
|
||
&& ls -la /opt/pear-home/.config/pear/bin \
|
||
&& du -sh /opt/pear-home/.config/pear \
|
||
&& echo "=== PATH: runtime shim resolves ===" \
|
||
&& export PATH="/opt/pear-home/.config/pear/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
|
||
&& SHIM="$(command -v pear)" \
|
||
&& echo "first pear on PATH: ${SHIM}" \
|
||
&& ls -la "${SHIM}" \
|
||
&& echo "=== pear help (via runtime shim; must succeed) ===" \
|
||
&& pear help | head -30 \
|
||
&& echo "=== npm pear CLI (explicit path; still useful for diagnostics) ===" \
|
||
&& /usr/local/bin/pear --help | head -20
|
||
|
||
RUN chmod -R a+rX /opt/pear-home \
|
||
&& find /opt/pear-home/.config/pear -type f \( -perm -111 -o -name 'pear-runtime' -o -name 'pear' \) \
|
||
-exec chmod a+rx {} \; 2>/dev/null || true
|
||
|
||
ENV PATH="/opt/pear-home/.config/pear/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||
|
||
RUN groupadd --system booter \
|
||
&& useradd --system --gid booter --home-dir /data --create-home booter \
|
||
&& chown -R booter:booter /opt/pear-home \
|
||
&& echo "=== Ownership after chown ===" \
|
||
&& id booter \
|
||
&& ls -la /opt/pear-home/.config \
|
||
&& echo "=== Smoke: booter user runs pear runtime shim ===" \
|
||
&& su -s /bin/sh booter -c \
|
||
'set -ex; id; command -v pear; pear help | head -20'
|
||
|
||
RUN mkdir -p /usr/local/lib/bare-os-booter
|
||
|
||
COPY run-pear-inner.sh /usr/local/lib/bare-os-booter/run-pear-inner.sh
|
||
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||
RUN chmod 755 /usr/local/lib/bare-os-booter/run-pear-inner.sh \
|
||
&& chmod 755 /usr/local/bin/docker-entrypoint.sh
|
||
|
||
USER booter
|
||
WORKDIR /data
|
||
|
||
ENV NODE_ENV=production
|
||
# Pear: trust + shim under /opt/pear-home — must match install (see build-time HOME).
|
||
ENV HOME=/opt/pear-home
|
||
# bare-os: Corestore + host data on the mounted volume (overrides homedir for host paths).
|
||
ENV BARE_OS_HOST_DATA=/data
|
||
# Default wait for at least one swarm peer (seeder). Raise if needed.
|
||
ENV BARE_OS_BOOT_TIMEOUT_MS=120000
|
||
# Line-oriented stderr in Docker; avoids full-screen splash on stdout obscuring docker logs.
|
||
ENV BARE_OS_NO_SPLASH=1
|
||
ENV TERM=xterm-256color
|
||
|
||
VOLUME ["/data"]
|
||
|
||
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|