Docker for DevOps Engineer : Docker Compose Part-1

Docker for DevOps Engineer : Docker Compose Part-1

👉Introduction to Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to define the services that make up your application, their dependencies, and how they interact with each other. With Docker Compose, you can use a single YAML file to configure and manage your multi-container application.

Structure of a Docker Compose File

A Docker Compose file is a YAML file that defines the services for your application. It typically has the following structure: 👇

version: "3"

services:
  service_name1:
    image: image_name1
    ports:
      - "host_port1:container_port1"
    volumes:
      - volume_name1:/directory1
    environment:
      - environment_variable1=value1
    depends_on:
      - service_name2

  service_name2:
    image: image_name2
    ports:
      - "host_port2:container_port2"
    volumes:
      - volume_name2:/directory2
    environment:
      - environment_variable2=value2

Defining Services

The services section of the Docker Compose file defines the individual services that make up your application. Each service is represented by a nested block that specifies its configuration details.

Image:

The image property specifies the Docker image that will be used for the service. This image should contain the application code, dependencies, and any other necessary configuration.

Ports:

The ports property defines the ports that the service will expose. This allows the service to communicate with other services or external applications. The format for a port mapping is "host_port:container_port", where host_port is the port on the host machine that will be mapped to the container_port on the container.

Volumes:

The volumes property defines persistent storage for the service. This allows the service to store data that will persist even after the container is stopped and restarted. The format for a volume mapping is "volume_name:/directory", where volume_name is the name of the volume and directory is the directory within the container that will be mounted to the volume.

Environment:

The environment property defines environment variables for the service. These environment variables can be used by the application to configure its behavior. The format for an environment variable is "environment_variable=value", where environment_variable is the name of the environment variable and value is its value.

Dependencies:

The depends_on property defines the dependencies between services. This specifies that a service should not be started until the specified dependencies are started. The format is "depends_on: - service_name1 - service_name2", where service_name1 and service_name2 are the names of the services that the current service depends on.

Up and Down Commands

Docker Compose provides two main commands for managing your application:

  • docker-compose.yml: Create & save the docker-compose.yml file in a directory of your project.

  • docker-compose up: This command starts all of the services defined in the Docker Compose file.

      docker-compose up -d
    

    The -d means execute the command in the detached mode. This means that the containers will continue to run in the background.

    To verify that your containers are running or not use docker-compose ps

      docker-compose ps
    

    This command shows the status of your services.

  • docker-compose down:

      docker-compose down
    

    This command stops and removes the containers, networks, and volumes defined in your docker-compose.yml file.

Example Docker Compose File 💻

Here is an example Docker Compose file for a simple web application:

version: "3"

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html

  app:
    build: .
    depends_on:
      - web

This Docker Compose file defines two services: web and app. The web service runs an Nginx web server and exposes port 80 on the host machine. The app service builds the application image from the current directory and depends on the web service being started first.😉

Linking Containers

Docker Compose provides a convenient mechanism for linking containers, allowing them to communicate with each other directly without the need to explicitly configure network settings. This simplifies the process of setting up inter-service communication and promotes loose coupling between components.

To link containers in Docker Compose, you can simply include the names of the linked containers within the links property of the service you want to link. For instance, consider the following example:

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    links:
      - app:app

  app:
    build: .

In this configuration, the web service is linked to the app service. This means that the web service can access the app container using the hostname app.

Using Environment Variables Environment variables provide a way to pass configuration information to containers. Docker Compose allows you to define environment variables for your services within the environment property of the service definition.

services:
  app:
    image: my-application:latest
    environment:
      - DB_HOST=db-container
      - DB_PORT=3306
      - APP_NAME=my-app

In this example, the app service is configured with three environment variables: DB_HOST, DB_PORT, and APP_NAME. These variables will be available to the application running inside the container.

Accessing Linked Containers' Environment Variables

When a container is linked to another container, it can access the environment variables of the linked container. This is achieved using the hostname of the linked container as the prefix for the environment variable name.

For instance, in the previous example, the web service can access the DB_HOST and DB_PORT environment variables of the app container using the following names:

APP_DB_HOST=db-container
APP_DB_PORT=3306

This allows the web service to connect to the database hosted in the app container.

Let's delve into some practical tasks to enhance our understanding of Docker Compose. Refer this --> link for more details. 😉

  1. Pull a pre-existing Docker image from a public repository

     docker pull nginx:latest
    

    This command fetches the latest version of the Nginx image from Docker Hub.

    By default, Docker fetches the latest image available on Docker Hub even if you haven't specified a tag. It is recommended to specify a tag.

  2. Run the container as a non-root user.

    To enhance security, it is recommended to execute containers as non-root users. The docker run command's --user flag will be employed to achieve this.

     docker run --user 1000:1000 -d -p 80:80 --name new_nginx nginx:latest
    
    • --user 1000:1000: Specifies the user and group IDs. Replace these values with appropriate non-root user IDs on your system.

    • -d: Runs the container in the background.

    • -p 80:80: Maps port 80 on the host to port 80 on the container.

    • --name new_nginx: Assigns the name "new_nginx" to the container.

Tip : Make sure you reboot an instance after giving permission to user assuming that you've used usermod

  1. Inspect the container's running processes and exposed ports using the docker inspect command.

  2. Lets use the docker logs command to view the container's log output.

  3. Use the docker stop and docker start commands to stop and start the container.

     docker stop new_nginx
    
     docker start new_nginx
    

    This will restart the container.

  4. Use the docker rm command to remove the container when you're done.

     docker rm mynginx
    

    How to run Docker commands without sudo?

    • Make sure docker is installed and system is updated (This is already been completed as a part of previous tasks):

    • sudo usermod -a -G docker $USER

    • Reboot the machine.

      😎 Happy Docker Learning!!