Skip to main content

Command Palette

Search for a command to run...

Docker Life cycle - Intro

Updated
12 min read
Docker Life cycle - Intro
R

✨🌟💫Threat Hunter 💫🌟✨

Docker Workflow

Docker follows a predictable lifecycle. Each step helps move an application from development to execution in a consistent manner.

1. Create

Build the Docker image using a Dockerfile.

Packages code, dependencies, runtime, and configs into an immutable artifact.

docker build -t myapp:v1 .

2. Store

Push the built image to a container registry such as Docker Hub, GCR, ECR or a private registry.

docker push myapp:v1

Central storage ensures consistent versions across environments.

example : hub.docker.com

3. Pull / Download

Retrieve the image from the registry before running it.

docker pull myapp:v1

Ensures the executed container matches the stored version.

4. Run

Start the container using the image.

Runs your application in an isolated and lightweight environment.

docker run myapp:v1

5. Destroy

Stop and remove the container once the job completes or a new version is deployed.

docker rm -f <container_id>

docker rmi

Docker Components

Understanding Docker requires clarity on four core building blocks. These components describe how applications are packaged, stored, shared and run in isolated environments.


1. Image

An image is a compressed, read-only template. It contains everything needed to create a container including base OS filesystem layers, dependencies, configuration and the application code.

It acts as the blueprint for the container.

You never “run” an image directly, you instantiate it into a container.


2. Container

A container is a running instance of an image.

It provides isolation using Linux namespaces and cgroups.

Containers remain lightweight because they share the host kernel.

Containers are ephemeral. You can start, stop or destroy them without affecting the underlying image.

Example command

docker run -it ubuntu:latest bash

3. Registry

A registry is a central location where Docker images are pushed and retrieved.

It can be public (Docker Hub) or private (GCR, ECR, Harbor).

Registries enable consistent distribution across teams and environments.

Push and pull examples

docker push myapp:v1
docker pull myapp:v1

4. Repository

A repository groups all versions (tags) of a specific image inside a registry.

For example:

ubuntu:18.04, ubuntu:20.04, ubuntu:22.04 are tags under the ubuntu repository.

This helps maintain structured versioning and rollback capability.


Mermaid Diagram: Docker Components Overview

This diagram represents the lifecycle:

  • Developers build an image

  • The image is stored as versions in a repository

  • The repository lives inside a registry

  • When needed, the image is pulled and converted into a container


Summary Table

ComponentPurposeExample
ImageBlueprint to create containersubuntu:20.04
ContainerRuntime instance of an imageRunning web server
RepositoryStores image versionsubuntu, nginx
RegistryRemote image storeDocker Hub, ECR

Docker Images

A Docker image is a blueprint that defines everything required to create a container.

A container is simply the running instance of that image.

Images are read-only templates that bundle:

  • Base operating system layers

  • Application code

  • Dependencies and libraries

  • Configuration and metadata

  • Entrypoint or commands to run the application

Images ensure applications behave the same across all environments.


How Images Are Created

Images are defined using a Dockerfile, which contains step-by-step instructions such as:

  • Selecting a base image

  • Setting environment variables

  • Configuring the working directory

  • Copying application source code

  • Installing dependencies

  • Exposing ports

  • Defining the entrypoint or command

Example Build Command

docker build --tag django.nv .

This command:

  • Reads the Dockerfile in the current directory

  • Builds an image

  • Tags it as django.nv


Core Elements in a Dockerfile

  • Base Images Starting point for your application such as ubuntu, python:3.11, alpine.

  • Port Binding Declares which ports the container exposes.

  • Entrypoint Defines the main executable that always runs.

  • Command (CMD) Default arguments supplied to the entrypoint.

  • Volumes Declares persistent or shared directories.

  • User Sets the user inside the container for security.

  • Working Directory Defines where commands will run inside the container.

  • Environment Variables Supplies runtime configuration.

  • Copy Instructions Moves application code or files into the image.


Sample Dockerfile

FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Copy requirement file
COPY requirements.txt .

# Install dependencies
RUN pip install -r requirements.txt

# Copy application
COPY . .

# Set environment variables
ENV APP_ENV=production

# Expose app port
EXPOSE 8000

# Default command
CMD ["python", "app.py"]

Mermaid Diagram: Docker Image Creation Flow


Create Docker image

To create a Docker image named django.nv with version 1.0, you run:

docker build --tag django.nv:1.0 .

Nothing mystical. The command:

  • docker build tells Docker to create an image.

  • -tag django.nv:1.0 gives the image a name and version.

  • . tells Docker to use the Dockerfile in the current directory.

Docker Registry

A registry is a place where you store and retrieve Docker images. Docker supports both public and private registries.

Organizations often maintain private registries on-prem or in cloud environments. AWS, GCP and Azure offer managed registry services.

You must authenticate before you push or pull images from private registries.

