Getting Started with Docker: Containers, Images, and Essential Commands

Understanding Containerization

Docker provides an open platform for packaging applications along with their runtime environment into portable units known as containers. Think of a container as a lightweight, isolated execution environment that behaves like a compact virtual machine.

Key characteristics of Docker containers:

  • Strict process and filesystem isolation between workloads
  • Minimal overhead compared to traditional virtualization
  • Horizontal scalability—spin up thousands of instances rapidly
  • Consistent runtime across development, testing, and production stages

Containers vs. Virtual Machines

Examining the architectural stack of each approach reveals the core difference: virtual machines include a full guest operating system per instance, leading to stronger isolation but heavier resource consumption. Containers, in contrast, share the host kernel and use operating‑system‑level virtualization to enforce boundaries. Both models share the underlying hardware, yet containers launch in seconds because starting one is essentially starting a process.

Core Docker Architecture

The platform comprises several major components:

  • Docker daemon – Manages images, containers, networks, and volumes.
  • Client – Sends commands to the daemon; the primary interface for day‑to‑day image and container operations.
  • Image – A read‑only template from which containers are spawned. Images are layered and can inherit from one another, typically defined via a Dockerfile.
  • Registry – Stores and distributes images, similar to how a Git repository stores code.
  • Container – A runnable instance of an image, analogous to the relationship between a class and an object in object‑oriented programming.

Installing Docker Engine

The following steps install Docker Community Edition on a CentOS host:

# Add required utilities and the Docker repository
yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

# Install the engine, CLI, and containerd
yum install docker-ce docker-ce-cli containerd.io

# Start Docker
systemctl start docker

# Verify the installation
docker run hello-world

A successful run prints "Hello from Docker!" in the terminal.

Working with Containers

A First Example: Static Web site

Consider a static site that only requires Nginx to serve its content. The project structure might look like this:

.
├── Dockerfile
└── site
    └── index.html

Defining an Image with a Dockerfile

The following Dockerfile describes how to assemble the image:

# Base image
FROM nginx:1.15.6

# Establish a working directory
WORKDIR /workspace

# Copy the site into the default Nginx HTML location
COPY ./site/* /usr/share/nginx/html

# Clean up the temporary working directory
RUN set -ex \
    && rm -rf /workspace

WORKDIR /usr/share/nginx/html

# The Nginx base image already declares EXPOSE and CMD,
# so repeating them is unnecessary. The snippet below is for illustration.
# EXPOSE 80
# CMD ["nginx", "-g", "daemon off;"]

Building the Image

Run the build command in the project root:

docker build -t demo1:v1.0.0 .

After pulling the base image and executing the instructions, the new demo1:v1.0.0 image appears in the local image list.

Launching the Container

docker run -p 8080:80 demo1:v1.0.0

Open http://localhost:8080 to see the site. The -p flag maps host port 8080 to the container's port 80.

Essential Dockerfile Instructions

  • FROM – Sets the base image (mandatory first instruction).

    FROM nginx:1.15.6
    
  • COPY – Transfers files from the build context in to the image.

    COPY --chown=nginx:nginx ./site/* /usr/share/nginx/html
    

    The --chown flag sets ownership on the copied content.

  • RUN – Executes commands during the image build phase.

    RUN apt-get update && apt-get install -y curl
    
  • CMD – Specifies the default command executed when a container starts.

    CMD ["executable", "param1", "param2"]
    
  • ENV – Defines environment variables.

    ENV APP_ENV=production LOG_LEVEL=info
    
  • USER – Sets the user for RUN, CMD, and ENTRYPOINT.

    USER appuser:appgroup
    
  • WORKDIR – Changes the working directory for subsequent instructions.

    WORKDIR /app
    

The .dockerignore File

Before uploading the build context to the daemon, Docker checks for a .dockerignore file in the context root. It follows .gitignore semantics:

# Ignore all .log files
**/*.log

# Exclude the data directory
/data

# Ignore markdown files except README.md
*.md
!README.md

Managing Images

A registry solves the problem of versioning and distributing images across teams and clusters. Docker Hub (hub.docker.com) is the public default registry. Official images (marked "Official Image") are maintained by the respective open‑source projects.

Common registry operations:

# Log in to a registry (optional for public pulls)
docker login --username=your_user registry.example.com

# Pull an image
docker pull nginx:latest

# Push an image (requires login)
docker push registry.example.com/myapp:v1.0.0

Private registries—hosted on‑premises or through cloud providers—use the same workflow.

Handling Container Data

Image Layering

A Docker image is constructed from multiple read‑only layers, each representing the delta from the previous one—similar to Git commits. When a container starts, a thin writable layer is added on top. Data stored in this layer vanishes when the container is removed.

Storage Options

  • Volumes – Managed by Docker under /var/lib/docker/volumes/. Create a volume and mount it:

    docker volume create app_data
    docker run -d --name app -v app_data:/mnt/data myimage
    
  • Bind mounts – Mount an arbitrary host path. Useful for sharing configuration files:

    docker run -d --name web \
      -v /host/nginx.conf:/etc/nginx/nginx.conf:ro \
      nginx
    
  • tmpfs – Stores data in the host’s memory (non‑persistent):

    docker run -d --name cache --tmpfs /mnt/data myimage
    

Container Networking

Containers can communicate via regular TCP/IP, and on the same host they can also use the legacy --link mechanism:

# Start a Redis instance
docker run -d --name redis redis

# Connect another container to it
docker run -d --name worker --link redis myworker

In side the worker container, the hostname redis resolves to the Redis container.

To expose a container port to the host:

docker run -d --name web -p 8080:80 nginx

The host’s port 8080 forwards traffic to port 80 inside the container. The host and container ports do not need to match.

Common CLI Commands

# List running containers
docker ps

# Start/stop/remove containers
docker start redis
docker stop redis
docker rm redis

# Open an interactive shell inside a container
docker exec -it redis bash

# Remove an image
docker image rm myimage

# Tag an image
docker tag <image-id> myregistry/myimage:v2.0.1

# Clean up dangling images
docker image prune

You can reference containers by name or ID interchangeably.

Operational Best Practices

Keep Images Lean

Avoid installing unnecessary packages and remove temporary build artifacts. Since instructions like RUN produce layers, chain related commands with &&:

RUN yum -y install gcc automake autoconf libtool make gcc-c++ \
    && ./configure \
    && make \
    && make install \
    && rm -rf /app \
    && yum clean all

Avoid Storing Critical Data Inside Containers

Containers are ephemeral. Persist data using volumes, bind mounts, external databases, or managed cloud services.

One Process per Container

Treat each container as a single‑purpose unit. For a PHP application, for example, run separate containers for Nginx+PHP‑FPM, MySQL, and Redis. This simplifies updates, scaling, and troubleshooting.

Build Reusable Base Images

When an organization shares the same stack (e.g., Nginx, PHP‑FPM, and common extensions), build an internal base image once. Subsequent application images inherit from it, reducing duplication and build time.

Keep the Main Process in the Foreground

The container’s lifecycle is tied to its main process (PID 1). If the main process daemonizes itself, the container exits immediately. Run the application in the foreground, and use docker run -d to detach the container itself if needed.

Tags: docker containers containerization images dockerfile

Posted on Sat, 17 Oct 2026 16:12:08 +0000 by EvanAgee