Docker Images in Real Life: Build, Run, Pull, and Push (Hands‑On, End‑to‑End)

Most Docker confusion starts here:

“I ran a container… but where did it come from?”

The answer is Docker images.

If you don’t deeply understand images, Docker will always feel half‑clear.

This post explains Docker images end‑to‑end, using real commands, exactly how images are built, shared, and used in real projects.


Mental Model First (Very Important)

Container ≠ Image

  • Image → blueprint (read‑only)
  • Container → running instance of an image

You build images.
You run containers.

Everything else in Docker revolves around this.


Step 1: Pull an Image (What docker pull Really Does)

Let’s start clean.

docker pull nginx

What actually happened?

Docker:

  1. Contacted Docker Hub (default registry)
  2. Downloaded image layers
  3. Stored them locally

Verify:

docker images

You’ll see something like:

REPOSITORY   TAG     IMAGE ID     SIZE
nginx        latest  abc123       180MB

✅ You now have an image
❌ No container yet


Step 2: Run the Image (Image → Container)

docker run -d -p 8080:80 nginx

What Docker did internally:

  1. Took the nginx image
  2. Created a container layer on top
  3. Started the main process (nginx)
  4. Attached networking

Check:

docker ps

This is the same image, but a new container.

Step 3: Images Are Immutable (This Changes Everything)

Try this:

docker exec -it <container_id> /bin/sh

Inside container:

echo "hello" > /test.txt
exit

Remove container:

docker rm -f <container_id>

Run again:

docker run -it nginx /bin/sh
cat /test.txt

❌ File is gone.

Why?

Because:

  • Image = read‑only
  • Container layer = disposable

✅ Images do not change
✅ Containers are temporary

This is intentional design, not a bug.


Step 4: Build Your Own Image (The Real Docker Skill)

Now let’s stop using other people’s images.

Create a simple app

mkdir myapp
cd myapp

Create index.html:

<h1>Hello from InfraDecode</h1>

Create Dockerfile (no extension):

FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html

Build the image

docker build -t infradecode-nginx .

Breakdown:

  • docker build → build image
  • -t → tag (name)
  • . → current directory as build context

Verify:

docker images

✅ You created your own image

Step 5: Run Your Custom Image

docker run -d -p 8080:80 infradecode-nginx

Open browser:

http://localhost:8080

✅ This container is running your image, not nginx’s default one.


Step 6: Image Layers (Why Docker Is Fast)

Run:

docker history infradecode-nginx

You’ll see:

  • base image layers
  • your COPY layer

Key idea: ✅ Docker caches layers
✅ Only changed layers rebuild

This is why Docker builds are fast when done correctly.


Step 7: Tag the Image (Before Pushing)

Docker registries require a namespace.

Format:

registry_name/<image>:<tag>

Example:

docker tag infradecode-nginx infra/infradecode-nginx:v1

Verify:

docker images

Same image ID — different name.

Step 8: Push Image to Docker Hub (Real Sharing)

Login first:

docker login

Push:

docker push infra/infradecode-nginx:v1

What happened:

  • Docker uploaded layers
  • Registry now stores your image

✅ Anyone with access can now pull this image
✅ This is how CI/CD and production work


Step 9: Pull and Run Anywhere (The Real Power)

On any machine with Docker:

docker pull infra/infradecode-nginx:v1
docker run -d -p 8080:80 infra/infradecode-nginx:v1

Same app.
Same behavior.
Different machine.

This is Docker’s real value.


Step 10: Real‑World Flow (How Teams Actually Use Docker)

This is the actual lifecycle:

Code → Dockerfile → docker build
     → docker push (registry)
     → docker pull (server)
     → docker run

Developers:

  • build locally
  • push images

Servers:

  • pull images
  • run containers

No SCP.
No “works on my machine”.


Common Beginner Mistakes (That Cause Pain)

❌ Editing inside containers
❌ Expecting containers to persist changes
❌ Not tagging images properly
❌ Using latest everywhere
❌ Building images without understanding layers

Docker is simple — but strict.


InfraDecode Takeaway

Docker images are the contract.
Containers are just temporary executions of that contract.

Once you respect that boundary, Docker becomes predictable, scalable, and boring — in the best way.

— InfraDecode


Discover more from

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top