Docker - CSU677 - Shoolini U

Docker

1. Introduction to Docker

Docker is an open-source platform that automates the deployment, scaling, and management of applications using containerization. Containers are lightweight, portable, and self-sufficient units that package an application along with all its dependencies, ensuring consistency across different environments. Docker has become a key tool in DevOps, simplifying the process of application development, deployment, and scaling.

2. Understanding Containers

Containers are at the core of Docker. They provide a standardized environment for running applications by encapsulating the application code, libraries, dependencies, and configuration files. Unlike virtual machines, containers share the host system's kernel, making them more efficient and faster to start.

2.1 Containers vs. Virtual Machines

While both containers and virtual machines allow for isolated environments, they differ in several ways:

2.2 How Containers Work

Containers are built using Docker images, which are read-only templates containing the application and its dependencies. When a container is started, Docker creates a writable layer on top of the image, where any changes made during runtime are stored.

2.2.1 Example of a Simple Dockerfile

# Use an official Node.js image as the base image
FROM node:14

# Set the working directory
WORKDIR /app

# Copy the package.json and install dependencies
COPY package.json .
RUN npm install

# Copy the application code
COPY . .

# Expose the port the app runs on
EXPOSE 3000

# Command to run the application
CMD ["npm", "start"]

This Dockerfile defines a simple Node.js application container that installs dependencies, copies the code, and runs the application on port 3000.

3. Docker Images

Docker images are the building blocks of containers. They are immutable templates that include everything needed to run an application, such as the code, runtime, libraries, and environment variables.

3.1 Creating Docker Images

Docker images are created using Dockerfiles, which are scripts that contain a series of instructions to build the image. These instructions specify the base image, application dependencies, configurations, and the command to run the application.

3.1.1 Example of Building an Image

docker build -t my-node-app .

This command builds a Docker image named my-node-app from the Dockerfile in the current directory.

3.2 Docker Image Layers

Each instruction in a Dockerfile creates a new layer in the Docker image. Layers are cached, which means that if a layer has not changed, Docker can reuse it, making the build process faster. This also enables more efficient storage and transfer of images.

3.3 Docker Hub

Docker Hub is a cloud-based registry service where Docker images can be stored and shared. Developers can push their images to Docker Hub and pull them to different environments as needed.

3.3.1 Example of Pushing an Image to Docker Hub

docker login
docker tag my-node-app username/my-node-app
docker push username/my-node-app

This sequence logs into Docker Hub, tags the image, and pushes it to a repository under the user's account.

4. Docker Containers

Once an image is built, it can be used to create a Docker container. Containers are running instances of Docker images, and they can be started, stopped, and managed using Docker commands.

4.1 Running Containers

To run a Docker container, use the docker run command, specifying the image and any necessary options such as port mappings, environment variables, or volumes.

4.1.1 Example of Running a Container

docker run -d -p 3000:3000 --name my-running-app my-node-app

This command runs a container from the my-node-app image, mapping port 3000 on the host to port 3000 in the container, and names the container my-running-app.

4.2 Managing Containers

Docker provides several commands to manage containers, such as listing running containers, stopping or restarting containers, and removing containers when they are no longer needed.

4.2.1 Common Container Management Commands

5. Docker Volumes

Docker volumes are used to persist data generated by a container, allowing it to be stored outside of the container’s filesystem. Volumes are the preferred way to manage data in Docker because they are independent of the container lifecycle and can be shared between multiple containers.

5.1 Creating and Using Volumes

Volumes can be created and attached to containers using the docker volume command. They can be mounted to specific directories inside the container to store data that should persist even after the container is stopped or removed.

5.1.1 Example of Using a Volume

docker volume create my-volume
docker run -d -p 3000:3000 -v my-volume:/app/data --name app-with-volume my-node-app

This command creates a volume named my-volume and attaches it to the /app/data directory in the container.

5.2 Bind Mounts vs. Volumes

Docker supports both bind mounts and volumes for managing data:

6. Docker Networking

Docker provides networking capabilities that allow containers to communicate with each other, with the host machine, and with external networks. Docker automatically creates a bridge network when it starts, which connects all running containers to the host and each other.

6.1 Docker Network Types

Docker supports several types of networks:

6.1.1 Example of Creating and Using a Custom Network

docker network create my-network
docker run -d --name db --network my-network postgres
docker run -d --name web --network my-network my-node-app

This example creates a custom network named my-network and connects two containers to it, allowing them to communicate with each other.

