DEV Community

Madhav Nakra
Madhav Nakra

Posted on

From Dockerfile to Docker Hub: A Complete Beginner's Guide to Docker šŸš€

Containerization has become a fundamental skill for DevOps Engineers, Cloud Engineers, and Software Developers.

However, many beginners learn Docker commands without understanding the complete workflow behind them.

Questions like:

  • What exactly is a Docker Image?
  • How does a Dockerfile become a running Container?
  • Why do we push images to Docker Hub?
  • How do organizations deploy the same application everywhere?

are common when starting out.

In this blog, we'll build a simple Node.js application, containerize it using Docker, run it locally, and finally push the image to Docker Hub.

By the end of this guide, you'll understand the complete Docker workflow used in real-world DevOps environments.


Docker Workflow Overview

flowchart LR
    A[Application Code] --> B[Dockerfile]
    B --> C[Docker Build]
    C --> D[Docker Image]
    D --> E[Docker Run]
    E --> F[Docker Container]
    D --> G[Docker Push]
    G --> H[Docker Hub]
Enter fullscreen mode Exit fullscreen mode

This is the same workflow followed by developers and DevOps teams worldwide.


What Are We Building?

We'll create a simple Node.js application that returns:

  • A welcome message
  • Environment information
  • Container hostname

This helps us verify that our application is actually running inside a Docker container.


Project Structure

.
ā”œā”€ā”€ Dockerfile
ā”œā”€ā”€ app.js
└── package.json
Enter fullscreen mode Exit fullscreen mode

Step 1: Create the Node.js Application

app.js

const express = require("express");
const app = express();

const PORT = process.env.PORT || 3000;
const ENV = process.env.ENV_VALUE || "No env set";
const HOSTNAME = process.env.HOSTNAME || require("os").hostname();

app.get("/", (req, res) => {
  res.json({
    message: "Hello from Simple App (Node)",
    env: ENV,
    container: HOSTNAME
  });
});

app.listen(PORT, () =>
  console.log(`Node Hello listening on ${PORT}`)
);
Enter fullscreen mode Exit fullscreen mode

package.json

{
  "name": "hello-app-node",
  "version": "1.0.0",
  "main": "app.js",
  "dependencies": {
    "express": "^5.2.1"
  }
}
Enter fullscreen mode Exit fullscreen mode

Application Architecture

flowchart LR
    User --> Browser
    Browser --> Container
    Container --> NodeJS
    NodeJS --> JSONResponse
Enter fullscreen mode Exit fullscreen mode

Whenever a user accesses the application, the request reaches the containerized Node.js application, which returns a JSON response.


Step 2: Create the Dockerfile

A Dockerfile is simply a blueprint that tells Docker how to build an image.

FROM node:24-slim

WORKDIR /app

COPY package*.json ./

RUN npm install --production

COPY . .

EXPOSE 3000

CMD ["node", "app.js"]
Enter fullscreen mode Exit fullscreen mode

Understanding the Dockerfile

Base Image

FROM node:24-slim
Enter fullscreen mode Exit fullscreen mode

We start with an official lightweight Node.js image from Docker Hub.


Working Directory

WORKDIR /app
Enter fullscreen mode Exit fullscreen mode

Creates and switches to the /app directory inside the container.


Copy Dependency Files

COPY package*.json ./
Enter fullscreen mode Exit fullscreen mode

Copies package files first.

This is considered a Docker best practice because Docker can cache dependency layers and speed up future builds.


Install Dependencies

RUN npm install --production
Enter fullscreen mode Exit fullscreen mode

Installs only production dependencies.


Copy Application Source Code

COPY . .
Enter fullscreen mode Exit fullscreen mode

Copies the entire project into the container.


Expose Application Port

EXPOSE 3000
Enter fullscreen mode Exit fullscreen mode

Documents that the application listens on port 3000.


Start the Application

CMD ["node", "app.js"]
Enter fullscreen mode Exit fullscreen mode

Runs the Node.js application when the container starts.


What Happens During Docker Build?

flowchart TD
    A[Dockerfile]
    --> B[Pull Node Base Image]
    --> C[Create Working Directory]
    --> D[Copy package.json]
    --> E[Install Dependencies]
    --> F[Copy Application Code]
    --> G[Create Image Layers]
    --> H[Docker Image Ready]
Enter fullscreen mode Exit fullscreen mode

Docker executes each instruction sequentially and creates image layers.


Step 3: Build the Docker Image

Run:

docker build -t madhavnaks/node-app .
Enter fullscreen mode Exit fullscreen mode

Let's understand this command:

docker build
Enter fullscreen mode Exit fullscreen mode

Builds an image from a Dockerfile.

-t
Enter fullscreen mode Exit fullscreen mode

Assigns a tag to the image.

madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

Image name.

.
Enter fullscreen mode Exit fullscreen mode

