Search code examples
node.jsdockerdockerfiledocker-imagedocker-run

What happens if I write RUN node index.js instead of CMD node index.js in a dockerfile?


I made a simple hello world node.js application with the dockerfile

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./

RUN npm install
COPY . .
EXPOSE 8080
CMD node index.js

If I change the CMD to RUN in my dockerfile it still works. It is documented in dockerfile to use CMD as it will then start the node server upon the running of the container.

I would like to know what will happen underhood if I use RUN cmd instead of CMD. Basically what happens if I make a docker image which itself is in running state.


Solution

  • RUN will execute a command during the build process. CMD is used as the default command when executing a container, as opposed to building. If you run node index.js in a RUN instruction, your build will never finish and you don't have a container to share with others.

    Refer to the dockerfile documentation for more detail: RUN and CMD.

    Relevant bits from that documentation:

    The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.

    The main purpose of a CMD is to provide defaults for an executing container.


    EDIT: using OP's index.json, package.json, and Dockerfile files, the docker image build does not complete when using RUN node index.js and does complete (as expected) when using CMD node index.js.

    Contents of index.js:

    //Load express module with `require` directive
    var express = require('express')
    var app = express()
    
    //Define request response in root URL (/)
    app.get('/', function (req, res) {
      res.send('Hello World!')
    })
    
    //Launch listening server on port 8081
    app.listen(8080, function () {
      console.log('app listening on port 8080!')
    })
    

    Contents of package.json:

    {
      "name": "dummy_nodejs_app",
      "version": "1.0.0",
      "description": "Node.js on Docker",
      "author": "Debojit",
      "main": "server.js",
      "scripts": {
        "start": "node server.js"
      },
      "dependencies": {
        "express": "^4.16.1"
      }
    }
    

    When using the Dockerfile as follows:

    FROM node:10
    WORKDIR /usr/src/app
    COPY package*.json ./
    
    RUN npm install
    COPY . .
    EXPOSE 8080
    RUN node index.js
    

    then the build hangs. Here is the output:

    jakub@dash:/tmp/test-node$ docker build -t test .
    Sending build context to Docker daemon  4.096kB
    Step 1/7 : FROM node:10
     ---> d5680e53a228
    Step 2/7 : WORKDIR /usr/src/app
     ---> Using cache
     ---> a4b4547833e5
    Step 3/7 : COPY package*.json ./
     ---> Using cache
     ---> 2b19cc3e48a3
    Step 4/7 : RUN npm install
     ---> Using cache
     ---> fe1f1e72d17d
    Step 5/7 : COPY . .
     ---> eb6fe0e3d1a7
    Step 6/7 : EXPOSE 8080
     ---> Running in e573b923fcb2
    Removing intermediate container e573b923fcb2
     ---> b3590153eed7
    Step 7/7 : RUN node index.js
     ---> Running in 08b408e6e6f3
    app listening on port 8080!
    

    This hangs indefinitely.

    When using the Dockerfile

    FROM node:10
    WORKDIR /usr/src/app
    COPY package*.json ./
    
    RUN npm install
    COPY . .
    EXPOSE 8080
    CMD node index.js
    

    the build output is:

    jakub@dash:/tmp/test-node$ docker build -t test .
    Sending build context to Docker daemon  4.096kB
    Step 1/7 : FROM node:10
     ---> d5680e53a228
    Step 2/7 : WORKDIR /usr/src/app
     ---> Using cache
     ---> a4b4547833e5
    Step 3/7 : COPY package*.json ./
     ---> Using cache
     ---> 2b19cc3e48a3
    Step 4/7 : RUN npm install
     ---> Using cache
     ---> fe1f1e72d17d
    Step 5/7 : COPY . .
     ---> Using cache
     ---> fc036f428e34
    Step 6/7 : EXPOSE 8080
     ---> Using cache
     ---> d1ede7276d34
    Step 7/7 : CMD node index.js
     ---> Using cache
     ---> cf051929395b
    Successfully built cf051929395b
    Successfully tagged test:latest