Docker for Web Development - Docker-Compose

In the previous posts, we covered Docker Volumes, Dockerfiles, and Container Networks. In this post, we will explore Docker-Compose and how it can help you manage multi-container applications and streamline your web development workflow.

This is a series of posts about Docker for Web Development:

  1. Basic Concepts
  2. Volumes
  3. Custom Images with Dockerfile
  4. Container Networks
  5. Docker-Compose

What is Docker-Compose?

Docker-Compose is a tool that allows you to define and manage multi-container applications using a simple YAML file called docker-compose.yml. With Docker-Compose, you can define the services, networks, and volumes needed for your application in a single file, making it easier to manage and deploy complex applications.

This makes it very easy to start, stop, and manage multiple containers with a single command. Docker-Compose is particularly useful for web development projects that require multiple services, such as a web server, database, and cache.

Basic Structure of a Docker-Compose File

A Docker-Compose file is written in YAML and typically includes the following sections:

  • version: Specifies the version of the Docker-Compose file format.
  • services: Defines the different services (containers) that make up your application.
  • networks: (Optional) Defines custom networks for your services.
  • volumes: (Optional) Defines named volumes that can be shared between services.

There are many other options and configurations available in Docker-Compose, but these are the most commonly used sections.

Here is a simple example of a Docker-Compose file for a web application with a web server and a database:

Copy
version: '3.8'

# Define the services that make up the application
services:
  # Define the api server service
  api:
    # Build the Dockerfile
    build: 
      context: ./api
      dockerfile: Dockerfile
    # Map the container port to the host port
    ports:
      - "3000:3000"
    # Add the container to the custom network
    networks:
      - webnet
    # Define the dependency on the database service. This ensures that the database service is started before the api service.
    depends_on:
      - db
    # This will create 2 instances of the api service, which can be useful for load balancing, scaling the application, and check user session management.
    deploy:
      mode: replicated
      replicas: 2

  # Define the database service
  db:
    # Use the official MySQL image
    image: mysql:5.7
    # Set environment variables for the database
    environment:
      MYSQL_ROOT_PASSWORD: example_password
      MYSQL_DATABASE: example_db
    # Include a named volume to persist database data
    volumes:
      - db_data:/var/lib/mysql
    # Add the container to the custom network
    networks:
      - webnet

# Define named volumes for data persistence
volumes:
  db_data:

# Define custom networks for container communication
networks:
  webnet:
    driver: bridge

Starting and Managing Containers with Docker-Compose

First we need to build the images for the services defined in the docker-compose.yml file. To do this, navigate to the directory containing the docker-compose.yml file and run the following command:

Copy
docker compose build

Then, to start the containers defined in the docker-compose.yml file, navigate to the directory containing the file and run the following command:

Copy
docker compose up

With that command, Docker Compose will start all the services defined in the docker-compose.yml file, creating the necessary containers, networks, and volumes. You can also use the -d flag to run the containers in detached mode:

Copy
docker compose up -d

Docker Compose Commands

Here a list of some useful Docker Compose commands:

  • docker compose build: Build the images for the services defined in the docker-compose.yml file. It is also possible to build a specific service by running docker compose build <service>.
  • docker compose up: Start the services defined in the docker-compose.yml file. It is also possible to start a specific service by running docker compose up <service>, and if you want to make sure that the other dependencies are not restarted (for example, if you want to restart only the api service without restarting the db service), you can use the --no-deps flag: docker compose up --no-deps <service>.
  • docker compose up -d: Start the services in detached mode.
  • docker compose down: Stop and remove the containers, networks, and volumes created by docker compose up. It also cleans up the resources created by Docker Compose, such as networks and volumes. You can also use the --volumes flag to remove the named volumes created by Docker Compose: docker compose down --volumes.
  • docker compose ps: List the running services and their status.
  • docker compose logs: View the logs of the running services.
  • docker compose stop: Stop the running services without removing them.
  • docker compose start: Start the stopped services without recreating them.
  • docker compose restart: Restart the running services.
  • docker compose rm: Remove the stopped services and their containers.
  • <command: Execute a command in a running service container (for example, to open a shell in the api service container, you can run docker compose exec api sh).