Tools: Docker & Containers: Ground UP (2026)

Tools: Docker & Containers: Ground UP (2026)

What Is a Container?

Containers vs. Virtual Machines

Why Are Containers So Lightweight?

What a container base image includes:

What it borrows from the host OS:

What Is Docker?

Docker Architecture

The Docker Lifecycle

Key Docker Terminology

Dockerfile

Container

Docker Daemon (dockerd)

Docker Client (docker)

Docker Registry

Installing Docker on Ubuntu

Start the Daemon & Grant User Access

Verify the Installation

Building & Running Your First Image

Step 1: Clone the example repo

Step 2: Log in to DockerHub

Step 3: Build your image

Step 4: Verify the image exists

Step 5: Run the container

Step 6: Push to DockerHub

Key Takeaways

What's Next? If you've ever heard "works on my machine" — containers are the permanent fix to that problem. A container is a self-contained, portable unit of software. It bundles together: Everything is packaged so the application runs identically regardless of the underlying environment — your laptop, a CI server, or a cloud VM in us-east-1. Simple Mental Model: Think of a container like a shipping container on a cargo ship. The contents are standardized and isolated. The ship (host OS) doesn't care what's inside — it just carries it. Both containers and VMs isolate applications, but the architecture is fundamentally different — and that difference has huge practical consequences. The Ubuntu container base image is almost 100× smaller than its VM equivalent. That's not a rounding error — that's a fundamentally different architecture. The secret is in what containers don't include. Rather than bundling a full operating system, a container shares the host OS kernel through containerization. Key Insight: Changes inside a container do NOT affect the host or other containers. Isolation is enforced at the kernel level via namespaces and cgroups — even though they share the same kernel. Containerization is the concept. Docker is the implementation. Docker is the platform that makes it easy to: If the Docker Daemon stops running, Docker is effectively dead — it's the orchestrator for everything. The CLI is just a thin client that sends commands to the daemon via the Docker API. Everything in Docker revolves around three core commands: A plain-text file where you define the steps to build your image. Each instruction creates a new layer in the image. Only changed layers are rebuilt on subsequent builds — which is why Docker builds stay fast. A read-only template built from a Dockerfile. Images are often composed on top of other images — for example, you might extend the official ubuntu image by installing Python on top of it. A running instance of an image. The same image can spawn many containers simultaneously. Containers are ephemeral by default — stop one and the data inside is gone unless you use volumes. The background service that manages everything — images, containers, networks, volumes. Listens for Docker API requests from the CLI or other daemons. The CLI tool most users interact with. When you run docker run, it sends that command to dockerd via the Docker API. A storage service for images. DockerHub is the default public registry. You can also run a private registry, or use services like Quay.io, GitHub Container Registry, or AWS ECR. The official docs at docs.docker.com/get-docker cover all platforms. For a quick Ubuntu / EC2 setup: This is where many beginners get stuck. After installing Docker, you need to both start the daemon and grant your user access to run Docker commands. Important: You must log out and log back in after running usermod for the group change to take effect. If you see a permission denied error, it usually means either the daemon isn't running or your user isn't in the docker group yet. If you see Hello from Docker! — you're good to go. Create a free account at hub.docker.com if you don't have one, then: You'll see Docker executing each step in your Dockerfile, pulling base images if needed, and tagging the final result: Your image is now publicly available on DockerHub. Anyone in the world can pull and run it with a single docker run command. What just happened? You containerized an application, ran it locally, and shipped it to a global registry — in 6 commands. That's the Docker workflow in its entirety. This is just the beginning. From here, explore: Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ /bin # ls, cp, ps — essential executables /sbin # init, shutdown — system executables /etc # config files for system services /lib # libraries used by executables /usr # user apps, utilities, docs /var # logs, spool files, temp files /root # home directory of root user /bin # ls, cp, ps — essential executables /sbin # init, shutdown — system executables /etc # config files for system services /lib # libraries used by executables /usr # user apps, utilities, docs /var # logs, spool files, temp files /root # home directory of root user /bin # ls, cp, ps — essential executables /sbin # init, shutdown — system executables /etc # config files for system services /lib # libraries used by executables /usr # user apps, utilities, docs /var # logs, spool files, temp files /root # home directory of root user Docker CLI (-weight: 500;">docker) ← you type commands here │ sends API requests to ▼ Docker Daemon (dockerd) ← the core -weight: 500;">service ├── manages → Images ├── manages → Containers ├── manages → Networks └── manages → Volumes │ communicates with ▼ Docker Registry (DockerHub / Quay.io / private) Docker CLI (-weight: 500;">docker) ← you type commands here │ sends API requests to ▼ Docker Daemon (dockerd) ← the core -weight: 500;">service ├── manages → Images ├── manages → Containers ├── manages → Networks └── manages → Volumes │ communicates with ▼ Docker Registry (DockerHub / Quay.io / private) Docker CLI (-weight: 500;">docker) ← you type commands here │ sends API requests to ▼ Docker Daemon (dockerd) ← the core -weight: 500;">service ├── manages → Images ├── manages → Containers ├── manages → Networks └── manages → Volumes │ communicates with ▼ Docker Registry (DockerHub / Quay.io / private) Dockerfile ──-weight: 500;">docker build──▶ Image ──-weight: 500;">docker run──▶ Container │ -weight: 500;">docker push │ ▼ Registry Dockerfile ──-weight: 500;">docker build──▶ Image ──-weight: 500;">docker run──▶ Container │ -weight: 500;">docker push │ ▼ Registry Dockerfile ──-weight: 500;">docker build──▶ Image ──-weight: 500;">docker run──▶ Container │ -weight: 500;">docker push │ ▼ Registry -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker.io -y -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker.io -y -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker.io -y # Check daemon -weight: 500;">status -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">status -weight: 500;">docker # Start daemon if not running -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start -weight: 500;">docker # Add your user to the -weight: 500;">docker group (replace 'ubuntu' with your username) -weight: 600;">sudo usermod -aG -weight: 500;">docker ubuntu # Check daemon -weight: 500;">status -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">status -weight: 500;">docker # Start daemon if not running -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start -weight: 500;">docker # Add your user to the -weight: 500;">docker group (replace 'ubuntu' with your username) -weight: 600;">sudo usermod -aG -weight: 500;">docker ubuntu # Check daemon -weight: 500;">status -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">status -weight: 500;">docker # Start daemon if not running -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start -weight: 500;">docker # Add your user to the -weight: 500;">docker group (replace 'ubuntu' with your username) -weight: 600;">sudo usermod -aG -weight: 500;">docker ubuntu -weight: 500;">docker run hello-world -weight: 500;">docker run hello-world -weight: 500;">docker run hello-world -weight: 500;">git clone https://github.com/iam-veeramalla/Docker-Zero-to-Hero cd examples -weight: 500;">git clone https://github.com/iam-veeramalla/Docker-Zero-to-Hero cd examples -weight: 500;">git clone https://github.com/iam-veeramalla/Docker-Zero-to-Hero cd examples -weight: 500;">docker login # Enter your DockerHub username and password when prompted -weight: 500;">docker login # Enter your DockerHub username and password when prompted -weight: 500;">docker login # Enter your DockerHub username and password when prompted -weight: 500;">docker build -t yourusername/my-first--weight: 500;">docker-image:latest . -weight: 500;">docker build -t yourusername/my-first--weight: 500;">docker-image:latest . -weight: 500;">docker build -t yourusername/my-first--weight: 500;">docker-image:latest . Successfully built 960d37536dcd Successfully tagged yourusername/my-first--weight: 500;">docker-image:latest Successfully built 960d37536dcd Successfully tagged yourusername/my-first--weight: 500;">docker-image:latest Successfully built 960d37536dcd Successfully tagged yourusername/my-first--weight: 500;">docker-image:latest -weight: 500;">docker images -weight: 500;">docker images -weight: 500;">docker images REPOSITORY TAG IMAGE ID CREATED SIZE yourusername/my-first--weight: 500;">docker-image latest 960d37536dcd 26 seconds ago 467MB ubuntu latest 58db3edaf2be 13 days ago 77.8MB hello-world latest feb5d9fea6a5 16 months ago 13.3kB REPOSITORY TAG IMAGE ID CREATED SIZE yourusername/my-first--weight: 500;">docker-image latest 960d37536dcd 26 seconds ago 467MB ubuntu latest 58db3edaf2be 13 days ago 77.8MB hello-world latest feb5d9fea6a5 16 months ago 13.3kB REPOSITORY TAG IMAGE ID CREATED SIZE yourusername/my-first--weight: 500;">docker-image latest 960d37536dcd 26 seconds ago 467MB ubuntu latest 58db3edaf2be 13 days ago 77.8MB hello-world latest feb5d9fea6a5 16 months ago 13.3kB -weight: 500;">docker run -it yourusername/my-first--weight: 500;">docker-image -weight: 500;">docker run -it yourusername/my-first--weight: 500;">docker-image -weight: 500;">docker run -it yourusername/my-first--weight: 500;">docker-image Hello World Hello World Hello World -weight: 500;">docker push yourusername/my-first--weight: 500;">docker-image -weight: 500;">docker push yourusername/my-first--weight: 500;">docker-image -weight: 500;">docker push yourusername/my-first--weight: 500;">docker-image - A container bundles your app + libraries + minimal OS into a portable, isolated unit - Containers share the host kernel — making them ~100× lighter than VMs - Docker is the toolchain that builds, runs, and distributes containers - The lifecycle is three commands: -weight: 500;">docker build → -weight: 500;">docker run → -weight: 500;">docker push - DockerHub is the default public registry for sharing images - Your application code - All required libraries and dependencies - The minimum system dependencies needed to run - Kernel & system calls — the container calls out to the host kernel for CPU, memory, I/O - Networking stack — for connectivity, using host networking or a virtual network - Linux namespaces — creates isolation for file system, PID, and network per container - Control groups (cgroups) — limits how much CPU/memory/I/O each container can use - Build container images from a simple text file (Dockerfile) - Run those images as containers on any machine - Push and pull images from public/private registries like DockerHub - Containers bundle app + dependencies + minimal OS into a portable unit - They're lightweight because they share the host kernel via namespaces & cgroups - Container base images are ~100× smaller than equivalent VM images - Docker is the platform: build images → run containers → push to registries - The Docker Daemon is the core -weight: 500;">service; the CLI is just a client talking to it - DockerHub is the default public registry for sharing and pulling images - The three lifecycle commands are build, run, and push - Docker Compose — define and run multi-container applications with a single YAML file - Docker Volumes — persist data beyond the container lifecycle - Multi-stage builds — drastically shrink production image sizes - Kubernetes — orchestrate containers at scale across clusters