Herold
Solutions
Blog
Preview for Dockerfile simplified

Dockerfile simplified

A step-by-step guide to build a Dockerfile.

September 17, 20247 min read

Docker will save you time and reduce errors when setting up your own IT infrastructure on a VM. Deploying containers on any system is easy, and Docker makes it happen. To create a Docker container, you must have a Dockerfile. This file describes how the image is structured and contains all the steps needed to create a finished image. A Dockerfile is like a small VM that works on its own. You only need to remember a few keywords to create your own Docker images. We will build a simple Dockerfile to run a Node.js script on the command line.

Setup

First, we need to set up our environment so that we have a sample application that we want to convert into a Docker image. To do that, we'll initialize an npm workspace by running npm init and initializing a new project. To get a good overview of all the different keywords you'll find in a Dockerfile, let's install the axios dependency in our package.json with npm install --save axios and create an index.js that looks like this:

// index.js
const axios = require("axios");

(async function () {
    const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
    console.log("Request status:", response.status);
    console.log("Post count:", response.data.length);
})().catch((error) => {
    console.error(error);
});

This NodeJS file is going to send an Axios request to the JSONplaceholder API. Then, we'll display the status of the request and how many elements we've received from the API. To test this, just run the command node index.js in a command line. You should then get the following output:

$ node index.js
Request status: 200
Post count: 100

Next, we'll run this script via Docker and create a Docker image from it. The first step is to create a Dockerfile. Below, we'll go through the individual keywords step by step that we need to create our Docker image.

FROM - the base image

The FROM keyword lets you choose which Docker image you want to use as the basis for your images. You can use a simple Linux like Debian as the basis, or you can use an image that's already been prepared and has the required dependencies installed. To find a suitable image, you can search for images on the Docker Hub page. We need Node.js as a dependency, so we're going to use the Node.js image as a base. To do that, we just need to add the following instruction to our Dockerfile:

# use node 20 as base image
FROM node:20

workdir - the apps space

Next, we use the WORKDIR keyword to set a directory where our app can be stored and run. The WORKDIR command will automatically create the directory and switch to it.

# [...]

# create and switch to a working directory for the app
WORKDIR /app

COPY - insert the project

Next, we need to add our project files to the Docker image. We can use the COPY instruction for this. The first path tells the system which path we want to copy from our project directory, and the second path tells it where in the image we want the files to go. In our case, we want to copy all the files from our project directory. Since we're already in our working directory in the image thanks to WORKDIR, we want to copy them directly into that directory:

# [...]

# copy project files into workdir of image
COPY . .

RUN - setup your environment

Once we've copied our project files, we need to install the dependencies our application needs. In our case, we added axios from our package.json. To add this to the image, we can use the RUN instruction to run any setup commands. In our case, the only setup needed is a simple npm install:

# [...]

# install required dependencies
RUN npm install

CMD - executable on run

Finally, the most important command in the Dockerfile is missing. With the CMD instruction, we can specify what exactly we want to happen when the image is launched. In our case, we want to run our index.js with node, so we add the following line:

# [...]

# start the nodejs file
CMD [ "node", "index.js" ]

All together

If you put all the parts together in one file, it will look like this:

# use node 20 as base image
FROM node:20

# create and switch to a working directory for the app
WORKDIR /app

# copy project files into workdir of image
COPY . .

# install required dependencies
RUN npm install

# start the nodejs file
CMD [ "node", "index.js" ]

Build the image

Now that we have a finished dockerfile, we need to create this dockerfile as an image. To do this, we can run a very simple command:

docker build . -t testimage

With this command, we build the Dockerfile in the current directory and create it with a tag named testimage. This tag is also the name that can be used later to run the docker image. After the command is executed, you can see on the command line how all the commands we added to our docker file are executed one by one.

Execute docker image

Now that we have created the docker image, we can test to see if it works properly. To do this, we can run the following command:

docker run testimage

If everything works as it should, we will see the same output we saw when printing the script directly:

$ docker run testimage
Request status: 200
Post count: 100

Conclusion

In summary, these 5 commands are all you need to create your own Docker containers. Of course, there are other keywords for specific purposes, which you can see in the official dockerfile reference. And you can also tweak the dockerfile to create a dockerfile that is as small as possible, but for general docker image creation you can do almost anything with these 5 commands.

The next topics to consider when building a web server in a Docker image, for example, are port mapping to exposing the server to the outside world and volume mapping to avoid losing written files. However, these topics are less related to building Docker images and more related to launching Docker images with advanced parameters.

If you have any questions about this or any other topic, please feel free to contact me and I will be happy to help you with your first steps with Docker or other topics.

Selfie of Felix Herold

The article was helpful, or are you feeling a bit unsure about anything?