feat(nvm): Enable full nvm support in Docker builds and CI/CD workflows

- Add global nvm configuration in /etc/bash.bashrc (prepended before PS1 check)
- Create bash-with-nvm wrapper for Dockerfile RUN commands
- Add intelligent ENTRYPOINT for runtime nvm support
- Change default SHELL directive to use nvm wrapper
- nvm commands work directly in RUN without manual sourcing
- nvm commands work in CI/CD workflow bash -c scripts
- Maintain backward compatibility: npmci still available, ENV PATH preserved
- Non-bash shells fall back to ENV PATH (v20.12.2)
- Both interactive and non-interactive shells have full nvm access

Technical implementation:
- /etc/bash.bashrc: NVM init prepended before early return
- /usr/local/bin/bash-with-nvm: Build-time wrapper via SHELL directive
- /usr/local/bin/docker-entrypoint.sh: Runtime wrapper for bash -c detection
- ENV PATH fallback ensures non-bash compatibility

Tested:
- Dockerfile RUN: install, use, version switching
- Runtime bash -c: all nvm commands
- CI/CD workflows: .gitea context
- Backward compat: pnpm, npmci, ENV PATH
- Multi-stage builds, interactive shells
This commit is contained in:
2025-10-26 10:35:42 +00:00
parent ab4275c430
commit c6ba400214

View File

@@ -85,18 +85,58 @@ RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selectio
# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
# Make nvm available globally in all bash shells (interactive + non-interactive)
# IMPORTANT: Prepend to bashrc, before the "[ -z "$PS1" ] && return" line
RUN printf '%s\n%s\n%s\n\n%s\n' \
'export NVM_DIR="/usr/local/nvm"' \
'[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"' \
'[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"' \
"$(cat /etc/bash.bashrc)" > /etc/bash.bashrc
# Create a shell wrapper that sources nvm before executing commands
RUN echo '#!/bin/bash' > /usr/local/bin/bash-with-nvm \
&& echo 'set -e' >> /usr/local/bin/bash-with-nvm \
&& echo 'export NVM_DIR="/usr/local/nvm"' >> /usr/local/bin/bash-with-nvm \
&& echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> /usr/local/bin/bash-with-nvm \
&& echo 'eval "$@"' >> /usr/local/bin/bash-with-nvm \
&& chmod +x /usr/local/bin/bash-with-nvm
# Use wrapper for RUN commands to enable nvm
SHELL ["/usr/local/bin/bash-with-nvm"]
# Create entrypoint wrapper for runtime nvm support (CI/CD workflows)
RUN echo '#!/bin/bash' > /usr/local/bin/docker-entrypoint.sh \
&& echo 'set -e' >> /usr/local/bin/docker-entrypoint.sh \
&& echo 'export NVM_DIR="/usr/local/nvm"' >> /usr/local/bin/docker-entrypoint.sh \
&& echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> /usr/local/bin/docker-entrypoint.sh \
&& echo '# If command is bash, source nvm in it' >> /usr/local/bin/docker-entrypoint.sh \
&& echo 'if [ "$1" = "bash" ] && [ "$2" = "-c" ]; then' >> /usr/local/bin/docker-entrypoint.sh \
&& echo ' shift 2' >> /usr/local/bin/docker-entrypoint.sh \
&& echo ' exec bash -c "source /etc/bash.bashrc && $*"' >> /usr/local/bin/docker-entrypoint.sh \
&& echo 'else' >> /usr/local/bin/docker-entrypoint.sh \
&& echo ' exec "$@"' >> /usr/local/bin/docker-entrypoint.sh \
&& echo 'fi' >> /usr/local/bin/docker-entrypoint.sh \
&& chmod +x /usr/local/bin/docker-entrypoint.sh
# Enable nvm for runtime bash commands (CI/CD workflows)
ENV BASH_ENV=/etc/bash.bashrc
# prepare pnpm
ENV PNPM_HOME="/root/.local/share/pnpm/pnpm"
RUN mkdir -p ${PNPM_HOME}
ENV PATH="$PNPM_HOME:$PATH"
RUN bash -c "source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION_STABLE \
# Now nvm is available directly without sourcing
RUN nvm install $NODE_VERSION_STABLE \
&& nvm alias default $NODE_VERSION_STABLE \
&& nvm use default \
&& curl -fsSL https://get.pnpm.io/install.sh | bash - \
&& pnpm -v \
&& pnpm config set unsafe-perm true"
&& pnpm config set unsafe-perm true
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION_STABLE/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION_STABLE/bin:$PATH
# Set entrypoint to make nvm available in all runtime contexts
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["bash"]