โŒ

Reading view

There are new articles available, click to refresh the page.

Tasks โ€“ Docker

  1. Install Docker on your local machine. Verify the installation by running the hello-world container.
  2. Pull the nginx image from Docker Hub and run it as a container. Map port 80 of the container to port 8080 of your host.
  3. Create a Dockerfile for a simple Node.js application that serves โ€œHello Worldโ€ on port 3000. Build the Docker image with tag my-node-app and run a container. Below is the sample index.js file.

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Hello World');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

4. Tag the Docker image my-node-app from Task 3 with a version tag v1.0.0.

5. Push the tagged image from Task 4 to your Docker Hub repository.

6. Run a container from the ubuntu image and start an interactive shell session inside it. You can run commands like ls, pwd, etc.

7. Create a Dockerfile for a Go application that uses multi-stage builds to reduce the final image size. The application should print โ€œHello Dockerโ€. Sample Go code.


package main

import "fmt"

func main() {
    fmt.Println("Hello Docker")
}

8. Create a Docker volume and use it to persist data for a MySQL container. Verify that the data persists even after the container is removed. Try creating a test db.

9. Create a custom Docker network and run two containers (e.g., nginx and mysql) on that network. Verify that they can communicate with each other.

10. Create a docker-compose.yml file to define and run a multi-container Docker application with nginx as a web server and mysql as a database.

11. Scale the nginx service in the previous Docker Compose setup to run 3 instances.

12. Create a bind mount to share data between your host system and a Docker container running nginx. Modify a file on your host and see the changes reflected in the container.

13. Add a health check to a Docker container running a simple Node.js application. The health check should verify that the application is running and accessible.

Sample Healthcheck API in node.js,


const express = require('express');
const app = express();

// A simple route to return the status of the application
app.get('/health', (req, res) => {
    res.status(200).send('OK');
});

// Example main route
app.get('/', (req, res) => {
    res.send('Hello, Docker!');
});

// Start the server on port 3000
const port = 3000;
app.listen(port, () => {
    console.log(`App is running on http://localhost:${port}`);
});

14. Modify a Dockerfile to take advantage of Dockerโ€™s build cache, ensuring that layers that donโ€™t change are reused.

15. Run a PostgreSQL database in a Docker container and connect to it using a database client from your host.

16. Create a custom Docker network and run a Node.js application and a MongoDB container on the same network. The Node.js application should connect to MongoDB using the container name.


const mongoose = require('mongoose');

mongoose.connect('mongodb://mongodb:27017/mydatabase', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
}).then(() => {
  console.log('Connected to MongoDB');
}).catch(err => {
  console.error('Connection error', err);
});

17. Create a docker-compose.yml file to set up a MEAN (MongoDB, Express.js, Angular, Node.js) stack with services for each component.

18. Use the docker stats command to monitor resource usage (CPU, memory, etc.) of running Docker containers.

docker run -d --name busybox1 busybox sleep 1000
docker run -d --name busybox2 busybox sleep 1000

19. Create a Dockerfile for a simple Python Flask application that serves โ€œHello Worldโ€.

20. Configure Nginx as a reverse proxy to forward requests to a Flask application running in a Docker container.

21. Use docker exec to run a command inside a running container.


docker run -d --name ubuntu-container ubuntu sleep infinity

22. Modify a Dockerfile to create and use a non-root user inside the container.

23. Use docker logs to monitor the output of a running container.

24. Use docker system prune to remove unused Docker data (e.g., stopped containers, unused networks).

25. Run a Docker container in detached mode and verify that itโ€™s running in the background.

26. Configure a Docker container to use a different logging driver (e.g., json-file or syslog).

27. Use build arguments in a Dockerfile to customize the build process.


from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, Docker Build Arguments!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

28. Set CPU and memory limits for a Docker container (for busybox)

Docker Ep 9: The Building Blocks โ€“ Detailed Structure of a Dockerfile

Alex now knows the basics, but itโ€™s time to get their hands dirty by writing an actual Dockerfile.

The FROM Instruction: Choosing the Foundation

The first thing Alex learns is the FROM instruction, which sets the base image for their container. Itโ€™s like choosing the foundation for a house.

  • Purpose:
    • The FROM instruction initializes a new build stage and sets the Base Image for subsequent instructions.
  • Choosing a Base Image:
    • Alex decides to use a Python base image for their application. They learn that python:3.9-slim is a lightweight version, saving space and reducing the size of the final image.

FROM python:3.9-slim

Example: Think of FROM as picking the type of bread for your sandwich. Do you want white, whole wheat, or maybe something gluten-free? Your choice sets the tone for the rest of the recipe.

The LABEL Instruction: Adding Metadata (Optional)

