Continuous Delivery and Docker Overview
Continuous Delivery and Docker Overview
Continuous Delivery (CD) is an engineering practice where code changes are automatically built,
tested, and prepared for release to production. It's a key part of DevOps philosophy.
• Core Insight: CD isn't just about speed; it's about reducing risk and building quality into the
process. By ensuring that the codebase is always in a releasable state, organizations can deploy
software changes at any time, on demand, with high confidence.
• Key Benefits:
o Lower Risk Deployments: Frequent, small changes are less risky to deploy than
infrequent, large ones.
o Better Product Quality: Automated and exhaustive testing in the pipeline catches
issues early.
o Improved Feedback Loop: Developers get rapid feedback on their changes, leading to
faster iteration.
1. Commit/Code: Developer commits code to the version control system (e.g., Git).
Docker is a platform for developing, shipping, and running applications using containerization. A
container is a lightweight, portable, and self-sufficient executable package that includes everything
needed to run a piece of software, including the code, runtime, libraries, environment variables, and
config files.
• Core Insight: Docker solves the "it works on my machine" problem. By packaging the
application and its environment together, it guarantees consistency across development,
testing, staging, and production environments. It abstracts the operating system differences,
providing isolation.
o docker **pull** <image>: Fetches an image from a registry (like Docker Hub).
o docker **build** -t <tag> .: Builds a Docker image from a Dockerfile in the current
directory.
o docker **run** <image>: Creates and starts a container from an image. Often
combined with flags like -d (detached mode), -p (port mapping), and --name.
o docker **ps**: Lists running containers. docker ps -a lists all containers (running and
stopped).
• Images: Read-only templates built from a Dockerfile. They are the blueprints for containers,
composed of layered filesystems that are highly efficient for sharing and storing. Images are
static.
• Containers: Runnable instances of an Image. They run the specified application and
environment in an isolated space. Containers are dynamic; they have a read/write layer on top
of the image layers, meaning changes made inside a running container are unique to that
instance (until it's stopped/removed). The application runs inside the container's isolated
process.
Docker File
The Dockerfile is a text file containing instructions for Docker to build an Image. Each instruction
creates a new layer in the image, promoting immutability and efficiency.
• Key Instructions:
o COPY <source> <dest>: Copies files from the local machine into the image.
o RUN <command>: Executes a command during the image build process (e.g., installing
dependencies).
o EXPOSE <port>: Documents which ports the application inside the container listens on
(doesn't publish them).
• Running Containers: Use docker run. Port mapping (-p 8080:80) is crucial to access the service,
as containers run in network isolation. The application runs as the main process within the
container.
• Working with Containers: This involves using docker logs to view output, docker exec to debug
or run one-off commands inside the container, and docker inspect to view detailed container
configuration (IP address, volumes, etc.).
Docker Hub is the world's largest public registry for Docker images.
• Process:
1. Tagging: Tag the local image with your Docker Hub username and repository name:
docker tag <local_image> <username>/<repo>:<tag>.
• Core Insight: Publishing to a registry allows the image (the application artifact) to be consumed
consistently by other parts of the CI/CD pipeline, staging environments, and production
orchestration tools (like Kubernetes).
Testing Tools
Introduction to Selenium and its features
Selenium is a portable framework for automated testing of web applications. It is primarily used for
end-to-end (E2E) and User Interface (UI) testing by simulating user interactions with a browser.
• Core Insight: Selenium enables browser automation. It directly controls the web browser
(Chrome, Firefox, etc.) as a real user would, allowing testers to validate functionality,
appearance, and performance across different browsers and operating systems.
• Key Features:
o Selenium Grid: Allows for the parallel execution of tests across multiple machines and
browser versions, significantly reducing test run time, a critical feature for fast CI/CD
pipelines (often deployed using Docker).
JavaScript Testing
JavaScript testing generally falls into three categories: Unit, Integration, and End-to-End (E2E) testing.
The ecosystem is rich with specific tools tailored for each level.
o Tools: Jest (popular for React, generally a fast all-in-one runner), Mocha (flexible,
extensible framework), Jasmine (behavior-driven development framework).
o Insight: Unit tests provide the fastest feedback loop and ensure individual
components work correctly in isolation.
o Tools: Often uses the same frameworks as unit testing (Jest/Mocha) but with more
complex setup, simulating service interactions (e.g., API calls).
o Insight: Confirms that interfaces between parts of the system are correct, catching
issues that individual unit tests might miss.
The integration of Docker with Selenium (running tests in consistent, isolated, and parallelized
containers) is a powerful pattern for reliable Continuous Deployment.
The primary goal of CD is to ensure the software is always in a releasable state. It achieves this by
forcing teams to work in small batches.
• Traditional Approach: Teams integrate code infrequently, leading to massive "big bang"
releases with hundreds of changes. When a bug occurs in production, it's nearly impossible to
isolate which of those hundreds of changes caused it, leading to prolonged downtime and
frantic debugging.
• CD Approach: Code is integrated and run through the pipeline multiple times a day. Each
deployment artifact contains only a few changes. If a production incident occurs, the cause is
immediately narrowed down to the handful of changes in that single, recent deployment. This
drastically reduces the "blast radius" of any failure.
CD is the engine that drives an agile business. It ensures the time from a business idea to a customer
seeing that feature is measured in hours or days, not months.
• Insight: Getting new features to customers quickly means learning quickly. If a feature is
unpopular or has a usability flaw, the business learns this in days, not after spending months
developing an unwanted product. This enables teams to "fail fast" and iterate rapidly based
on real user feedback.
By automating the build, testing (unit, integration, and UI), and deployment steps, CD creates an
objective, repeatable process that removes human error from the pipeline.
High. If the release fails, the site is Low. If a deployment fails, only a tiny change is
down for hours, requiring a costly, the culprit, which can be fixed and deployed in
Risk of Failure
manual rollback of the entire minutes (roll-forward) or automatically reverted
complex batch of changes. (roll-back) with a single command.
Export to Sheets
Conclusion
For the CD-Enabled Startup, releases are no longer a stressful, all-hands-on-deck event. They are a
trivial consequence of development. This allows the team to focus 99% of their energy on innovation
and delivering value, rather than on the mechanics and trauma of deployment. This is the ultimate
importance of Continuous Delivery.
o A developer commits code to the Version Control System (VCS), like Git, triggering the
pipeline.
2. Build (CI):
o The code is compiled into a single, immutable artifact (e.g., a Docker image, JAR file,
or executable).
3. Test (CI):
o Unit Tests, Integration Tests, and Static Analysis run rapidly. Any failure immediately
stops the pipeline and notifies the developer.
o More comprehensive tests run: End-to-End (E2E) Tests, Performance/Load Tests, and
Security Scans (DAST).
o Real-time monitoring and alerting tools (Observability) track key metrics (error rates,
latency) and will automatically trigger an automated rollback if a predefined alert
threshold is breached.
Pipeline
Action Triggered by Pipeline Insight on Automation
Stage
A developer pushes a small code change to Starts the flow. The system knows a
Commit
Git for a new "Dark Mode" CSS file. change exists.
The system builds the new container image Builds Trust. The change is proven
Build/Test and runs 10,000 automated Unit/Integration compatible with the existing 100% of the
tests. codebase in minutes.
The most significant aspect of Continuous Deployment is the fundamental culture shift it represents:
It replaces the philosophy of "Release slowly to avoid failure" with "Test thoroughly and fail fast to
recover instantly."
This is why major tech companies often deploy hundreds of times a day. Their confidence is placed
entirely in the automated test and monitoring suite, allowing them to prioritize speed and
instantaneous customer feedback above the historical need for manual sign-offs.
Docker doesn't just package your code; it packages the entire operating system and environment
necessary to run your code, ensuring consistency and portability across development, testing, and
production.
Before Docker, deploying an application involved installing the application's code, plus its specific
dependencies (e.g., Python 3.8, a certain version of PostgreSQL client library, specific operating system
patches, etc.) onto a server. This led to environmental drift, where minor differences between the
developer's machine, the staging server, and the production server would cause bugs.
• The Docker Solution: Docker uses a concept called Containerization. A Docker container is a
lightweight, executable package that includes everything needed to run a piece of software:
the code, runtime, system tools, system libraries, and settings. This package is called a Docker
Image.
• The Insight: Since the environment inside the image is identical everywhere, the deployment
becomes predictable. If it works in the container on the developer's laptop, it will work exactly
the same way in the container on the production server.
2. Efficiency and Resource Management
Docker containers share the host operating system's kernel, making them much lighter and faster than
traditional Virtual Machines (VMs).
• VM: Each VM requires its own full copy of an operating system (OS), including the kernel,
making it heavy, slow to boot, and resource-intensive.
• Container: Containers abstract at the OS level (user space). They share the host OS kernel,
making them incredibly lightweight. A container can start in milliseconds and uses far less
memory. This allows a single server to run significantly more isolated applications.
The Docker Image becomes the single source of truth for the application and its environment.
• This single artifact can be moved seamlessly from a local development machine to a cloud
VM, a Kubernetes cluster, or an on-premise data center without changes. This dramatically
simplifies the Continuous Delivery (CD) pipeline.
A zipped Python project file and a document A single Docker Image (e.g., my-
Artifact
with manual installation steps. app:v1.0).
Low. The production VM might have a different High. The container bundles all
Consistency version of a system library than the developer's dependencies, ensuring the exact same
machine, causing a subtle bug. environment runs everywhere.
In essence: Docker turns infrastructure dependency headaches into a single, executable file, allowing
developers to focus on writing code, not configuring environments.
• Role: The Daemon is the "brain" of Docker. It is responsible for building images, running
containers, managing storage volumes, and controlling the network.
• Insight: When you install Docker, you are essentially installing a standardized control plane on
your machine. This abstraction is what allows your Docker commands to work identically
whether you are on Windows, macOS, or a Linux server.
The fundamental workflow with Docker revolves around three major command categories: Images,
Containers, and Cleanup.
Images are the immutable, read-only blueprints that package your application and its entire
environment.
docker **pull** Downloads an image from a The first step to reproducibility—you pull
[image_name] registry (like Docker Hub). a defined, tagged version.
Export to Sheets
You have a simple web app and a file named Dockerfile in your current directory:
# and names the resulting image 'web-app' with the tag 'v1'.
Containers are the live, running instances of an image. They are the isolated, ephemeral environments
where your application executes.
Command Action Insight
Creates and starts a container from The moment the blueprint comes to
docker **run** -d -p
an image, detaching (-d) it and life. Port mapping is critical for
8080:80 [image_name]
mapping ports (-p). accessing the isolated app.
Lists all currently running Shows the live state of your isolated
docker **ps**
containers. application environments.
1. Run the container: Start your image, map the container's internal port 80 to your host's port
8080, and run it in the background (-d).
Bash
Bash
docker ps
3. Inspect the environment: Access the running container's shell to check files or configurations.
Proper containerization involves a lot of temporary assets, so cleaning up is essential to prevent clutter
and save disk space.
docker **rmi**
Removes a local image. Removes the local blueprint.
[image_name]
Export to Sheets
Example: Cleanup
docker rm my-web-app
• The Image is the class in object-oriented programming (OOP)—a static, read-only definition.
• The Container is the object (or instance)—a dynamic, running realization of that definition.
A Docker Image is a lightweight, standalone, executable package of software that includes everything
needed to run an application: code, runtime, libraries, environment variables, and config files.
Deep Insights:
• Layered File System (The Key to Efficiency): Images are built using a Union File System (UFS),
meaning they are composed of a stack of read-only layers. Each command in a Dockerfile (e.g.,
RUN, COPY) creates a new layer.
o Insight: If you have 10 applications based on the same Ubuntu base image, that base
layer is stored only once on your system. This drastically reduces storage space and
speeds up image distribution, as only the new, unique layers need to be downloaded
or copied.
• Immutability and Trust: Once an image is built, it never changes. If you need to fix a bug, you
don't modify the existing image; you build a new image with a new tag (e.g., app:v1.1).
o Insight: This guarantees that the image tested in QA is the exact same binary artifact
deployed to production, eliminating configuration errors and environmental drift.
• Portability: An image is designed to run the same way on any operating system that has the
Docker Engine installed.
o Insight: This makes the image the universal unit of software delivery in the cloud-
native world.
A Docker Container is a runtime instance of a Docker Image. It is a live process running in an isolated
environment on a host machine.
Deep Insights:
• The Read/Write Layer (The Key to Isolation): When a container starts from an immutable
image, Docker adds a single, thin read/write layer on top of the image's read-only layers.
o Insight: Any changes made while the container is running (e.g., creating a file, writing
a log) happen only in this top read/write layer. The original image remains untouched.
When the container is deleted, this ephemeral layer is destroyed, ensuring a clean
slate for the next container started from the same image. This is why containers are
considered ephemeral.
• Resource Isolation (via Linux Kernel Features): Containers achieve isolation using two
fundamental Linux kernel features:
o Namespaces: Provide the container with its own isolated view of the system (its own
process ID space, network interface, hostname, etc.).
o cgroups (Control Groups): Limit the amount of resources (CPU, memory, disk I/O) the
container can consume.
o Insight: This is the core difference from Virtual Machines (VMs). Containers are simply
isolated processes running on the host OS kernel, making them much lighter and
faster than full VMs.
• Process-Centric: A container is typically designed to run a single main process (e.g., a web
server). When that main process exits, the container stops.
Action Built or Pulled from Docker Hub Started (docker run) and Stopped (docker stop)
Concept Image (httpd:2.4) Container (Instance of httpd:2.4)
The Apache HTTP Server code and A live, isolated Apache server responding to
Example
configuration files. requests on port 80.
In summary: The Docker Image provides the assurance that your application's environment is defined
and immutable. The Docker Container provides the isolation and ephemeral execution of that assured
environment. This duality of static blueprint (Image) and dynamic instance (Container) is the
foundation of modern, scalable application deployment.
The deeper insight into Dockerfile, running containers, working with containers, and publishing to
Docker Hub is that they collectively form the complete DevOps lifecycle for a single microservice. This
workflow establishes a repeatable, automated path that transforms simple application code into a
highly portable, shareable, and runnable artifact.
This process is about codifying everything an application needs, from its build instructions to its
distribution method.
The Dockerfile is the core of Docker's philosophy, representing Infrastructure as Code (IaC) at the
application level. It is a plain text file that contains a sequence of instructions used to automatically
build a Docker Image.
The most critical insight is how the Docker build process uses layer caching based on the immutable,
ordered instructions in the Dockerfile.
• Instruction: Each command in a Dockerfile (like FROM, RUN, COPY) creates a new, read-only
layer.
• Caching: Docker checks if the instruction and its context have changed since the last build. If
they haven't, it uses the cached layer, dramatically speeding up subsequent builds.
• Optimization Strategy: To maximize this caching, slow-changing instructions (like the base OS
and system dependencies) should be placed before frequently changing instructions (like the
application code).
Dockerfile Instruction Purpose Insight on Efficiency
RUN apt-get update && Placed high to benefit from cache reuse across
Installs base dependencies.
apt-get install python3 code changes.
Running a container (docker run) transforms the static Image into a live, isolated environment. Working
with containers involves managing their interaction with the host system and the outside world.
The primary power of the running container is its isolation from the host system.
• Networking Isolation: By default, containers are isolated. You must explicitly map a port using
the -p flag (e.g., -p 8080:80) to expose the container's internal services to the outside world.
o Insight: This means a container running a web server on port 80 won't conflict with
another application on the host using the same port 80, unless you map them
incorrectly.
• Storage Isolation (The Read/Write Layer): As noted, all runtime changes are ephemeral. To
make data persistent (e.g., database files, log files), you must use a Docker Volume with the -
v flag.
docker exec -it Allows you to temporarily break into the isolated process's environment for
[container_id] sh real-time debugging and inspection.
Command Deep Insight on Isolation
Accesses the container's standard output stream, respecting the principle that
docker logs
containers should write logs to stdout/stderr for the Docker Daemon to
[container_id]
collect.
Docker Hub (or any container registry) serves as the centralized repository for storing and distributing
your Docker Images.
Publishing an image requires tagging, which is more than just a name—it's the version control
mechanism for your entire codified environment.
• The Tagging Rule: Before pushing, you must tag the image with the registry path: docker tag
local-image:latest dockerhub-username/repo-name:tag.
• The Workflow: A typical process involves building an image, tagging it with a specific version
(e.g., v2.5.1), and also tagging it as latest.
Specific Tag Marks a production-ready, known- Ensures pinning—users can always pull the
(v2.5.1) good build. exact version that was tested.
Moving Tag Always points to the most recently Provides a convenient default for users who
(latest) published stable build. don't care about specific versioning.
This final step completes the microservice DevOps loop: Code Dockerfile Image (Build) Container
(Test) Registry (Distribute).
Testing Tools:Selenium and JavaScript testing
The profound insight into Selenium and JavaScript testing is that they represent two distinct, yet
complementary, approaches to ensuring web application quality: External End-to-End (E2E) UI Testing
(Selenium) and Internal Component/Unit Testing (JavaScript Frameworks).
Selenium validates the entire user experience from the outside, acting as a human would, while
JavaScript testing frameworks validate the smallest building blocks of the application from the inside,
ensuring reliability at the source code level. Together, they create a robust quality assurance strategy.
Selenium is an open-source suite of tools designed to automate web browsers for testing purposes. It
provides a way to write scripts that mimic user interactions (clicks, form inputs, navigation) and verify
the application's behavior and user interface (UI) in real browsers.
Selenium operates as a "Black Box" testing tool. It doesn't care how the code is structured internally;
it only cares that the final, rendered webpage works correctly for the end-user. It tests the application
as a complete system, catching errors related to integration, deployment, and overall user flow.
Export to Sheets
This script logs into a dummy website and verifies the successful login.
Python
driver = [Link](service=service)
try:
username_field.send_keys("testuser")
print("Entered username.")
password_field.send_keys("password123")
print("Entered password.")
login_button.click()
except Exception as e:
finally:
# 3. Cleanup
[Link]()
JavaScript testing refers to the use of dedicated frameworks (like Jest, Mocha, and Cypress) to test the
application's code modules, components, and logic before they are integrated or deployed.
This is "White Box" testing, where the internal structure and logic of the code are known and explicitly
tested. It validates the code at the developer level, catching bugs early and providing fast feedback.
• Unit Testing (Jest, Mocha): Tests the smallest isolated parts of the application (e.g., a single
function).
o Insight: Extremely fast and pinpoint failure location precisely. This is the first line of
defense against bugs.
• Component Testing (React Testing Library, Vue Test Utils): Tests UI components in isolation
(e.g., a "Login Form" component).
JavaScript
// [Link]
function sum(a, b) {
}
return a + b;
[Link] = sum;
JavaScript
// [Link]
expect(sum(1, 2)).toBe(3);
});
expect(sum(-1, 1)).toBe(0);
});
});
});
o npm test
o Output: A console message showing that 3 tests passed with 100% code coverage for
the [Link] file.
Synthesis of Approaches
User experience, integration, and final Code logic correctness and individual
Goal
product validation. component reliability.
Feedback Slow (Requires building, deploying, and Fast (Runs in milliseconds in the [Link]
Speed full browser setup). environment).
Broad (Can't easily pinpoint the Pinpoint (Identifies the exact function and
Failure Scope
function that failed). line of code that failed).
Question bank
1. A key challenge in Continuous Delivery (CD) is maintaining environment parity. How
does Docker address this issue, and why is this critical for achieving true CD reliability?
(Bloom's Level 3 - Application)
2. Which sequence of Docker commands correctly prepares and publishes the image?
(Bloom's Level 3 - Application)
3. Differentiate the roles of the CMD and ENTRYPOINT instructions within a Dockerfile
and explain how they interact to define the executable when a container is run.
(Bloom's Level 2 - Comprehension).
4. Demonstrate the combination of two Docker commands you would use to confirm
the container is running and then access its real-time internal process output to find
potential errors? (Bloom's Level 3 - Application)
5. Explain the rationale for splitting the COPY instructions, in Dockersfile. (Bloom's Level
3 - Application)
6. Bring out the primary difference in persistence and modification between a Docker
Image and a Docker Container? (Bloom's Level 2 - Comprehension)
7. A Continuous Integration (CI) build pipeline for a microservice fails during the npm test
step. The tests are written using a JavaScript framework like Jest and specifically check
if a single class method, [Link](id), correctly returns a validated user
object. Based on the scope of the code being tested, what type of testing is most likely
failing? (Bloom's Level 3 - Application)
Bit Bank:
Corre
ct
# Question Options Bloom's Level
Answ
er
Which fundamental
Docker component is
defined as a read-only
A. Docker Daemon B. Docker Container C. Level 2
3 template composed of C
Docker Image D. Docker CLI (Comprehension)
layered filesystems and
serves as the blueprint for
containers?
Which instruction in a
Dockerfile is used to
execute a command during
Level 2
5 the image build process A. CMD B. EXPOSE C. RUN D. ENTRYPOINT C
(Comprehension)
(e.g., installing
dependencies) and creates
a new layer?
Corre
ct
# Question Options Bloom's Level
Answ
er
# Question Answer
To list all currently running containers on your system, you would use the
3 docker ps
________ command.
When a Container is started, Docker adds a single, thin ________ layer on top read/write (or
4
of the image's read-only layers for runtime state changes. writable)
# Question Answer
The Dockerfile instruction ________ specifies the starting base image, such as
5 FROM
node:18-alpine.
To make a local image available to a remote CI/CD pipeline, the final step after
6 docker push
tagging the image is to use the ________ command to upload it to the registry.
The ________ framework allows for the parallel execution of Selenium tests
7 Selenium Grid
across multiple machines and browser versions, speeding up the test run time.