<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Malleswari</title>
    <description>The latest articles on DEV Community by Malleswari (@malleswari_b).</description>
    <link>https://dev.to/malleswari_b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4083164%2Fa89a4d2a-914a-4722-acf9-af827aa1f5c4.png</url>
      <title>DEV Community: Malleswari</title>
      <link>https://dev.to/malleswari_b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/malleswari_b"/>
    <language>en</language>
    <item>
      <title>Docker for Beginners: What Actually Happens When You Dockerize an Application?</title>
      <dc:creator>Malleswari</dc:creator>
      <pubDate>Wed, 19 Aug 2026 05:19:39 +0000</pubDate>
      <link>https://dev.to/malleswari_b/docker-for-beginners-what-actually-happens-when-you-dockerize-an-application-7mh</link>
      <guid>https://dev.to/malleswari_b/docker-for-beginners-what-actually-happens-when-you-dockerize-an-application-7mh</guid>
      <description>&lt;p&gt;A few days ago, I started learning Docker.&lt;/p&gt;

&lt;p&gt;Like many beginners, I started with the commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build
docker run
docker ps
docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But after seeing a few commands, I realized something.&lt;/p&gt;

&lt;p&gt;I could memorize them.&lt;/p&gt;

&lt;p&gt;But I didn't really understand &lt;strong&gt;what was happening behind them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What exactly is a Docker image?&lt;/p&gt;

&lt;p&gt;What is a container?&lt;/p&gt;

&lt;p&gt;Why do we need a Dockerfile?&lt;/p&gt;

&lt;p&gt;What does &lt;code&gt;docker run&lt;/code&gt; actually do?&lt;/p&gt;

&lt;p&gt;And why does &lt;code&gt;-p 3000:3000&lt;/code&gt; suddenly make my application accessible?&lt;/p&gt;

&lt;p&gt;So instead of learning Docker as a list of commands, I decided to follow one simple application and understand what happens at each step.&lt;/p&gt;

&lt;p&gt;And that's the story I want to share here.&lt;/p&gt;




&lt;h1&gt;
  
  
  It Works on My Machine
&lt;/h1&gt;

&lt;p&gt;Imagine you're working on a Node.js application.&lt;/p&gt;

&lt;p&gt;You clone the project, install the dependencies, and start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything works.&lt;/p&gt;

&lt;p&gt;Your application needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node.js
npm
Dependencies
Application code
Configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then someone else clones the same project.&lt;/p&gt;

&lt;p&gt;They run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It doesn't work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Maybe they have a different Node.js version.&lt;/p&gt;

&lt;p&gt;Maybe a dependency behaves differently.&lt;/p&gt;

&lt;p&gt;Maybe some configuration is missing.&lt;/p&gt;

&lt;p&gt;The code is the same.&lt;/p&gt;

&lt;p&gt;But the environment is different.&lt;/p&gt;

&lt;p&gt;That's where Docker starts becoming interesting.&lt;/p&gt;

&lt;p&gt;Instead of asking every developer or server to manually recreate the environment, we can describe how our application should be packaged.&lt;/p&gt;




&lt;h1&gt;
  
  
  So, What Does Docker Actually Give Us?
&lt;/h1&gt;

&lt;p&gt;At first, Docker looked like a collection of commands to me.&lt;/p&gt;

&lt;p&gt;But the basic idea is actually simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
    +
Dependencies
    +
Required environment
        ↓
    Docker Image
        ↓
    Container
        ↓
Running Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this introduced three words I needed to understand:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile. Image. Container.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's build our way through them.&lt;/p&gt;




&lt;h1&gt;
  
  
  First: How Do We Tell Docker What We Need?
&lt;/h1&gt;

&lt;p&gt;Our application needs Node.js.&lt;/p&gt;

&lt;p&gt;It needs dependencies.&lt;/p&gt;

&lt;p&gt;It needs our source code.&lt;/p&gt;

&lt;p&gt;It needs to know what command to run.&lt;/p&gt;

&lt;p&gt;How do we describe all of that?&lt;/p&gt;

&lt;p&gt;We create a file called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of the Dockerfile as a set of instructions for building our application's environment.&lt;/p&gt;

&lt;p&gt;For our simple Node.js application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:22&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, this looked like a lot of new syntax.&lt;/p&gt;

&lt;p&gt;But once I understood what each line was doing, it became much easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  Reading Our First Dockerfile
&lt;/h1&gt;