7. Docker Compose

Docker Compose is a tool that simplifies the process of managing multi-container Docker applications. It allows you to define and run multi-container applications using a YAML file, where you specify the services, networks, and volumes needed for the application.

7.1 Docker Compose File

A Docker Compose file is written in YAML and defines the configuration for your application’s services, including the images to use, the ports to expose, the volumes to mount, and the networks to connect.

7.1.1 Example of a Docker Compose File

version: '3'
services:
  web:
    image: my-node-app
    ports:
      - "3000:3000"
    volumes:
      - ./app:/app
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: example

This Docker Compose file defines two services: a web service running a Node.js application and a database service running PostgreSQL.

7.2 Running Docker Compose

Once the Docker Compose file is defined, you can use Docker Compose commands to manage the entire application:

8. Docker Swarm and Orchestration

Docker Swarm is Docker’s native clustering and orchestration tool. It allows you to manage a cluster of Docker engines as a single virtual host. Docker Swarm enables the deployment, scaling, and management of multi-container applications across multiple hosts.

8.1 Setting Up a Docker Swarm

To create a Docker Swarm, you initialize it on a Docker host and add other hosts as nodes to the swarm. The swarm manager orchestrates the distribution of containers across the nodes.

8.1.1 Example of Initializing a Swarm

docker swarm init --advertise-addr 
docker swarm join --token  :2377

This initializes a Docker Swarm on the manager and joins other nodes to the swarm using a token.

8.2 Deploying Services in a Swarm

In Docker Swarm, services are the tasks that run on the swarm nodes. You can deploy services using Docker commands or Docker Compose files.

8.2.1 Example of Deploying a Service

docker service create --name my-web-app --replicas 3 -p 80:80 my-node-app

This command deploys a service running three replicas of a Node.js application on port 80.

8.3 Scaling Services

One of the key features of Docker Swarm is the ability to scale services up or down based on demand. You can adjust the number of replicas running across the swarm with a simple command.

8.3.1 Example of Scaling a Service

docker service scale my-web-app=5

This command scales the my-web-app service to run five replicas.

9. Security in Docker

Security is a critical aspect of Docker, especially when running containers in production environments. Docker provides several security features to help isolate containers, protect data, and secure communications.

9.1 Namespaces and Control Groups (cgroups)

Docker uses Linux namespaces and control groups to isolate containers from each other and the host system. Namespaces provide isolation for resources like process IDs, network interfaces, and file systems, while control groups limit the resources (CPU, memory, I/O) that a container can use.

9.2 Securing Docker Images

Securing Docker images involves using trusted base images, minimizing the attack surface by installing only necessary software, and regularly updating and scanning images for vulnerabilities.

9.3 Docker Content Trust (DCT)

Docker Content Trust allows you to use digital signatures to verify the integrity and authenticity of Docker images. This ensures that only trusted images are used in your environment.

9.3.1 Enabling Docker Content Trust

export DOCKER_CONTENT_TRUST=1

This command enables Docker Content Trust, ensuring that all pulled or pushed images are signed and verified.

9.4 Secrets Management

Docker provides a secure way to manage sensitive data like passwords, API keys, and certificates using Docker secrets. Secrets are encrypted and stored securely, and they can be injected into containers at runtime.

9.4.1 Example of Creating and Using a Secret

echo "my_secret_password" | docker secret create db_password -
docker service create --name my-db --secret db_password postgres

This creates a secret named db_password and makes it available to the my-db service.

10. Best Practices for Docker

Following best practices when using Docker ensures that your containers are efficient, secure, and easy to manage.

10.1 Keep Images Small

Smaller images are faster to build, transfer, and deploy. Use minimal base images, and only include the necessary dependencies for your application.

10.2 Use Multi-Stage Builds

Multi-stage builds allow you to use multiple FROM statements in a Dockerfile, enabling the separation of build-time dependencies from the final image. This reduces the size of the final image by excluding unnecessary files and tools.

10.3 Tag Images Properly

Tagging images with meaningful and versioned tags helps in identifying and managing different versions of your application. Avoid using the latest tag for production deployments, as it can lead to unpredictability.

10.4 Clean Up Resources

Regularly clean up unused images, containers, volumes, and networks to free up disk space and improve Docker’s performance.

10.4.1 Example of Cleaning Up Resources

docker system prune -a

This command removes all stopped containers, unused networks, dangling images, and optionally, all unused images.