$ docker login -u <username> -p <password> docker.domain.com
Login Succeeded

Registry Structure

Registry / Repository / Version

Examples:

docker.io / nmap    / latest
docker.io / bandit  / 1.0.1

Reference

https://docs.docker.com/registry/

Downloading a Docker Image

Before downloading images from a private registry, authentication is required. Public images can be pulled without login.

If no version is specified during a pull, Docker defaults to using latest.


How Image Naming Works

A fully qualified Docker image reference follows this structure:

Registry / Repository / Version

Examples

docker.io/nmap:latest
docker.io/bandit:1.0.1

Pulling an Image

To download an image from a repository, use the docker pull command.

Example

docker pull registry.domain.com/username/ubuntu:16.04

This pulls the ubuntu:16.04 version from the specified private registry.


Mermaid Diagram: Image Reference Structure

The diagram shows how Docker identifies an image by chaining:

  • Registry (where the image is stored)

  • Repository (the image family or name)

  • Version Tag (specific release of the image)


Key Points

  • Login is required for private registries.

  • Omission of the tag defaults to latest.

  • Pulling retrieves an image and stores it locally for later use.

Docker Repository

A repository organizes and stores multiple versions of a Docker image. It behaves like a namespace similar to a git repository that holds several releases.

If an image tag is not specified, Docker uses latest by default.

To tag an image before pushing it to a registry, use the -t or tag option.

Tag Example

docker tag django.nv:1.0 registry.domain.com/username/django.nv:1.0

Push Example

docker push registry.domain.com/username/django.nv:1.0

Repository Structure

Registry / Repository / Version

Examples:

docker.io / nmap   / latest
docker.io / bandit / 1.0.1

A registry stores repositories.

A repository stores all tagged versions of an image.

Example

1 - searching

raj@raj-ubuntu:~$ docker search nmap
NAME                  DESCRIPTION                                     STARS     OFFICIAL
securecodebox/nmap    A Docker image containing the NMAP security …   30
demisto/nmap                                                          0
parrotsec/nmap        Official Parrot container for nmap              1
instrumentisto/nmap   Nmap ("Network Mapper") Docker Image            30
frapsoft/nmap         nmap on Alpine Linux (6 MB)                     3
uzyexe/nmap           nmap container image (size: 14.93MB)            32
networkstatic/nmap    Dockerized Nmap Port Scanner on Debian          6
appsmanager/nmap                                                      1
sneakerhax/nmap       A Dockerized version of Nmap                    0
flibustier/nmap       NMAP based on Alpine                            2
sammascanner/nmap     Nmap Scanner  Will run and then save the res…   1
volterraio/nmap                                                       0
bytesizedalex/nmap    Alpine Linux image with nmap network scanner.   0
blairy/nmap           Single concern container to execute the most…   1
vonahisec/nmap        A simple Nmap docker image.                     0
n4n0m4c/nmap          docker nmap                                     1
nikhen/nmap           This is a docker container including nmap in…   0
cyberwatch/nmap       Docker Image with Nmap build from source        4
dockerpinata/nmap                                                     0
k0st/nmap             Nmap on minimum, modern and secure Alpine di…   4
functions/nmap                                                        0
tomkukral/nmap                                                        0
whiteadam/nmap        Alpine Linux image with nmap, libssl, and ca…   0
nitrogen17/nmap       ubuntu 18.04 with nmap                          0
linosgian/nmap                                                        0

2- pulling

raj@raj-ubuntu:~$ docker pull uzyexe/nmap
Using default tag: latest
latest: Pulling from uzyexe/nmap
b0dc45cd432d: Pull complete
364328af40b6: Pull complete
9c7abf28af64: Pull complete
635bab23d5f1: Pull complete
054e7786c1b6: Pull complete
5100e35a43b2: Pull complete
d908e559dfdc: Pull complete
aaed4af89abd: Pull complete
Digest: sha256:efd58ad449b98ae71ad1e1690af7e2c940117dd61a66c902da9d894fafa92e52
Status: Downloaded newer image for uzyexe/nmap:latest
docker.io/uzyexe/nmap:latest

3 - run

