Docker exec npm command - docker

I have successfully build docker container with node in it.
When I ssh'd into it, npm, node commands works as expected, but when I'm trying to execute command remotely (docker exec vvs_workspace npm install), it prints rpc error: code = 2 desc = oci runtime error: exec failed: exec: "npm": executable file not found in $PATH
Dockerfile:
#####################################
# Node / NVM:
#####################################
ENV NVM_DIR=/home/dockuser/.nvm
ENV NODE_VERSION 6.3.1
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash \
&& . ~/.nvm/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/v$NODE_VERSION/bin:$PATH
RUN echo "" >> ~/.bashrc && \
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bashrc && \
echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.bashrc
P.S. when executing docker exec vvs_workspace composer install everything is ok.

I found the solution, https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/82 , just add ENV PATH $PATH:/home/laradock/.nvm/versions/node/v6.8.0/bin in your Dockfile. change /home/laradock/.nvm/versions/node/v6.8.0/bin to your nvm path.

Related

Installing NVM on a Docker Alpine image: How to " Close and reopen your terminal to start using nvm or run the following to use it now"

I'm using this Dockerfile:
ARG PHP_VERSION=8.1
FROM php:${PHP_VERSION}-fpm-alpine AS coo-php
WORKDIR /srv/app
# Install Node, NVM and Yarn
RUN apk add --no-cache libstdc++ bash; \
echo 'source $HOME/.profile;' >> $HOME/.zshrc; \
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash; \
echo 'export NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release;' >> $HOME/.profile; \
echo 'nvm_get_arch() { nvm_echo "x64-musl"; }' >> $HOME/.profile; \
NVM_DIR="$HOME/.nvm"; source $HOME/.nvm/nvm.sh; source $HOME/.profile; \
nvm -v \
nvm install 18
It runs correctly but the install.sh tells me to:
#0 3.304 => Close and reopen your terminal to start using nvm or run the following to use it now:
#0 3.304
#0 3.304 export NVM_DIR="$HOME/.nvm"
#0 3.304 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
#0 3.304 [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
#0 3.338
#0 3.338 Node Version Manager (v0.35.1)
How to export NVM_DIR="$HOME/.nvm"?
Add to the next line (after the RUN apk add), ENV NVM_DIR "$HOME/.nvm", also bash is needed in order to source files
ARG PHP_VERSION=8.1
FROM php:${PHP_VERSION}-fpm-alpine AS coo-php
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
WORKDIR /srv/app
ENV NVM_DIR /usr/local/nvm # or ~/.nvm
ENV NODE_VERSION 18
# Install nvm with node and npm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash; \
&& . $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default

Change node version using nvm and docker-compose

I have a Dockerfile running centos/systemd that also installs nvm and have an entrypoint.sh that runs /usr/sbin/init (as required by docs) it also accept an argument from docker-compose command to control the node version being used - BUT it seems the node version is not persistent/kept for some reason.
How can I control node version from docker-compose file?
Dockerfile:
FROM centos/systemd
# Install & enable httpd
RUN yum -y update
RUN yum -y install \
httpd \
autofs \
gcc-c++ \
make \
git \
fontconfig \
bzip2 \
libpng-devel \
ruby \
ruby-devel \
zip \
unzip
RUN yum clean all
RUN systemctl enable httpd.service
# Setting up virtual hosts
RUN echo "IncludeOptional apps/*.conf" >> /etc/httpd/conf/httpd.conf
# Install nvm to later use in compose
ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 13.10.0
RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
# install node and npm
RUN source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm install 12.16.1 \
&& nvm install 11.9.0 \
&& nvm install 10.9.0 \
&& nvm alias default $NODE_VERSION \
&& nvm use default
# add node and npm to path so the commands are available
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
# Expose ports
EXPOSE 80
EXPOSE 443
COPY entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
entrypoint.sh:
#!/bin/bash
source root/.nvm/nvm.sh && nvm use "$#"
node --version
exec /usr/sbin/init
docker-compose:
version: '3'
services:
httpd:
build: '..\Web-Server\Apache'
privileged: true
ports:
- 80:80
- 443:443
command: 11.9.0
docker-compose up (output):
httpd_1 | Now using node v11.9.0 (npm v6.5.0)
httpd_1 | v11.9.0
docker exec -it /bin/sh -lc "node --version":
v13.10.0
Thanks!
If you create a dockerfile for each project then, combine them with docker-compose files, for each deployment, that is your best option. If you want to facilitate for code reuse you can look at creating a generic base image to which all your dockerfiles use.
Answering my own question after endless searches across the web.
2 things to note/change:
We need to set the default node version as well (inside the shell script). Unfortunately, I don't no why it's necessary to set it as default to keep it persistent but it just works (if anyone can explain that, please do). So entrypoint.sh looks like this:
#!/bin/bash
source root/.nvm/nvm.sh && nvm use "$#" && nvm alias default "$#"
node --version
exec /usr/sbin/init
when running bash with docker exec -it <container_id> /bin/sh -c "node --version" and not in interactive mode or login to shell it will not read startup scripts so node version set by using source /root/.nvm/nvm.sh and nvm use XXX is not red and thats why it's not "changed" for this specific bash session. Solution is to login to container and run node --version from within OR source nvm.sh as well before running node --version e.g. docker exec -it <container_id> sh -c "source /root/.nvm/nvm.sh && node --version"
Hope that helps to anyone that came across the same issue.

Runing commands installing nodejs in a new docker container works, but fails in a Dockerfile?

