Docker - Interactive Terminal
root@linux-server:~# Welcome to the interactive Docker tutorial
Welcome to the interactive Docker containerization tutorial!

Docker is a containerization tool that allows you to test and fast deploy applications without worrying about the underlying architecture of CPU, or what operating system is running. It isolates itself from pretty much everything and only includes the bare bones needed to run your dedicated application.

Today, we’ll learn how to containerize your own application using Docker!

For this tutorial, we'll containerize a Node.js backend application for a todo app. Let's start by examining our application structure.
ls -la
total 48 drwxr-xr-x 10 user user 320 Dec 4 10:30 . drwxr-xr-x 3 user user 96 Dec 4 10:29 .. drwxr-xr-x 3 user user 96 Dec 4 10:30 Controllers drwxr-xr-x 3 user user 96 Dec 4 10:30 Database drwxr-xr-x 3 user user 96 Dec 4 10:30 Middleware drwxr-xr-x 3 user user 96 Dec 4 10:30 Models drwxr-xr-x 3 user user 96 Dec 4 10:30 Services drwxr-xr-x 3 user user 96 Dec 4 10:30 Utility -rw-r--r-- 1 user user 847 Dec 4 10:30 package.json drwxr-xr-x 150 user user 4800 Dec 4 10:30 node_modules -rw-r--r-- 1 user user 1234 Dec 4 10:30 index.js
Perfect! We have a Node.js application with all the necessary components. Now let's check our package.json to understand the application dependencies.
cat package.json
{ "name": "todo-backend", "version": "1.0.0", "description": "Backend API for Todo application", "main": "index.js", "scripts": { "start": "node index.js", "dev": "nodemon index.js" }, "dependencies": { "express": "^4.18.2", "cors": "^2.8.5", "dotenv": "^16.3.1" }, "devDependencies": { "nodemon": "^3.0.1" } }
Great! Now we need to create a Dockerfile. This is the blueprint that tells Docker how to build our container image. Let's create it step by step.
touch Dockerfile
Now let's add the Dockerfile content. We'll build it step by step to understand each instruction.
cat > Dockerfile << 'EOF'
# Use Node.js 20 as base image FROM node:20

Set working directory inside container

WORKDIR /app

Copy package files and install dependencies

COPY package*.json ./ RUN npm install

Copy source code

COPY . .

Expose the port your app runs on

EXPOSE 3000

Command to run the server

CMD [“node”, “index.js”] EOF

Let's examine our Dockerfile to understand each instruction:

• FROM node:20 - Uses Node.js version 20 as the base image (includes Linux + Node.js + npm) • WORKDIR /app - Sets the working directory inside the container • COPY package*.json ./ - Copies package files first (for better caching) • RUN npm install - Installs dependencies • COPY . . - Copies all source code • EXPOSE 3000 - Documents which port the app uses • CMD - Defines the command to start the application

cat Dockerfile
# Use Node.js 20 as base image FROM node:20

Set working directory inside container

WORKDIR /app

Copy package files and install dependencies

COPY package*.json ./ RUN npm install

Copy source code

COPY . .

Expose the port your app runs on

EXPOSE 3000

Command to run the server

CMD [“node”, “index.js”]

Perfect! Now let's build our Docker image. The -t flag tags our image with a name for easy reference.
docker build -t todo-backend .
[+] Building 23.4s (10/10) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 285B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/node:20 2.1s => [1/5] FROM docker.io/library/node:20@sha256:abc123... 8.3s => [internal] load build context 0.1s => => transferring context: 12.45kB 0.1s => [2/5] WORKDIR /app 0.2s => [3/5] COPY package*.json ./ 0.1s => [4/5] RUN npm install 11.2s => [5/5] COPY . . 0.2s => exporting to image 1.2s => => exporting layers 1.2s => => writing image sha256:def456... 0.0s => => naming to docker.io/library/todo-backend 0.0s
Excellent! Our Docker image has been built successfully. Let's verify it exists in our local Docker registry.
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE todo-backend latest def456789abc 2 minutes ago 1.1GB node 20 abc123456def 3 days ago 1.09GB
Great! Now let's run our containerized application. The -p flag maps port 3000 from the container to port 3000 on our host machine.
docker run -p 3000:3000 todo-backend
Server starting... ✅ Database connected successfully ✅ CORS middleware configured ✅ Routes loaded 🚀 Todo Backend API running on port 3000 📡 Ready to accept requests at http://localhost:3000
Perfect! Our application is now running inside a Docker container. Let's test it in another terminal to make sure it's working properly.
curl http://localhost:3000/health
{ "status": "healthy", "timestamp": "2023-12-04T10:45:23.123Z", "uptime": "00:02:15", "service": "todo-backend" }
Excellent! Our containerized application is working perfectly. Let's also run it in detached mode so it runs in the background.
docker run -d -p 3001:3000 --name todo-app todo-backend
a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
Great! The container is now running in the background. Let's check the running containers.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a1b2c3d4e5f6 todo-backend "docker-entrypoint.s…" 30 seconds ago Up 29 seconds 0.0.0.0:3001->3000/tcp todo-app
Perfect! You've successfully containerized your Node.js application with Docker.

Key takeaways: ✅ Docker isolates applications in lightweight containers ✅ Dockerfile defines how to build your container image ✅ Layer caching optimizes build times (copy package.json first) ✅ Port mapping connects container ports to host ports ✅ Containers can run in foreground or background (detached mode)

Your application is now portable and can run consistently across any environment that supports Docker!