Ratchet
Ratchet

Reputation: 283

How can I run an npm command in a docker container?

I am trying to run an angular application in development mode inside a docker container, but when i run it with docker-compose build it works correctly but when i try to put up the container i obtain the below error:



ERROR: for sypgod  Cannot start service sypgod: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"npm\": executable file not found in $PATH

The real problem is that it doesn't recognize the command npm serve, but why??

The setup would be below:

Docker container (Nginx Reverse proxy -> Angular running in port 4000)

I know that there are better ways of deploying this but at this moment I need this setup for some personals reasons

Dockerfile:


FROM node:10.9 


COPY package.json package-lock.json ./

RUN npm ci && mkdir /angular && mv ./node_modules ./angular

WORKDIR /angular

RUN npm install -g @angular/cli 

COPY . . 


FROM nginx:alpine
COPY toborFront.conf /etc/nginx/conf.d/
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
CMD ["npm", "serve", "--port 4000"]

NginxServerSite

server{
    listen 80;
    server_name sypgod;


    location / {
            proxy_read_timeout 5m;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://localhost:4000/;


    }

}


Docker Compose file(the important part where I have the problem)

 sypgod: # The name of the service
        container_name: sypgod  # Container name
        build: 
            context: ../angular
            dockerfile: Dockerfile # Location of our Dockerfile


Upvotes: 24

Views: 107110

Answers (5)

Mateja Petrovic
Mateja Petrovic

Reputation: 4357

I was stuck at this step:

docker run -it --rm node /usr/local/bin/npm install

Which would instantiate a container from the node image with the default latest tag. run npm install inside the container in the predefined working directory. The solution is to simply use a bind mount in conjunction with setting the working directory:

docker run -it --rm -v .:/tmp -w /tmp node /usr/local/bin/npm install

. is the project to run npm install in and /tmp is just a directory to mount your project in inside the container. Using /tmp makes sense since the container will be removed after the command executes due to the --rm flag.

P.S. Consider use node:alpine or node:hydrogen-alpine (hydrogen is the codename for lts version 18, but you can use a newer lts version codename) and alias the image locally by tagging it docker tag ecbe47697d08 node or docker tag ecbe47697d08 node:alp. The alpine image takes up approximately 10 times less disk space, but provides you access to the same version of npm as the non alpine image.

Upvotes: 0

Ben in CA
Ben in CA

Reputation: 851

If you have Portainer.io installed for managing your Docker setup, you can open the console for a particular container from a browser.

This is useful if you want to run a reference command like "npm list" to show what versions of dependencies have been loaded.

portainer

So that you can view it like this:

console

I found this useful for diagnosing issues where an update to a dependency had broken something, which worked fine in a test environment, but the docker version had installed newer minor versions which broke the application.

Upvotes: 0

David Maze
David Maze

Reputation: 159781

The image that's finally getting run is this:

FROM nginx:alpine
COPY toborFront.conf /etc/nginx/conf.d/
EXPOSE 8080
CMD ["npm", "serve", "--port 4000"]

The first stage doesn't have any effect (you could COPY --from=... files out of it), and if there are multiple CMDs, only the last one has an effect. Since you're running this in a plain nginx image, there's no npm command, leading to the error you see.

I'd recommend using Node on the host for a live development environment. When you've built and tested your application and are looking to deploy it, then use Docker if that's appropriate. In your Dockerfile, run ng build in the first stage to compile the application to static files, add a COPY --from=... in the second stage to get the built application into the Nginx image, and delete all the CMD lines (nginx has an appropriate default CMD). @VikramJakhar's answer has a more complete Dockerfile showing this.

It looks like you might be trying to run both Nginx and the Angular development server in Docker. If that's your goal, you need to run these in two separate containers. To do this:

  • Split this Dockerfile into two. Put the CMD ["npm", "serve"] line at the end of the first (Angular-only) Dockerfile.
  • Add a second block in the docker-compose.yml file to run the second container. The backend npm serve container doesn't need to publish ports:.
  • Change the host name of the backend server in the Nginx config from localhost to the Docker Compose name of the other container.

Upvotes: 12

Vikram Jakhar
Vikram Jakhar

Reputation: 742

You can do something like below

### STAGE 1: Build ###

# We label our stage as ‘builder’
FROM node:alpine as builder

RUN apk --no-cache --virtual build-dependencies add \
    git \
    python \
    make \
    g++

    RUN mkdir -p /ng-app/dist

    WORKDIR /ng-app

    COPY package.json package-lock.json ./

    ## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
    RUN npm install

    COPY . .

    ## Build the angular app in production mode and store the artifacts in dist folder

    RUN npm run ng build -- --prod --output-path=dist


    ### STAGE 2: Setup ###

    FROM nginx:1.14.1-alpine

    ## Copy our default nginx config
    COPY toborFront.conf /etc/nginx/conf.d/

    ## Remove default nginx website
    RUN rm -rf "/usr/share/nginx/html/*"

    ## From ‘builder’ stage copy over the artifacts in dist folder to default nginx public folder
    COPY --from=builder /ng-app/dist /usr/share/nginx/html

    CMD ["nginx", "-g", "daemon off;"]

Upvotes: 2

btnhawk
btnhawk

Reputation: 231

It would appear the npm can't be accessed from the container. Try defining where it tries to execute it from:

docker run -v "$PWD":/usr/src/app -w /usr/src/app node:10.9 npm serve --port 4000

source: https://gist.github.com/ArtemGordinsky/b79ea473e8bc6f67943b

Also make sure that npm is installed on the computer running the docker container.

Upvotes: 14

Related Questions