Skip to content

Building the Image

We’ve dissected the Dockerfile and discussed the .dockerignore file.

Let’s put it all together and build an image that is ready to run.

First, let’s make a tiny Node app so that we have something to containerize and test.

In terminal, run the following:

Terminal window
mkdir node-aboard
cd node-aboard
npm init -y

Then, create a super-simple server.js that greets us:

server.js
const http = require("http");
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from Node inside Docker!\n");
});
server.listen(3000, () => {
console.log("Server running on port 3000");
});

Make sure we have a start script in package.json:

package.json
"scripts": {
"start": "node server.js"
}
Why are we using `start` here?

In this example, we use npm start instead of npm run dev.

That helps reinforce an important idea: dev scripts are great while we’re building and testing, but start is often a better fit when we’re containerizing the app to ship it.

At the root of our Node project, create the Dockerfile exactly as discussed:

Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

Right next to it, let’s create our .dockerignore:

.dockerignore
node_modules
.git
.env
npm-debug.log
.DS_Store

Now we tell Docker Engine to read our recipe (Dockerfile) and construct our image.

From the terminal, at the root of the project:

Terminal window
docker build -t node-aboard .
Don't Forget the Dot

The trailing . is not a typo. It is the path to the build context. If you forget it, Docker will error out because it won’t know where to look for the files.

Building the Image

Figure 1: Building the Image

  • docker build: tells the engine to start an image build process.
  • -t node-aboard: “tags” the resulting image with a recognizable name.
  • .: tells Docker to use the current directory (.) as the build context.
Not Running Yet

Wait! What?? Why don’t we see the console log from our app? At this point, we have successfully packaged the image, but it is not running yet. It’s just built. It is sitting in our local Docker registry, ready and waiting for us to run it. Remember the difference between RUN and CMD!

Docker Desktop Built Image

Figure 2: The Docker Desktop Built Image


Docker CLI: build

Our image is ready to roll. Let’s bring it to life as a container.