&lt;p&gt;Let's go through it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with Node.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:22&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our application needs Node.js.&lt;/p&gt;

&lt;p&gt;Instead of installing Node.js manually, we start from an existing Node.js image.&lt;/p&gt;

&lt;p&gt;So we're saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me an environment that already has Node.js 22.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Create a working directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets &lt;code&gt;/app&lt;/code&gt; as the working directory inside the image.&lt;/p&gt;

&lt;p&gt;Our application will live there.&lt;/p&gt;




&lt;h3&gt;
  
  
  Copy the package files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We copy our package files into the image.&lt;/p&gt;




&lt;h3&gt;
  
  
  Install dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker runs &lt;code&gt;npm install&lt;/code&gt; while building the image.&lt;/p&gt;

&lt;p&gt;That's important:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build
      ↓
RUN npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;RUN&lt;/code&gt; happens during the &lt;strong&gt;image build&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Copy our application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we copy the rest of our source code into the image.&lt;/p&gt;




&lt;h3&gt;
  
  
  Tell Docker about the application port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our Node.js application listens on port &lt;code&gt;3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This tells Docker that the application uses that port inside the container.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; yet make the application accessible from our computer.&lt;/p&gt;

&lt;p&gt;We'll get to that.&lt;/p&gt;




&lt;h3&gt;
  
  
  Tell Docker how to start the application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the container starts, Docker will run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the application can start.&lt;/p&gt;




&lt;h1&gt;
  
  
  We Have Instructions. But We Don't Have an Application Running Yet.
&lt;/h1&gt;

&lt;p&gt;This was one of the first things that confused me.&lt;/p&gt;

&lt;p&gt;We have a Dockerfile.&lt;/p&gt;

&lt;p&gt;But a Dockerfile isn't our running application.&lt;/p&gt;

&lt;p&gt;It's just instructions.&lt;/p&gt;

&lt;p&gt;So we need to use those instructions to create something.&lt;/p&gt;

&lt;p&gt;That's where the &lt;strong&gt;Docker image&lt;/strong&gt; comes in.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building the Image
&lt;/h1&gt;

&lt;p&gt;We run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker reads the Dockerfile and builds an image.&lt;/p&gt;

&lt;p&gt;The flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Dockerfile
                    │
                    │ docker build
                    ↓
                Docker Image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-t my-app&lt;/code&gt; gives our image a name.&lt;/p&gt;

&lt;p&gt;And that final &lt;code&gt;.&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It tells Docker:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the current directory as the build context.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This small &lt;code&gt;.&lt;/code&gt; is easy to overlook when you're starting.&lt;/p&gt;

&lt;p&gt;Now we can check our images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should see our:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we have an image.&lt;/p&gt;

&lt;p&gt;But our application still isn't running.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because an &lt;strong&gt;image isn't a running application&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  From Image to Container
&lt;/h1&gt;

&lt;p&gt;Now we finally use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker uses our image to create a container and starts the application.&lt;/p&gt;

&lt;p&gt;The flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
    ↓
docker build
    ↓
Image
    ↓
docker run
    ↓
Container
    ↓
npm start
    ↓
Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was the mental model that made Docker much easier for me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dockerfile → Image → Container&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A useful analogy is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile = Recipe
Image      = Prepared package / blueprint
Container  = Running instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And one image can create multiple containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              my-app Image
              /     |     \
             ↓      ↓      ↓
        Container Container Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image is the reusable package.&lt;/p&gt;

&lt;p&gt;The containers are the instances created from it.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Application Is Running... So Why Can't I Open It?
&lt;/h1&gt;

&lt;p&gt;Now comes another small surprise.&lt;/p&gt;

&lt;p&gt;Our Node.js application is running inside the container.&lt;/p&gt;

&lt;p&gt;It's listening on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But our browser is outside the container.&lt;/p&gt;

&lt;p&gt;So if I simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can't necessarily access it through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to connect the port on our computer to the port inside the container.&lt;/p&gt;

&lt;p&gt;That's what this does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-p HOST_PORT:CONTAINER_PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-p 3000:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Computer
localhost:3000
       │
       ↓
Container
port 3000
       │
       ↓