Next, Alex discovers the LABEL instruction. While optional, itโ€™s a good practice to include metadata about the image.

  • Purpose:
    • The LABEL instruction adds metadata like version, description, or maintainer information to the image.
  • Example:
    • Alex decides to add a maintainer label:

LABEL maintainer="alex@example.com"

Story Note: This is like writing your name on a sandwich wrapper, so everyone knows who made it and whatโ€™s inside.

The RUN Instruction: Building the Layers

The RUN instruction is where Alex can execute commands inside the image, such as installing dependencies.

  • Purpose:
    • The RUN instruction runs any commands in a new layer on top of the current image and commits the results.
  • Example:
    • To install the Flask framework, Alex writes:

RUN pip install flask

They also learn to combine commands to reduce layers:


RUN apt-get update && apt-get install -y curl

Story Note: Imagine slicing tomatoes and cheese for your sandwich and placing them carefully on top. Each ingredient (command) adds a layer of flavor.

The COPY and ADD Instructions: Bringing in Ingredients

Now, Alex needs to bring their application code into the container, which is where the COPY and ADD instructions come into play.

  • COPY:
    • The COPY instruction copies files or directories from the host filesystem into the containerโ€™s filesystem.
  • ADD:
    • The ADD instruction is similar to COPY but with additional features, like extracting compressed files.
  • Example:
    • Alex copies their application code into the container:

COPY . /app

Story Note: This is like moving ingredients from your fridge (host) to the counter (container) where youโ€™re preparing the sandwich.

The WORKDIR Instruction: Setting the Workspace

Alex learns that setting a working directory makes it easier to manage paths within the container.

  • Purpose:
    • The WORKDIR instruction sets the working directory for subsequent instructions.
  • Example:
    • Alex sets the working directory to /app:

WORKDIR /app

Story Note: This is like setting up a designated area on your counter where youโ€™ll assemble your sandwichโ€”keeping everything organized.

The CMD and ENTRYPOINT Instructions: The Final Touch

Finally, Alex learns how to define the default command that will run when the container starts.

  • CMD:
    • Provides defaults for an executing container, but can be overridden.
  • ENTRYPOINT:
    • Configures a container that will run as an executable, making it difficult to override.
  • Example:
    • Alex uses CMD to specify the command to start their Flask app:

CMD ["python", "app.py"]

Story Note: Think of CMD as the final step in making your sandwichโ€”like deciding to add a toothpick to hold everything together before serving.

Below is an example Dockerfile of a flask application,


# Use an official Python runtime as a parent image
FROM python:3.9-slim

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Breakdown of the Dockerfile:

  1. FROM python:3.9-slim:
    • This line specifies the base image. In this case, it uses a slim version of Python 3.9, which is lightweight and sufficient for a simple Flask application.
  2. WORKDIR /app:
    • This sets the working directory inside the container to /app. All subsequent commands will be run inside this directory.
  3. COPY . /app:
    • This copies everything from your current directory on the host machine into the /app directory inside the container.
  4. RUN pip install โ€“no-cache-dir -r requirements.txt:
    • This installs the necessary Python packages listed in the requirements.txt file. The --no-cache-dir option reduces the image size by not caching the downloaded packages.
  5. EXPOSE 80:
    • This makes port 80 available for external access. Itโ€™s where the Flask application will listen for incoming requests.
  6. ENV NAME World:
    • This sets an environment variable NAME to โ€œWorldโ€. You can access this variable in your Python code.
  7. CMD [โ€œpythonโ€, โ€œapp.pyโ€]:
    • This tells the container to run the app.py file using Python when it starts.

Example Flask Application (app.py):

To complete the example, hereโ€™s a simple Flask application you can use:


from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    name = os.getenv('NAME', 'World')
    return f'Hello, {name}!'

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

Example requirements.txt:

And hereโ€™s the requirements.txt file listing the dependencies for the Flask app:


Flask==2.0.3

Building and Running the Docker Image:

  1. Build the Docker image using the Dockerfile:
docker build -t my-flask-app .

2. Run the Docker container:


docker run -p 4000:80 my-flask-app
  • This maps port 4000 on your host machine to port 80 in the container.

Open your browser and go to http://localhost:4000, and you should see โ€œHello, World!โ€ displayed on the page.

You can customize the ENV NAME in the Dockerfile or by passing it as an argument when running the container:


docker run -p 4000:80 -e NAME=Alex my-flask-app

This will display โ€œHello, Alex!โ€ instead.

Docker Ep 5 : THE Bakery, Recepies, Dough & Cookies โ€“ Registry, Repository, Images, Containers

In the bustling town of Tambaram, there was a famous factory known for its delicious cookies. This factory had a unique and modern way of making and distributing its cookies, using a system inspired by Dockerโ€™s architecture.

