Skip to content
All question banks

DevOps

Docker Questions

Comprehensive technical guide covering Docker Architecture, Images, Networking, Volumes, Orchestration (Swarm/K8s), and Security.

149 of 149 questions

Introduction7

Docker is an open-source platform designed to automate the deployment, scaling, and management of applications using containerization. it allows developers to package an application with all its dependencies into a standardized unit called a container, ensuring it runs consistently across different computing environments.

Containers are lightweight, standalone, and executable packages that include everything needed to run a piece of software, including the code, runtime, system tools, libraries, and settings. They isolate applications from each other and the underlying infrastructure.

A Docker container is a runtime instance of a Docker image. It is a sandboxed process on the host machine that is isolated from all other processes. Multiple containers can run on the same host, sharing the OS kernel but having their own file system and network stack.

Virtual Machines (VMs) include a full guest operating system, making them heavy and slow to start. Docker containers share the host's OS kernel and isolate the application processes at the user level, making them much lighter, faster to boot, and more resource-efficient than VMs.

Advantages include: 1. Consistency across environments (Dev/Test/Prod). 2. Rapid deployment and scaling. 3. Resource efficiency through shared kernels. 4. Isolation and security. 5. Simplified dependency management and version control of infrastructure.

A Docker container is a standardized, encapsulated environment that runs an application. It is isolated from the host OS and other containers using kernel namespaces and cgroups, providing a 'write once, run anywhere' experience.

Containers are process-level isolation sharing one OS kernel. VMs are hardware-level isolation each with its own OS kernel. This makes containers faster to start (milliseconds vs minutes) and more portable.

Architecture4

The architecture follows a client-server model consisting of: 1. Docker Client (CLI tool). 2. Docker Host (running the Docker Daemon). 3. Docker Objects (Images, Containers, Networks, Volumes). 4. Docker Registry (Docker Hub or private registries).

The Docker daemon (dockerd) is a persistent background process that manages Docker objects such as images, containers, networks, and volumes. It listens for Docker API requests and performs the heavy lifting of building and running containers.

Docker uses Linux kernel features to provide isolation. 'Namespaces' provide a private view of system resources (network, PID, mount), while 'Control Groups' (cgroups) limit and monitor resource usage like CPU and memory for each container.

Namespaces are a kernel feature that isolates system resources per process (Network, User, UTS, Mount, IPC, PID). Cgroups (Control Groups) manage the resource allocation, ensuring a container doesn't consume all available CPU or RAM of the host.

Docker Images13

A Docker image serves as a read-only template used to create containers. It contains the application code, libraries, and environment configurations. Images are portable, allowing the same software to be deployed anywhere Docker is installed.

An image is a static, read-only blueprint (class), while a container is a dynamic, running instance (object) of that image. You can create multiple containers from a single image, and changes to a container do not affect the underlying image.

You use the 'docker build' command. This command reads the instructions in the Dockerfile and executes them step-by-step to produce a final image. Example: 'docker build -t my-app:v1 .'

Docker images are composed of a series of read-only layers. Each instruction in a Dockerfile creates a new layer. These layers are cached and shared, making builds faster and reducing storage space. When a container runs, a thin 'writable layer' is added on top.

Tags are aliases for Image IDs, usually used for versioning (e.g., '1.0', 'latest', 'stable'). They are important because they allow developers to identify specific releases of an image and ensure the correct version is deployed in production.

Optimization techniques include: 1. Using minimal base images (like Alpine). 2. Multi-stage builds to exclude build tools. 3. Minimizing the number of layers. 4. Using .dockerignore to exclude unnecessary files. 5. Leveraging layer caching efficiently.

A Docker image is a read-only, multi-layered file that includes the application code and all its dependencies. It is the persistent 'snapshot' from which containers are launched.

An image is the source code/blueprint; it is static. A container is the running process; it is dynamic. Think of an Image as a Program and a Container as a Process.

It automates the creation of a Docker image by following instructions in a Dockerfile. It sends the 'build context' to the daemon and produces a tagged image in the local library.

By appending a colon and the tag name to the image name. Example: 'docker pull python:3.9-slim'. If no tag is specified, Docker defaults to ':latest'.

Images are immutable. To 'update' an image, you must modify the Dockerfile, run 'docker build' again to create a new version, and then restart your containers using the new image.