Node.js Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello from Docker!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was one of those Docker commands that makes much more sense once you understand &lt;strong&gt;why it exists&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  But What About &lt;code&gt;EXPOSE 3000&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;At first, I also wondered:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If we already wrote &lt;code&gt;EXPOSE 3000&lt;/code&gt;, why do we need &lt;code&gt;-p 3000:3000&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They're different.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The application uses port 3000 inside the container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whereas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Connect port 3000 on my computer to port 3000 inside the container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPOSE
   ↓
Application uses port 3000

-p
   ↓
Connect host port → container port
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction is important when you're starting with Docker.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Actually Happens When We Run &lt;code&gt;docker run&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;When we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker is doing more than simply starting our Node.js application.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Image
     ↓
Create Container
     ↓
Set up container filesystem
     ↓
Set up networking
     ↓
Map port 3000
     ↓
Start container process
     ↓
npm start
     ↓
Application runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't need to understand every internal Docker component yet.&lt;/p&gt;

&lt;p&gt;For now, understanding this flow is enough.&lt;/p&gt;




&lt;h1&gt;
  
  
  Then the Container Stops...
&lt;/h1&gt;

&lt;p&gt;Now imagine the application crashes.&lt;/p&gt;

&lt;p&gt;Or we stop the container.&lt;/p&gt;

&lt;p&gt;We can check running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if the container already stopped?&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs &amp;lt;container-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This became one of the first useful debugging habits for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Something isn't working
        ↓
docker ps -a
        ↓
Find the container
        ↓
docker logs
        ↓
Understand what happened
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe the application crashed.&lt;/p&gt;

&lt;p&gt;Maybe a dependency is missing.&lt;/p&gt;

&lt;p&gt;Maybe an environment variable isn't configured.&lt;/p&gt;

&lt;p&gt;Docker doesn't automatically fix application problems.&lt;/p&gt;

&lt;p&gt;It gives us a consistent environment to run the application.&lt;/p&gt;




&lt;h1&gt;
  
  
  One More Thing I Learned: Docker Images Have Layers
&lt;/h1&gt;

&lt;p&gt;Look at these lines again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why do we copy the package files separately?&lt;/p&gt;

&lt;p&gt;One reason is Docker's image layering and build cache.&lt;/p&gt;

&lt;p&gt;Docker builds images in layers.&lt;/p&gt;

&lt;p&gt;If we change our source code but don't change &lt;code&gt;package.json&lt;/code&gt;, Docker may be able to reuse the layer where the dependencies were installed.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Package files
      ↓
Install dependencies
      ↓
Application source
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the next build doesn't necessarily have to redo everything from scratch.&lt;/p&gt;

&lt;p&gt;This becomes increasingly useful as applications become larger.&lt;/p&gt;




&lt;h1&gt;
  
  
  And There Is a Small File Called &lt;code&gt;.dockerignore&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Our project might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
.git
.env
coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't necessarily want all of those sent as part of the Docker build context.&lt;/p&gt;

&lt;p&gt;So we can create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
.git
.env
coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a small thing, but it's useful to know early.&lt;/p&gt;




&lt;h1&gt;
  
  
  So What Have We Actually Learned?
&lt;/h1&gt;

&lt;p&gt;Let's stop for a moment.&lt;/p&gt;

&lt;p&gt;We started with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It works on my machine."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then we needed a consistent way to describe our application's environment.&lt;/p&gt;

&lt;p&gt;That led us to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used the Dockerfile to create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used the image to create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container runs our application.&lt;/p&gt;

&lt;p&gt;Then we needed our browser to reach the application.&lt;/p&gt;

&lt;p&gt;That introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Port Mapping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we needed to understand what happened when something went wrong.&lt;/p&gt;

&lt;p&gt;That introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
docker ps -a
docker logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we learned that images are built in layers and can use caching.&lt;/p&gt;

&lt;p&gt;So our journey currently looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"It works on my machine."
          ↓
Need a consistent environment
          ↓
      Dockerfile
          ↓
      docker build
          ↓
        Image
          ↓
      docker run
          ↓
      Container
          ↓
    Port Mapping
          ↓
Running Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is already enough to understand the &lt;strong&gt;core Docker workflow&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  But Our Application Will Eventually Grow
&lt;/h1&gt;

&lt;p&gt;Right now, we're running a simple Node.js application.&lt;/p&gt;

&lt;p&gt;Real applications are rarely this simple.&lt;/p&gt;

&lt;p&gt;Eventually, our application might need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Backend
Database
Cache
Other Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's where Docker introduces more concepts.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Our application needs persistent data
&lt;/h3&gt;

