Home > Software design >  NPM not found when using npm run start command within shell script from a docker container
NPM not found when using npm run start command within shell script from a docker container

Time:11-13

I am not sure what I may be doing wrong but I have the following script.sh file sitting at the root of my project:

script.sh

#!/bin/sh
npm run start
envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'

Then I referenced the above script in my Dockerfile as shown below:

Dockerfile

# Build environment
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./

# server environment
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080

COPY script.sh /
RUN chmod  x /script.sh

ENTRYPOINT ["/script.sh"]

After building the Docker image successfully, I attempted to run it as a container but all I keep getting back is the following error:

/script.sh: line 2: npm: not found

I expect that the script should be able to pick up the already installed npm from the environment.

What can I do differently to make this work?

CodePudding user response:

You're trying to run two separate programs, so run them in two separate containers.

# Dockerfile.app
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080
CMD npm run start
# Dockerfile.nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template

You might use a system like Docker Compose to run the two parts together:

# docker-compose.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.app
  nginx:
    build:
      context: .
      dockerfile: nginx
    ports:
      - 8080:80

Running docker-compose up -d will start both containers together. In your Nginx configuration, make sure to proxy_pass http://app:8080, using the Compose service name and the port number the service is listening on, to forward requests to the other container.

(The Nginx Dockerfile looks short, but it's correct. The Docker Hub nginx image already knows how to run the envsubst line from your script in its own entrypoint script and it has a correct default command already.)

There's two basic problems in the setup you show in the question, both related to trying to run two programs in the same container. The first is that you can't merge images, having a second FROM line makes Docker start over from the new base image. (So your final image contains only Nginx, not Node or your built application, hence the npm not found error.) The second you'll run into is that your script will start your application, but not start the Nginx proxy until after the application exits. There are some common workarounds to this (like using a background process) but it essentially results in one process or the other being unmonitored by Docker, so your application could potentially fail and Docker wouldn't notice it to be able to restart it.

  • Related