I don’t know why, but Docker seems confusing for me, that’s why I started learning some more about it. As a senior frontend engineer, I don’t like being at the hand of the senior backend so this is what I learned so far:
Let’s say I want to create a simple Nodejs app. My project is located in “D:/Projects/docker-tutorial”
Create an
app/index.js
for the Nodejs app.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World from node');
});
app.listen(8080, () => {
console.log('Server is running on port 8080 ');
});
Next create a
package.json
{
"name": "docker-tuts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.21.1"
}
}
What I want to do is take this small app, copy it somewhere, install the dependencies and run it. For this, I will use Docker.
Create a file called
dockerfile
FROM node:22-alpine
WORKDIR /home/node/app
COPY package*.json ./
RUN npm install
COPY app/ .
CMD ["node", "index.js"]
This is the “recipe” for your containers. This will create an image.
The image is the recipe. The image represents the instructions to build the containers.
The containers are the dishes. The containers contain the logic and node_modules
.
First let’s explain what is happening:
Step 1: Specify the Base Image
FROM node:22-alpine
We start from the official Node.js image based on Alpine Linux for a lightweight container.
Step 2: Set the Working Directory
WORKDIR /home/node/app
This sets the working directory inside the container where all subsequent commands will be executed and where your logic and node_modules will stay.
Step 3: Copy the package.json
COPY package*.json ./
This copies package.json
and package-lock.json
(if it exists) into the working directory.
Step 4: Install Dependencies
RUN npm install
Installs the dependencies specified in package.json
inside the working directory.
Step 5: Copy Application Code
COPY app/ .
Copies your application code app/index.js
into the container /home/node/app/
.
Step 6: Specify the Command to Run the App
CMD ["node", "index.js"]
Defines the command to start your application when the container starts.
The behavior of the COPY
command depends on whether you include a trailing slash:
With trailing slash
COPY app/ ./destination/
: Copies the contents of theapp
directory into a new directory calleddestination
, inside the container resulting in/home/node/app/destination/index.js
.# Result in container: # /home/node/app/destination/ # └── index.js
Without trailing slash
COPY app ./destination/
: Copies the entireapp
directory into/home/node/app/destination/
, resulting in/home/node/app/destination/app/index.js
.# Result in container: # /home/node/app/destination/ # └── app/ # └── index.js
Using just . or ./ for the destination
COPY app/ .
: Copies the contents of theapp
directory into the current directory inside the container (/home/node/app/
), soindex.js
ends up directly inside/home/node/app/
.# Result in container: # /home/node/app/ # └── index.js
In the console you create the image
In “D:/Projects/docker-tutorial”
you can run
docker build . -t myNodeImg
This will build the image inside docker and this image will contain the instructions
-t myNodeImg
- will give the name of the imagenotice the
.
- this is the directory where thedockerfile
exists
Then you can create a container (or multiple) with
docker run --name myNodeContainer1 -p 80:8080 -d myNodeImg
This will create a named container named
myNodeContainer1
it will link the port (
-p
) from your computer to the port inside the container, where-p <host_port>:<container_port>
. In this case,-p 80:8080
maps port80
on your computer (host) to port8080
inside the container.it will not block your terminal, by being detached from it (
-d
)it will know to create the container from the image
myNodeImg
Now when you go to the browser on localhost:80 you should see the message “Hello World from node”.
That’s it for now but stay tuned for more.