refactor(nvm): Move wrapper scripts to image_support_files directory
Improved code organization and maintainability: - Created image_support_files/ directory for Docker helper scripts - Moved bash-with-nvm and docker-entrypoint.sh to support directory - Added comprehensive README.md documenting each script's purpose - Updated Dockerfile to COPY from organized directory structure Benefits: - Cleaner repository structure - Scripts are now version-controlled files (not echo chains) - Easier to read, modify, and maintain - Self-documented with in-directory README No functional changes - all nvm functionality remains identical.
This commit is contained in:
		
							
								
								
									
										25
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -93,31 +93,14 @@ RUN printf '%s\n%s\n%s\n\n%s\n' \ | |||||||
|     '[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"' \ |     '[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"' \ | ||||||
|     "$(cat /etc/bash.bashrc)" > /etc/bash.bashrc |     "$(cat /etc/bash.bashrc)" > /etc/bash.bashrc | ||||||
|  |  | ||||||
| # Create a shell wrapper that sources nvm before executing commands | # Copy nvm wrapper scripts from support directory | ||||||
| RUN echo '#!/bin/bash' > /usr/local/bin/bash-with-nvm \ | COPY image_support_files/bash-with-nvm /usr/local/bin/bash-with-nvm | ||||||
|     && echo 'set -e' >> /usr/local/bin/bash-with-nvm \ | COPY image_support_files/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh | ||||||
|     && echo 'export NVM_DIR="/usr/local/nvm"' >> /usr/local/bin/bash-with-nvm \ | RUN chmod +x /usr/local/bin/bash-with-nvm /usr/local/bin/docker-entrypoint.sh | ||||||
|     && 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 | # Use wrapper for RUN commands to enable nvm | ||||||
| SHELL ["/usr/local/bin/bash-with-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) | # Enable nvm for runtime bash commands (CI/CD workflows) | ||||||
| ENV BASH_ENV=/etc/bash.bashrc | ENV BASH_ENV=/etc/bash.bashrc | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								image_support_files/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								image_support_files/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | |||||||
|  | # Image Support Files | ||||||
|  |  | ||||||
|  | This directory contains helper scripts that are copied into the Docker image during build to enable NVM functionality. | ||||||
|  |  | ||||||
|  | ## Files | ||||||
|  |  | ||||||
|  | ### `bash-with-nvm` | ||||||
|  |  | ||||||
|  | **Purpose**: Wrapper script for Dockerfile RUN commands | ||||||
|  |  | ||||||
|  | **Usage**: Set as SHELL directive in Dockerfile | ||||||
|  | ```dockerfile | ||||||
|  | SHELL ["/usr/local/bin/bash-with-nvm"] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **What it does**: | ||||||
|  | - Sources nvm before executing each Dockerfile RUN command | ||||||
|  | - Enables direct usage of `nvm` commands without manual sourcing | ||||||
|  | - Example: `RUN nvm install 18` works without `bash -c "source ..."` | ||||||
|  |  | ||||||
|  | **Location in image**: `/usr/local/bin/bash-with-nvm` | ||||||
|  |  | ||||||
|  | **How it works**: | ||||||
|  | 1. Exports NVM_DIR environment variable | ||||||
|  | 2. Sources `$NVM_DIR/nvm.sh` to load nvm functions | ||||||
|  | 3. Executes the command passed to it via `eval "$@"` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### `docker-entrypoint.sh` | ||||||
|  |  | ||||||
|  | **Purpose**: ENTRYPOINT script for runtime nvm support | ||||||
|  |  | ||||||
|  | **Usage**: Set as ENTRYPOINT in Dockerfile | ||||||
|  | ```dockerfile | ||||||
|  | ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **What it does**: | ||||||
|  | - Makes nvm available in `docker run ... bash -c` commands | ||||||
|  | - Enables nvm in CI/CD workflow scripts | ||||||
|  | - Passes through non-bash commands unchanged | ||||||
|  |  | ||||||
|  | **Location in image**: `/usr/local/bin/docker-entrypoint.sh` | ||||||
|  |  | ||||||
|  | **How it works**: | ||||||
|  | 1. Loads nvm in the entrypoint environment | ||||||
|  | 2. Detects if command is `bash -c ...` | ||||||
|  | 3. If yes: Injects `source /etc/bash.bashrc` before the user's command | ||||||
|  | 4. If no: Executes command as-is with `exec "$@"` | ||||||
|  |  | ||||||
|  | **Examples**: | ||||||
|  | - `docker run image bash -c "nvm install 18"` → nvm is available | ||||||
|  | - `docker run image node --version` → Passes through to node binary | ||||||
|  | - CI/CD: `run: nvm install 19` → Works automatically | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Why These Scripts Are Needed | ||||||
|  |  | ||||||
|  | **The Problem**: | ||||||
|  | - nvm is a bash function, not a binary executable | ||||||
|  | - It must be sourced into each shell session | ||||||
|  | - Docker RUN commands and `bash -c` don't automatically source it | ||||||
|  |  | ||||||
|  | **The Solution**: | ||||||
|  | 1. **bash-with-nvm**: Makes Dockerfile RUN commands work | ||||||
|  | 2. **docker-entrypoint.sh**: Makes runtime `bash -c` commands work | ||||||
|  | 3. **/etc/bash.bashrc** (configured in Dockerfile): Makes interactive shells work | ||||||
|  |  | ||||||
|  | Together, these provide seamless nvm access in all contexts. | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Maintenance | ||||||
|  |  | ||||||
|  | **Modifying the scripts**: | ||||||
|  | 1. Edit the file in this directory | ||||||
|  | 2. Rebuild the Docker image | ||||||
|  | 3. Test with both `docker build` and `docker run` scenarios | ||||||
|  |  | ||||||
|  | **Testing checklist**: | ||||||
|  | - [ ] `RUN nvm install 18` works in Dockerfile | ||||||
|  | - [ ] `docker run image bash -c "nvm install 18"` works | ||||||
|  | - [ ] `docker run image node --version` still works (fallback) | ||||||
|  | - [ ] CI/CD workflows can use nvm commands | ||||||
|  |  | ||||||
|  | **Debugging**: | ||||||
|  | - View script in running container: `docker run image cat /usr/local/bin/bash-with-nvm` | ||||||
|  | - Test entrypoint manually: `docker run --entrypoint /bin/bash image -c "nvm --version"` | ||||||
							
								
								
									
										9
									
								
								image_support_files/bash-with-nvm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								image_support_files/bash-with-nvm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | # Load nvm before executing Dockerfile RUN commands | ||||||
|  | export NVM_DIR="/usr/local/nvm" | ||||||
|  | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" | ||||||
|  |  | ||||||
|  | # Execute the command passed to this wrapper | ||||||
|  | eval "$@" | ||||||
							
								
								
									
										14
									
								
								image_support_files/docker-entrypoint.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								image_support_files/docker-entrypoint.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | # Load nvm in the entrypoint environment | ||||||
|  | export NVM_DIR="/usr/local/nvm" | ||||||
|  | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" | ||||||
|  |  | ||||||
|  | # If command is bash -c, inject bashrc sourcing to make nvm available | ||||||
|  | if [ "$1" = "bash" ] && [ "$2" = "-c" ]; then | ||||||
|  |   shift 2 | ||||||
|  |   exec bash -c "source /etc/bash.bashrc && $*" | ||||||
|  | else | ||||||
|  |   exec "$@" | ||||||
|  | fi | ||||||
		Reference in New Issue
	
	Block a user