1. Use .dockerignore. 2. Order instructions from least to most frequent change. 3. Combine RUN commands to reduce layers. 4. Use multi-stage builds. 5. Clear package manager caches (e.g., rm -rf /var/lib/apt/lists/*).

Base images like 'Alpine' or 'Distroless' contain only the bare minimum files. This reduces the number of vulnerable binaries (like shells or package managers), making the container much harder for an attacker to exploit.

Dockerfile6

A Dockerfile is a text document containing all the commands a user could call on the command line to assemble an image. Instructions like FROM, RUN, CMD, and ENTRYPOINT define the build process and the container's default behavior.

COPY is preferred for simply moving local files into the container. ADD is more powerful as it can fetch files from URLs and automatically extract tar archives. Use COPY for transparency unless you specifically need the extra features of ADD.

Multi-stage builds allow you to use multiple 'FROM' statements in one Dockerfile. You can compile your code in a large 'build' stage and then copy only the resulting binary into a smaller 'production' stage, resulting in a significantly smaller and more secure image.

The .dockerignore file is used to exclude files and directories from the build context. This speeds up the build process and keeps the resulting image smaller by preventing unnecessary files (like .git, node_modules, or logs) from being sent to the Docker daemon.

It is a script containing instructions to build a Docker image. Its purpose is to provide a version-controlled, repeatable way to document and automate the environment setup for an application.

Build arguments (ARG) allow you to pass variables into the Dockerfile during the build process ('--build-arg'). They are useful for setting version numbers or environment settings that shouldn't be hardcoded.

Docker Container Operations24

'docker create' initializes a container from an image and prepares it for running, but does not start it. 'docker run' is a combination of 'docker create' and 'docker start', creating and starting the container immediately.

'docker run' is used to create and start a NEW container. 'docker exec' is used to run a new command inside an ALREADY running container, which is useful for debugging or executing administrative tasks.

'docker exec' starts a new process inside the container, allowing you to leave it without stopping the container. 'docker attach' connects your terminal to the container's main process (PID 1); if you exit with Ctrl+C, the entire container usually stops.

You use the '-d' flag with the 'docker run' command. This runs the container in the background of your terminal, allowing you to continue using the terminal while the container executes. Example: 'docker run -d nginx'.

You use the 'docker system prune' command. This safely removes stopped containers, unused networks, and dangling images. Adding the '-a' flag will also remove images not associated with any container, and '--volumes' will remove unused volumes.

The lifecycle includes several states: 1. Created. 2. Running. 3. Paused. 4. Exited (Stopped). 5. Dead (Removal phase). Containers move between these states based on user commands or internal process completion.

Using the '--restart' flag during 'docker run'. Options include 'no' (default), 'on-failure' (restart if process fails), 'always' (always restart), and 'unless-stopped' (restart unless manually stopped by the user).

'exec' creates a new process (like a new shell), while 'attach' connects you to the existing process that started the container. If you exit 'attach', the container usually dies; if you exit 'exec', the container keeps running.

Using 'docker run [OPTIONS] IMAGE [COMMAND]'. Common options include '-d' (detached), '-p' (ports), and '--name' (custom name).

You can use 'docker create' to instantiate it without starting, or 'docker run' to both create and start it immediately.

'docker exec -it <container_id> /bin/bash' (or /bin/sh for Alpine). The '-it' flag makes the session interactive with a TTY.

To run an auxiliary process inside a container that is already running. It is the standard tool for interactive shell debugging or running one-off scripts against a live DB container.

Using 'docker stop <container_id>'. This sends a SIGTERM signal to the process, allowing it to shut down gracefully before being killed.

'docker ps' lists running containers. 'docker ps -a' lists all containers, including those that have stopped or exited.

Simply run the command 'docker ps'.

To provide a status overview of containers, showing IDs, image names, command used, creation time, status (up/down), ports, and names.

Using 'docker rm <container_id>'. You cannot remove a running container unless you use the '-f' (force) flag.

You must first unpause it using 'docker unpause', then stop it, and then remove it. Alternatively, 'docker rm -f' will remove it directly.

Using the 'docker system prune' command. This is the 'cleanup' command for Docker.

States include: Created, Restarting, Running, Removing, Paused, Exited, and Dead. You check them via 'docker ps -a' or 'docker inspect'.

The process stops, and resources (CPU/RAM) are released, but the container's file system remains on the host disk until the container is explicitly removed ('docker rm').

You cannot 'update' a running container's image. You must stop the container, remove it, and 'docker run' a new one using the updated image.

This requires an orchestrator like Docker Swarm or Kubernetes. You use a 'Rolling Update' strategy where new containers are started before old ones are stopped, often managed via a load balancer.

By never storing important data inside the container's writable layer. All persistent data (DB files, uploads) must be stored in external Volumes or Bind Mounts.

Docker Volumes & Data Management9

A Docker volume is a managed storage mechanism for persisting data generated and used by Docker containers. Volumes are stored on the host file system but managed by Docker, ensuring data survives even if the container is deleted.

Volumes are managed by Docker and stored in a specific directory (/var/lib/docker/volumes). Bind mounts can be stored anywhere on the host system and rely on the host's directory structure, making them more dependent on the host's OS configuration.

Volumes are specialized directories used to bypass the container's storage layer. They are used for data persistence and sharing data between containers, as they are not deleted when a container stops.

Data is managed using three main methods: 1. Volumes (managed by Docker). 2. Bind Mounts (linked to host path). 3. Tmpfs (stored in host memory, never written to disk).

Using the '-v' or '--mount' flag. Example: 'docker run -v /host/path:/container/path image_name'.

By mounting the same Volume to multiple containers simultaneously. Any changes made by one container are instantly visible to the others.

Volume drivers allow you to store data on external storage (like AWS EBS, Azure Disks, or NFS). You use it with the '--driver' flag when creating a volume.

In production, managed Volumes with cloud-specific drivers (like CSI drivers) are used to ensure data is backed up, redundant, and can move with the container if it migrates to another host.

Distributed environments use Network File Systems (NFS) or Cloud Storage plugins so that any node in the cluster can access the same persistent data volume.

Docker Networking10

1. Bridge: The default, creating a private network on the host. 2. Host: Shares the host's network stack directly (no isolation). 3. Overlay: Connects multiple Docker daemons across different hosts, enabling Swarm services to communicate securely.

You can use the 'docker inspect' command along with a filter. Example: 'docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" container_id'.

Using the '-p' or '--publish' flag. Example: 'docker run -p 8080:80 nginx' maps port 80 of the container to port 8080 of the host machine, making the service accessible externally.

It is an infrastructure that allows containers to communicate with each other and the outside world. Docker creates virtual interfaces and bridges to route this traffic.

The default is the 'bridge' network. It assigns a private IP to each container and allows them to communicate with each other on that host.

It is a software-defined bridge named 'bridge' (usually on the subnet 172.17.0.0/16) created by Docker when it is installed.

Typically, the Docker bridge 'docker0' takes the IP '172.17.0.1'. This serves as the default gateway for all containers on the default bridge.

Using 'docker network create --driver <type> <name>'. Custom bridge networks allow containers to use 'automatic service discovery' via container names.

To define a specific communication boundary. Containers on different custom networks cannot talk to each other, providing an extra layer of network security.

At scale, 'overlay' networks are used to bridge traffic between multiple physical hosts, or a CNI (Container Network Interface) is used in Kubernetes to manage complex routing.

Docker Compose7

Docker Compose is a tool for defining and running multi-container applications. Using a YAML file (docker-compose.yml), you can configure your application's services, networks, and volumes, and then start everything with a single command: 'docker-compose up'.

It is a tool used for orchestrating multi-container applications, allowing you to define services (DB, Web, Cache) in one YAML file and manage their entire lifecycle together.

It simplifies management by creating shared networks and volumes automatically, maintaining service dependencies, and allowing for easy environment configuration (environment variables).

By using the 'docker-compose.yml' file to define services. Running 'docker-compose up' starts all services, and 'docker-compose scale' can increase the number of instances for a service.

It is the configuration file for Docker Compose. It defines the images, ports, volumes, and networks for every container in a multi-container app.

It is used to store local configuration overrides. When you run 'docker-compose up', it automatically merges this file with the main file, making it perfect for dev-specific settings.

By defining each microservice as a 'service' in the YAML file. Compose handles linking them together on a private network, allowing them to communicate using service names as hostnames.

Docker Swarm8

Docker Swarm is Docker's native orchestration tool. It allows you to manage a cluster of Docker nodes as a single virtual system, providing features like load balancing, service discovery, and rolling updates for containerized applications.

In a Swarm environment, a container is a single instance, while a service is the definition of the desired state (e.g., 'run 5 replicas of nginx'). The Swarm manager ensures that the specified number of containers (tasks) are running across the cluster.

Swarm is Docker's built-in, easy-to-use orchestrator. It is simpler to set up but less flexible than Kubernetes, which has a much larger feature set and ecosystem support.

A service is the logical definition of an application (image + replicas). A container (task) is the individual physical instance running on a node to fulfill that service definition.

By running 'docker service update --image <new_image> <service_name>'. Swarm updates instances one-by-one to ensure zero downtime.

Swarm uses 'Manager' nodes (raft consensus) and 'Worker' nodes. It uses a declarative model similar to K8s but is more tightly integrated into the Docker CLI.

It is a group of physical or virtual machines running Docker that have been joined together into a cluster. Managers coordinate the distribution of tasks among workers.

In Swarm, you use 'docker service'. In Kubernetes, you use 'kubectl' to manage Pods, Deployments, and Services. K8s is significantly more complex but more robust for large apps.

Container Orchestration8

Orchestration is the automated management of container lifecycles in complex environments. It handles tasks like deployment, scaling, networking between containers, load balancing, and health monitoring (Self-healing).

It is the system that manages the lifecycle of thousands of containers, handling networking, scale-up/down, health checks, and cross-host communication.

In microservices, you have many moving parts. Orchestration is vital because it automates the 'plumbing' (discovery and load balancing) so services can find and talk to each other.

Manually by running more 'docker run' commands, or in an orchestrator by using 'scale' commands (e.g., 'docker service scale myservice=10').

By putting a load balancer (like Nginx or HAProxy) in front of multiple containers running the same image, distributing incoming traffic among them.

By using a cluster manager (K8s/Swarm) to spread containers across multiple physical nodes to increase compute capacity and ensure high availability.

There is no fixed limit. It is limited only by the host's resources (CPU, RAM, disk space) and the Linux kernel's process limit (PID limit).

Usually via an orchestrator's 'Ingress' network or an external load balancer (like AWS ELB) that routes traffic to the nodes where the containers are running.

Security11

Security best practices include: 1. Running as non-root users. 2. Using trusted, scanned images. 3. Limiting container resources (cgroups). 4. Using read-only file systems. 5. Managing secrets securely using Swarm secrets or Vault. 6. Keeping the Docker daemon updated.

Using security scanning tools (Snyk/Clair), limiting kernel capabilities (--cap-drop), and isolating containers into separate virtual networks.

1. Use minimal images. 2. Don't run as root. 3. Scan for vulnerabilities. 4. Use read-only root filesystems. 5. Limit CPU/RAM to prevent DoS attacks.

Both have a 'Secret' object type. Secrets are encrypted in transit and only mounted as temporary files (tmpfs) in memory for authorized containers.

Avoid environment variables for sensitive data as they appear in 'inspect'. Use Docker Secrets (Swarm) or mount secret files into the container.

A vulnerability is an old/insecure library in the image. You scan them using 'docker scan' (integrated Snyk) or specialized tools like Trivy or Anchore.

It is an automated step where images are checked for known CVEs (Common Vulnerabilities and Exposures). If vulnerabilities are found, the build is failed.

A feature (DOCKER_CONTENT_TRUST=1) that allows you to sign images with a digital key. Docker will only pull and run images that have been signed by a trusted publisher.

By protecting the Docker socket (unix:///var/run/docker.sock) and configuring the daemon to only accept connections over TLS/HTTPS with client certificates.

An instruction in a Dockerfile (HEALTHCHECK) that tells Docker how to test if the app inside is still working (e.g., running a curl command against localhost).

By defining health check parameters (interval, timeout, retries) in the docker-compose or service definition so the orchestrator can restart failed instances.

Kubernetes vs Docker4

Docker is a platform for building and running containers on a single host. Kubernetes is a more complex orchestration platform designed to manage clusters of hosts running containers. Kubernetes offers more advanced self-healing, automated rollouts, and secret management than basic Docker.

By running multiple replicas of a service across different nodes in a Swarm/Kubernetes cluster with a load balancer in front.

Implement layer caching, use a local registry mirror to save bandwidth, and use 'Prometheus' for real-time alerting on resource bottlenecks.

By using 'Self-healing' features where the orchestrator automatically detects a dead container and restarts a new one on a healthy node.

Advanced Docker Concepts5

DinD is the practice of running Docker inside a Docker container. It is commonly used in CI/CD pipelines to build and push Docker images. It requires the container to run in '--privileged' mode, which has significant security implications.

Metadata in the form of key-value pairs (e.g., version="1.0", maintainer="admin") that help organize images and containers.

Extensions that add new features to Docker, such as custom volume drivers (storing data on S3) or network drivers (integrating with Cisco/VMware networking).

In orchestration, these are actions triggered by state changes (e.g., 'PostStart' or 'PreStop'), allowing for custom initialization or graceful cleanup.

Via the Docker API. Monitoring tools (Dynatrace), security tools (Aqua), and automation tools (Ansible) all use this API to manage containers.

Monitoring, Logging & Debugging15

The 'docker stats' command provides a live stream of resource usage statistics for running containers, including CPU percentage, memory usage, network I/O, and block I/O. It is essential for basic performance monitoring.

To fetch the stdout and stderr logs from a container. This is the primary way to debug an application running inside a Docker container.

Using 'docker inspect <container_id>'. It returns a detailed JSON object containing every configuration detail about the container (Network, Mounts, State).

It helps identify misconfigurations such as incorrect port mappings, unmounted volumes, wrong environment variables, or unexpected exit codes.

Locally, use 'docker stats'. In production, you use tools like Prometheus, Grafana, and cAdvisor to collect and visualize container metrics.

By setting CPU and memory limits in the container configuration and monitoring them using the Docker API or external monitoring agents.

Through full-stack monitoring solutions like Datadog, New Relic, or ELK (Elasticsearch, Logstash, Kibana) for log aggregation and metric tracking.

By using Docker logging drivers (e.g., json-file, syslog, gelf, fluentd) to forward logs from the container to a centralized log management server.

By default, Docker stores logs in JSON files on the host. For active management, you use 'docker logs' or configure log rotation to prevent disk exhaustion.

Implement an 'EFK' stack (Elasticsearch, Fluentd, Kibana). Fluentd acts as the collector that scrapes logs from all nodes and sends them to Elasticsearch for analysis.

By aggregating logs via the Docker log-driver and visualizing performance with a monitoring agent installed on the Docker host.

Using a 'Sidecar' pattern (in K8s) or a global service (in Swarm) that collects logs from all containers on all nodes and pushes them to a central repo.

By using DaemonSets (K8s) to ensure a log-collection pod runs on every node, capturing logs from the node's filesystem where Docker writes them.

1. Run 'docker ps -a' to see the exit code. 2. Check 'docker logs'. 3. Use 'docker inspect' to check entrypoints. 4. Try running it interactively with 'docker run -it --entrypoint /bin/sh image_name'.

Centralized logging is key. Additionally, using 'Distributed Tracing' (Jaeger/Zipkin) helps follow a request across multiple container services to find where it fails.

Docker Hub & Registry6

It is the official, world's largest public registry of Docker images, providing millions of community and official images like Ubuntu, MySQL, and Nginx.

A registry is a storage and distribution system for named Docker images. Images can be 'pushed' to the registry for storage and 'pulled' by others for use.

To download an image from a registry (like Docker Hub) to your local machine so you can build containers from it.

They are the 'sync' commands of Docker. 'Push' shares your local image with the team/world via a registry; 'Pull' retrieves updates from others.

The role is to centralize image management. Private registries are managed using Docker's official 'registry' image or enterprise tools like Harbor, JFrog Artifactory, or AWS ECR.

You can run the 'registry:2' container on a server. For security, you must configure TLS/HTTPS and set up basic authentication for users.

Environment Variables & Configuration2

They are key-value pairs used to pass dynamic configuration (like DB credentials or API keys) into a container without hardcoding them into the image.

Using the '-e' flag in 'docker run' or by defining an 'environment' section in a docker-compose.yml file. You can also use an '.env' file.

Docker & Microservices2

Docker provides the 'packaging' for each microservice, ensuring that Service A (Python) doesn't conflict with Service B (Node.js) on the same server.

Docker custom networks have a built-in DNS server. Containers can find each other using their container_name as the hostname.

CI/CD & DevOps4

Containers are used as 'build environments' to ensure identical builds, and the final application is packaged as an image to be deployed automatically.

Git Push -> Jenkins builds image -> Push to Registry -> Helm upgrade -> Kubernetes pulls new image and performs a rolling update.

It provides a GUI and a bundled VM (for Windows/Mac) to run Docker, including a local single-node Kubernetes cluster for testing.

It provides standardized dev environments for teams and includes enterprise features like centralized management and security policy enforcement.

Deployment Strategies1

By running two identical environments (Blue and Green). You deploy the new version to Green, test it, and then switch the Load Balancer traffic from Blue to Green.

System Management3

Using the 'docker version' command for detailed info, or 'docker --version' for a quick summary.

Running 'docker version' displays both the Client (CLI) and Server (Engine/Daemon) versions separately.

On Linux, use 'systemctl status docker'. On Windows/Mac, check the Docker Desktop tray icon or run 'docker info'.

Related