raj@raj-ubuntu:~$ docker run -t uzyexe/nmap:latest localhost
Starting Nmap 7.80 ( <https://nmap.org> ) at 2025-12-09 15:43 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0000090s latency).
Other addresses for localhost (not scanned): ::1
All 1000 scanned ports on localhost (127.0.0.1) are closed

Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds

In the world of Docker:

  • localhost does NOT mean your Ubuntu computer (raj-ubuntu).

  • localhost means the container itself.

You asked the container to scan itself. Since uzyexe/nmap is a tiny container with only the scanner installed and no web servers or databases running inside it, it correctly reported that it has no open ports.

How to touch the host computer from container

If you want the container to "break out" and scan your Ubuntu box (raj-ubuntu), you need to attach it to the host's network.

Run this command instead (notice the added flag):

Bash

docker run --network host -t uzyexe/nmap:latest localhost
  • -network host: This removes the network isolation. Now, when the container says "localhost," it actually refers to your real Ubuntu server.

  • Outcome: You might see port 22 (SSH) open now, since you are SSH'ed into that box.

raj@raj-ubuntu:~$ docker run --network host -t uzyexe/nmap:latest localhost
Starting Nmap 7.80 ( <https://nmap.org> ) at 2025-12-09 15:47 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000014s latency).
Not shown: 998 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
631/tcp open  ipp

Nmap done: 1 IP address (1 host up) scanned in 0.16 seconds

Docker Expose

A container can expose ports to the outside world so external systems can communicate with the application running inside it.

You expose ports during runtime using the -p or –publish option.

Syntax

docker run -p HOST_PORT:DOCKER_PORT image-name

Examples

docker run -p 8000:8000 django.nv:1.0
docker run -p 8000:8000 -p 8001:8001 django.nv:1.0

Example Dockerfile

# Python base image
FROM python:2

# Copy startup script
COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt
RUN ./reset_db.sh

# Expose port 8000 for communication
EXPOSE 8000

# Command executed when container starts
CMD ["/app/runapp.sh"]
  • EXPOSE is documentation. It does not open the port automatically.

  • docker run -p is what binds a container port to a host port.

  • Multiple ports can be exposed and published as needed.

Docker Mount

A container has its own filesystem. When it stops, that filesystem disappears unless you explicitly mount a folder from the host. Mounts let you:

  • Save output or logs

  • Edit files on your host and see the changes instantly inside the container

  • Treat a folder like a shared directory between host and container

Think of a mount as telling Docker:

“Use this real folder on my machine instead of creating a temporary filesystem.”

docker run -v HOST_DIR:CONTAINER_DIR image-name

Meaning:

PartExplanation
HOST_DIRThe actual folder on your machine
CONTAINER_DIRWhere the container will see that folder
-vThe mount instruction

Example 1: Mount local ./app to /app inside container

docker run -v ./app:/app django.nv:1.0

Inside the container, /app now shows your local ./app contents.

Example 2: Mount current working directory

docker run -v $(pwd):/app django.nv:1.0

Great when you are developing on your host and want the container to use the same files.


Why mount is essential?

Without mount:

  • The container writes data.

  • The container exits.

  • The data is gone.

With mount:

  • Data is written into your real filesystem.

  • You can inspect, modify, and reuse it even after the container dies.

clean up

when i checked for the docker process in the system

raj@raj-ubuntu:~$ docker ps -a
CONTAINER ID   IMAGE                COMMAND            CREATED         STATUS                     PORTS     NAMES
4651276a2f11   uzyexe/nmap:latest   "nmap localhost"   2 minutes ago   Exited (0) 2 minutes ago             mystifying_brown
69ea0d81a079   uzyexe/nmap:latest   "nmap localhost"   6 minutes ago   Exited (0) 6 minutes ago             kind_kepler
raj@raj-ubuntu:~$ docker rm 4651276a2f11
4651276a2f11
raj@raj-ubuntu:~$ docker rm 69ea0d81a079
69ea0d81a079
raj@raj-ubuntu:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

The "Pro Tip" for next time

Since Nmap is a "one-off" tool (you run it, get results, and leave), you don't want to manually delete the container every single time.

Use the --rm flag in your run command next time:

Bash

docker run --rm -t uzyexe/nmap scanme.nmap.org

  • -rm: "Automatically remove this container the moment it finishes."

Now the big question should i need to run the docker pull command again ?

NO. You do not need to pull again.

You removed the Container (the instance), but you kept the Image (the software/installer).

The "App Store" Analogy

Think of the Docker Image like an app on your phone (e.g., WhatsApp). Think of the Docker Container like "Opening WhatsApp to send a message."

  • docker pull: Downloading WhatsApp from the App Store. (You did this once).

  • docker run: Opening the app.

  • docker rm: Closing the app (swiping it away).

You just "swiped away" the app. You did not uninstall it. If you want to run it again, just type docker run ... and it will start instantly without downloading anything.

here is the proof

raj@raj-ubuntu:~$ docker images
                                                                                                              i Info →   U  In Use
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
uzyexe/nmap:latest   1166ff5a6b0a       18.5MB             0B

Detached Mode

A container can run in detached mode so your terminal stays free for other work.

Use the -d or --detach option when starting a container.

Why detached mode matters

  • The container runs in the background

  • Your terminal is not blocked

  • Useful for servers, APIs or long-running tasks

Commands

docker run -d image-name

Run with a custom name:

docker run --name webserver -d nginx

Stop the detached container:

docker stop webserver
3 views

More from this blog