Current directory containing the Dockerfile.


After a successful build you'll see output similar to:

=> naming to docker.io/madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

Docker has now created an image locally on your machine.


Step 4: Verify the Image

To see locally available images:

docker images
Enter fullscreen mode Exit fullscreen mode

Example output:

REPOSITORY                TAG       IMAGE ID       SIZE
madhavnaks/node-app       latest    42c936686000   234MB
Enter fullscreen mode Exit fullscreen mode

At this point, the image exists but is not running.


Docker Image vs Docker Container

Many beginners confuse these two concepts.

Think of it like this:

  • Docker Image = Blueprint
  • Docker Container = Running Application
flowchart LR
    A[Docker Image]
    --> B[Container 1]

    A --> C[Container 2]

    A --> D[Container 3]
Enter fullscreen mode Exit fullscreen mode

A single image can create multiple containers.


Step 5: Run a Container

Now let's start our application.

docker run -d --name node-app -p 3001:3000 madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

Understanding the Command

Detached Mode

-d
Enter fullscreen mode Exit fullscreen mode

Runs the container in the background.


Container Name

--name node-app
Enter fullscreen mode Exit fullscreen mode

Assigns a friendly name to the container.


Port Mapping

-p 3001:3000
Enter fullscreen mode Exit fullscreen mode

Maps:

Host Port      → Container Port
3001           → 3000
Enter fullscreen mode Exit fullscreen mode

The application listens on port 3000 inside the container but is accessible on port 3001 from your machine.


Step 6: Verify the Container

Check running containers:

docker ps
Enter fullscreen mode Exit fullscreen mode

Expected output:

CONTAINER ID   IMAGE                 STATUS
10265698c978   madhavnaks/node-app   Up
Enter fullscreen mode Exit fullscreen mode

Step 7: Access the Application

Open:

http://localhost:3001
Enter fullscreen mode Exit fullscreen mode

Expected response:

{
  "message": "Hello from Simple App (Node)",
  "env": "No env set",
  "container": "10265698c978"
}
Enter fullscreen mode Exit fullscreen mode

Notice the hostname.

The hostname corresponds to the container ID, proving the application is running inside Docker.


Step 8: Login to Docker Hub

Before pushing images, authenticate with Docker Hub.

docker login
Enter fullscreen mode Exit fullscreen mode

Example:

Login Succeeded
Enter fullscreen mode Exit fullscreen mode

Docker is now authorized to push images to your repository.


Why Push Images to Docker Hub?

Docker Hub acts as a centralized registry.

flowchart LR
    A[Developer Machine]
    -->|Push| B[Docker Hub]

    B -->|Pull| C[Server]

    B -->|Pull| D[Kubernetes Cluster]
Enter fullscreen mode Exit fullscreen mode

Once an image is pushed, it can be pulled and run from anywhere.


Step 9: Push the Image

Push the image to Docker Hub:

docker push madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

Example output:

latest: digest: sha256:d1081ec542f521e100bd886943c13ab7568c663b56e36200e6d846163975f979
Enter fullscreen mode Exit fullscreen mode

This confirms that the image has been successfully uploaded.


Step 10: Verify on Docker Hub

Visit your Docker Hub account.

You should now see:

madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

listed under repositories.

You can even share the image with others.

Anyone can now run:

docker pull madhavnaks/node-app

docker run -p 3001:3000 madhavnaks/node-app
Enter fullscreen mode Exit fullscreen mode

without needing your source code.


Real-World DevOps Workflow

In production environments, the workflow usually looks like this:

flowchart LR
    A[Developer Writes Code]
    --> B[GitHub]

    B --> C[CI/CD Pipeline]

    C --> D[Docker Build]

    D --> E[Docker Hub]

    E --> F[Kubernetes Cluster]
Enter fullscreen mode Exit fullscreen mode

This is exactly how modern DevOps teams package and deploy applications.


Key Takeaways

āœ… Dockerfile defines how an image should be built

āœ… Docker Build creates an image

āœ… Docker Run creates a container

āœ… Docker Hub stores and distributes images

āœ… One image can create multiple containers

āœ… Containerization ensures consistency across environments


Conclusion

In this guide, we covered the complete Docker workflow from source code to Docker Hub.

We learned how to:

  • Create a Dockerfile
  • Build a Docker image
  • Run a container
  • Verify application execution
  • Push images to Docker Hub
  • Understand how images move through real-world DevOps pipelines

Mastering these Docker fundamentals is the first step toward advanced topics like Docker Compose, Kubernetes, Helm, CI/CD pipelines, and cloud-native deployments.

If you're learning DevOps, try containerizing applications in different languages such as Python, Java, Go, or .NET to strengthen your understanding of Docker.

Happy Containerizing! šŸš€

Top comments (1)

Collapse
 
ridhima_51713c28bb40621e0 profile image
Ridhima

Letsgoo