5

I created a Dockerfile for a nodejs project. It contains a package.json with many scripts.

"scripts": {
        "start": "npm run",
        "server": "cd server && npm start",
        "generator": "cd generator && npm start",
...
    },

I need to run server and genberator in my docker image. How to achieve this?

I tried:

CMD ls;npm run server ; npm run generator this won't find the package json because shellform seems to run within /bin/sh -c.

CMD ["npm","run","server"] is also not working and is missing the 2nd command

The ls in first try showed me that all files are in place (incl. the package.json).

For sake of completeness the project in question is https://github.com/seekwhencer/node-bilder-brause (not mine). the current Dockerfile:

FROM node:14

# Create app directory
WORKDIR /usr/src/app

# Bundle app source
COPY ./* ./

RUN npm install

EXPOSE 3050
EXPOSE 3055
CMD ls ; npm run server ; npm run generator
2
  • 1
    Write a wrapper script that includes the npm commands, and then use that as your CMD. Commented Jun 28, 2020 at 21:01
  • could you make this an answer please? Commented Jun 28, 2020 at 21:03

3 Answers 3

14

The typical way to run multiple commands in a CMD or ENTRYPOINT is to write all of the commands to a file and then run that file. This is demonstrated in the Dockerfile below.

This Dockerfile also install imagemagick, which is a dependency of the package OP is trying to use. I also changed the base image to node:14-alpine because it is much smaller than node:14 but works just as well for this purpose.

FROM node:14-alpine

# Install system dependencies for this package.
RUN apk add --no-cache imagemagick

# Create app directory
WORKDIR /usr/src/app

# Bundle app source
COPY . .

RUN npm install \
    # Install server and generator.
    && npm run postinstall \
    # Write entrypoint.
    && printf "ls\nnpm run server\nnpm run generator\n" > entrypoint.sh

EXPOSE 3050
EXPOSE 3055

CMD ["/bin/sh", "entrypoint.sh"]
docker build --tag nodebilderbrause .
docker run --rm -it nodebilderbrause

The contents of entrypoint.sh are written in the Dockerfile. Here is what the file would look like.

ls
npm run server
npm run generator
Sign up to request clarification or add additional context in comments.

4 Comments

could you please add the sh file? if it has mor than 2 line 1: npm run server 2:npm run generator
I don't understand what you're asking for. Do you want the contents of the shell file?
jakub sorry - but yes. (i accepted and upvoted anyway)
Can we use command in entrypoint.sh npm run server & npm run generator ?
10

I found another way, adding for sake of completeness and reference for me: https://www.npmjs.com/package/concurrently

adding

RUN npm install -g concurrently

enables:

CMD ["concurrently","npm:server", "npm:generator"]

Comments

1

If you need to run two separate processes, the typical approach is to run two separate containers. You can run both containers off the same image; it's very straightforward to override the command part of a container when you start it.

You need to pick something to be the default CMD. Given the package.json you show, for example, you can specify

CMD npm start

When you actually go to run the container, you can specify an alternate command: anything after the image name is taken as the command. (If you're using Docker Compose, specify command:.) A typical docker run setup might look like:

docker build -t bilder-brause .

docker network create photos

docker run \
  --name server \
  --net photos \
  -d \
  -p 3050:3050 \
  bilder-brause \
  npm run server

docker run \
  --name generator \
  --net photos \
  -d \
  -p 3055:3055 \
  bilder-brause \
  npm run generator

You could build separate images for the different components with separate EXPOSE and CMD directives if you really wanted

FROM bilder-brause
EXPOSE 3050
CMD npm run server

Building these is a minor hassle; there is no way to specify in Compose that one local image is built FROM another so the ordering might not turn out correctly, for example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.