So my Dockerfile looks like that:
# start from base
FROM ubuntu:18.04
# install system-wide deps for node
RUN apt-get -yqq update
RUN apt-get install -yq wget
RUN wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
ENV NVM_DIR="$HOME/.nvm"
RUN [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
RUN [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
RUN nvm install v10.15.1
RUN nvm use v10.15.1
...
And when I try to build and image it fails on:
Step 6/13 : RUN [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
---> Running in e46106d9dfd8
The command '/bin/sh -c [ -s "$NVM_DIR/nvm.sh" ] && \.
"$NVM_DIR/nvm.sh"' returned a non-zero code: 1
What I don't understand is why when I run ubuntu:18.04 image and execute all the commands in the terminal everything succeeds? How can I fixt that, I am new to docker btw.

Run nvm with docker exec

I want to run nvm with docker exec
something like
docker run -d <image>
docker exec <container> nvm use v6.13.0 && npm install
but I have an error
OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "exec: \"nvm\": executable file not found in $PATH": unknown
I know that I can do something like that which work
docker exec <container> /bin/bash -c 'source "$NVM_DIR"/nvm.sh && nvm use v6.13.0'
But I don't want. Why ? because the point is to create a docker container usable with all my project with different version of python and node and run the nvm use <version> && npm install directly from gitlab-ci using the .nvmrc file into my project
my gitlab-cy.yml run a makefile which basically run the nvm use and npm install
image: cracky5457/nvm-pyenv-yarn
stages:
- install
- test
variables:
GITLAB_CACHING: "true"
cache:
paths:
- pip-cache/
key: "python_2.7"
installing:
stage: install
script:
- make install
artifacts:
paths:
- venv/
- node_modules/
expire_in: 1 hour
tags:
- docker-runner
and I don't want to push /bin/bash -c into my makefile because the project will become docker dependent locally
This is my docker image with the instructions to run it ( you have to create a file base_dependencies.txt, node-versions.txt, python-versions.txt ) or you can just docker pull cracky5457/nvm-pyenv-yarn
https://hub.docker.com/r/cracky5457/nvm-pyenv-yarn/
FROM phusion/baseimage:0.10.0
# Make sure bash is the standard shell
RUN rm /bin/sh && ln -sf /bin/bash /bin/sh
ENV ENV ~/.profile
ENV PYENV_ROOT /root/.pyenv
ENV PATH $PYENV_ROOT/shims:$PYENV_ROOT/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
# Add yarn registry
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
# Install base system libraries.
ENV DEBIAN_FRONTEND=noninteractive
COPY base_dependencies.txt /base_dependencies.txt
RUN apt-get update && \
apt-get install -y $(cat /base_dependencies.txt)
# Install pyenv and default python version.
ENV PYTHONDONTWRITEBYTECODE true
RUN git clone https://github.com/yyuu/pyenv.git /root/.pyenv && \
cd /root/.pyenv && \
git checkout `git describe --abbrev=0 --tags` && \
eval "$(pyenv init -)"
# Install nvm and default node version.
ENV NVM_DIR /usr/local/nvm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash && \
echo 'source $NVM_DIR/nvm.sh' >> /etc/profile
# Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install python and node versions
COPY python-versions.txt /python-versions.txt
RUN for version in $(cat python-versions.txt); do pyenv install $version; pyenv global $version; pip install virtualenv; done
COPY node-versions.txt /node-versions.txt
RUN for version in $(cat node-versions.txt); do source $NVM_DIR/nvm.sh; nvm install $version; done
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
I didn't found a proper way.
You can create a bash file into /usr/bin/nvm with chmod +x /usr/bin/nvm
#!/bin/bash
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm "$#"
And then
docker exec <container> nvm use
But it's tricky and I can't add an other instruction in my exec, for exemple I can't docker exec <container> nvm use && npm install at the same time.
But I finally fixed my issue directly in gitlab-ci.yaml using
$(NVM_DIR)/nvm.sh && nvm use && npm install

Docker CMD doesn't see installed components

I am trying to build a docker image using the following docker file.
FROM ubuntu:latest
# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# Update packages
RUN apt-get -y update && apt-get install -y \
curl \
build-essential \
libssl-dev \
git \
&& rm -rf /var/lib/apt/lists/*
ENV APP_NAME testapp
ENV NODE_VERSION 5.10
ENV SERVE_PORT 8080
ENV LIVE_RELOAD_PORT 8888
# Install nvm, node, and angular
RUN (curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash -) \
&& source /root/.nvm/nvm.sh \
&& nvm install $NODE_VERSION \
&& npm install -g angular-cli \
&& ng new $APP_NAME \
&& cd $APP_NAME \
&& npm run postinstall
EXPOSE $SERVE_PORT $LIVE_RELOAD_PORT
WORKDIR $APP_NAME
EXPOSE 8080
CMD ["node", "-v"]
But I keep getting an error when trying to run it:
docker: Error response from daemon: Container command 'node' not found or does not exist..
I know node is being properly installed because if I rebuild the image by commenting out the CMD line from the docker file
#CMD ["node", "-v"]
And then start a shell session
docker run -it testimage
I can see that all my dependencies are there and return proper results
node -v
v5.10.1
.....
ng -v
angular-cli: 1.0.0-beta.5
node: 5.10.1
os: linux x64
So my question is. Why is the CMD in Dockerfile not able to run these and how can I fix it?
When using the shell to RUN node via nvm, you have sourced the nvm.sh file and it will have a $PATH variable set in it's environment to search for executable files via nvm.
When you run commands via docker run it will only inject a default PATH
docker run <your-ubuntu-image> echo $PATH
docker run <your-ubuntu-image> which node
docker run <your-ubuntu-image> nvm which node
Specifying a CMD with an array execs a binary directly without a shell or a $PATH to lookup.
Provide the full path to your node binary.
CMD ["/bin/node","-v"]
It's better to use the node binary rather than the nvm helper scripts due to the way dockers signal processing works. It might be easier to use the node apt packages in docker rather than nvm.

Resources