&lt;p&gt;We'll need to understand &lt;strong&gt;Docker Volumes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple containers need to communicate
&lt;/h3&gt;

&lt;p&gt;We'll need to understand &lt;strong&gt;Docker Networking&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  We have multiple containers to manage
&lt;/h3&gt;

&lt;p&gt;We'll need to understand &lt;strong&gt;Docker Compose&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  We want to build smaller production images
&lt;/h3&gt;

&lt;p&gt;We'll need to understand &lt;strong&gt;Multi-stage Builds&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  We want automated deployments
&lt;/h3&gt;

&lt;p&gt;We'll need to understand &lt;strong&gt;Docker + CI/CD&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But I don't think we need to learn all of these at once.&lt;/p&gt;

&lt;p&gt;For me, the important first step was understanding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How does my application become an image, and how does that image become a running container?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Where Does the Image Go When We Want to Share It?
&lt;/h1&gt;

&lt;p&gt;Our image currently exists on our computer.&lt;/p&gt;

&lt;p&gt;But imagine we want to deploy the application somewhere else.&lt;/p&gt;

&lt;p&gt;We don't want to manually rebuild the image on every machine.&lt;/p&gt;

&lt;p&gt;Instead, we can store the image in a &lt;strong&gt;container registry&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My Computer
     ↓
Docker Image
     ↓
   push
     ↓
Container Registry
     ↓
    pull
     ↓
Another Environment
     ↓
Docker Image
     ↓
Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, Docker Hub is a container registry.&lt;/p&gt;

&lt;p&gt;We can download an existing image using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So images can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Built locally
     OR
Pulled from a registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either way, we eventually use the image to create a container.&lt;/p&gt;




&lt;h1&gt;
  
  
  And This Is Where Docker Connects to Deployment
&lt;/h1&gt;

&lt;p&gt;Now the whole idea starts to make sense.&lt;/p&gt;

&lt;p&gt;We have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
    ↓
Dockerfile
    ↓
Docker Image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That image can be stored in a registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Image
    ↓
Container Registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a server or cloud platform can use that image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container Registry
        ↓
   Docker Image
        ↓
     Container
        ↓
    Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a simplified real-world workflow looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
    ↓
Code
    ↓
Dockerfile
    ↓
Docker Image
    ↓
Container Registry
    ↓
Production Environment
    ↓
Container
    ↓
Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the reasons Docker is so useful in modern development and deployment workflows.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Mental Model I Finally Have
&lt;/h1&gt;

&lt;p&gt;After going through this example, Docker doesn't feel like a list of random commands anymore.&lt;/p&gt;

&lt;p&gt;I can now think about it as a journey:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Application
                      │
                      ↓
                 Dockerfile
                      │
                 docker build
                      ↓
                 Docker Image
                      │
                  docker run
                      ↓
                Docker Container
                      │
                      ↓
                 Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when I need to share it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Image
     ↓
docker push
     ↓
Container Registry
     ↓
docker pull
     ↓
Docker Image
     ↓
Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the foundation.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I'm Learning Next
&lt;/h1&gt;

&lt;p&gt;I'm intentionally stopping here.&lt;/p&gt;

&lt;p&gt;I haven't learned every Docker concept yet, and I don't think beginners need to learn everything in one sitting.&lt;/p&gt;

&lt;p&gt;My next topics are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Volumes
       ↓
Docker Networking
       ↓
Docker Compose
       ↓
Multi-stage Builds
       ↓
Docker Security
       ↓
CI/CD with Docker
       ↓
Cloud Deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of those solves a different problem that appears as our application becomes more complex.&lt;/p&gt;

&lt;p&gt;And that's probably the biggest thing I learned from starting Docker:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't just memorize the command. Understand why the command exists.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the reason is clear, the command becomes much easier to remember.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Takeaway
&lt;/h1&gt;

&lt;p&gt;If you're just starting Docker, don't worry about memorizing everything.&lt;/p&gt;

&lt;p&gt;Start with these three relationships:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
    ↓
   Image
    ↓
Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And understand what happens around them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
    ↓
docker build
    ↓
Image
    ↓
docker run
    ↓
Container
    ↓
Port Mapping
    ↓
Running Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's where I would start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker becomes much easier when you stop looking at it as a collection of commands and start seeing it as a journey your application goes through.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>docker</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