The Recipe Registry

At the heart of the cookie-making process was the Recipe Registry, a giant digital library that stored all the cookie recipes. This registry was like a magical cookbook, holding secrets to every type of cookie imaginable: chocolate chip, oatmeal raisin, and even double fudge delight.

  • Purpose: The Recipe Registry ensured that everyone had access to the latest and greatest recipes. Bakers from all around the world could upload new recipes or download existing ones to make their own cookies.

The Cookie Repository

Each type of cookie had its own Cookie Repository within the Recipe Registry. These repositories were specialized sections where all the different variations of a particular cookie recipe were stored.

  • Example: The chocolate chip cookie repository contained recipes for classic, vegan, gluten-free, and extra gooey versions. Each version was labeled with a tag, like classic, vegan, or gooey.

The Image: A Perfect Cookie Dough

In the factory, the term โ€œImageโ€ referred to the perfect cookie dough that was ready to be baked into cookies. Each image was a complete package containing the recipe, ingredients, and instructions needed to make the cookies.

  • Characteristics: Just like a Docker image, the cookie dough was consistent and repeatable. No matter how many times you used the recipe, you always got the same delicious dough, ready to be baked.

The Container: Freshly Baked Cookies

Once the cookie dough was prepared, it was placed into a Container, representing a batch of freshly baked cookies. Each container was like a magical oven that turned the dough into cookies.

  • Isolation: Each container baked cookies independently, ensuring that the flavor and quality were perfect every time. Bakers could create multiple containers from the same dough image, producing countless batches of cookies.

The Cookie Delivery System

With the help of the Recipe Registry, Cookie Repository, Images, and Containers, the factory had an efficient Cookie Delivery System. This system allowed the factory to distribute its cookies all over Tambaram and beyond.

  • Scalability: If a bakery needed more cookies, they simply created more containers using the same dough image, ensuring everyone had enough cookies to enjoy.

Letโ€™s try directly in to the concepts,

Registry

  • Definition: A Docker Registry is a storage and content delivery system that holds Docker images.
  • Purpose: It is used to manage where Docker images are stored and distributed from.
  • Examples: Docker Hub (the default public registry), Amazon ECR, Google Container Registry, and Azure Container Registry.
  • Functionality: Registries can be public or private. They store Docker images and provide an interface to push (upload) or pull (download) these images to and from repositories.

Docker Hub is the default public registry used by Docker. Here are examples of Docker Hub registry links:

  • Official Image: docker pull nginx

Community Image: docker pull username/repository:tag

Repository

  • Definition: A Docker Repository is a collection of related Docker images, usually providing different versions of the same application or service.
  • Purpose: Repositories organize and manage multiple images of an application or service.
  • Structure: A repository may contain multiple tagged versions of an image. For example, myapp:latest and myapp:v1.0 might be two tags in the same repository.
  • Functionality: Users can push images to a repository and pull images from a repository. Tags are used to differentiate between different versions of an image.

Official Repositories

Community Repositories

User-Specific Repositories

Images

  • Definition: A Docker Image is a lightweight, standalone, executable package that includes everything needed to run a piece of software: code, runtime, libraries, environment variables, and configuration files.
  • Purpose: Images are used to create containers. They provide a portable and consistent runtime environment.
  • Immutability: Images are immutable; once created, they do not change. If updates are needed, a new image version is created.
  • Layers: Images are built up from a series of layers, where each layer represents an instruction in the imageโ€™s Dockerfile.

For example, Dockerfile will comprises of the layers of instructions. https://hub.docker.com/layers/library/postgres/12.20-bullseye/images/sha256-2092f4af9ad9fff76e8d0b7c04d8c62b561e44c21a850d4a028124426046f6fa?context=explore

Sample dockerfile for postgres, https://github.com/docker-library/postgres/blob/805329e7a64fad212a5d4b07abd11238a9beab75/17/bookworm/Dockerfile

Containers

  • Definition: A Docker Container is a runnable instance of a Docker image. It is a lightweight, standalone, and executable package of software that includes everything needed to run it.
  • Purpose: Containers provide a consistent environment for applications, allowing them to run reliably regardless of where they are deployed.
  • Isolation: Containers are isolated from each other and the host system, but they can communicate with each other through well-defined channels.
  • Lifecycle: Containers can be created, started, stopped, moved, or deleted using Docker commands.

Relationship Between Concepts

  • Registry and Repository: A Docker registry can host multiple repositories. Each repository can contain multiple images with different tags.
  • Repository and Images: A repository serves as a namespace for images. For example, myrepo/myapp can contain different image tags like v1.0, v2.0, etc.
  • Images and Containers: Containers are running instances of images. You can run multiple containers from the same image.

โŒ