Docker 101: Docker Compose + Docker Compose Watch

Docker 101: Docker Compose + Docker Compose Watch

PART XI

ยท

6 min read

Docker Compose

Managing all those commands for building images, running containers, and setting up host mappings can indeed be cumbersome. Fortunately, there's a more efficient solution โ€“ Docker Compose. With just a single, straightforward command, Docker Compose empowers you to define and run your entire application effortlessly. It's a game-changer for simplifying the deployment process and orchestrating all the services your application needs in one go.

  • it's a tool that allows us to Define and manage multi-container Docker application

  • it uses a yaml file to configure the services networks and volumes for your application enabling us to run and scale the entire application with single command

  • with a single command we don't have to run 10 commands separately to run 10 containers for one application

Docker init

Using Docker init we initialize our application with all the files needed to dockerize it by specifying our Tech choices inside a yaml file.

docker compose up command

The docker-compose up command is used to start services defined in a docker-compose.yml file. It orchestrates the creation and startup of all the services defined in the docker-compose.yml configuration.

In windows: Need to run as administrator

In mac or linux: sudo docker compose up

CONS

While Docker Compose greatly improves our development workflow by allowing us to manage multiple containers seamlessly and keeping our code changes up-to-date through volumes, there's still room for an even smoother developer experience. Whenever we tweak something in our package files, the need to manually rebuild and rerun the container can be a bit cumbersome. This is where Docker Compose Watch steps in, addressing this gap by automating the process of rebuilding images when necessary. It streamlines our development efforts, making the workflow more dynamic and efficient.

Docker Compose Watch

Docker compose watch listens to our changes and

  • Rebuilding our app

  • Re-running the container

  • sync operation moves changed files from our computer to the right places in the container making sure that everything stays up to date in real time

    • working on any app because it lets us instantly see any changes we make while the app is running
  • Rebuild process starts with the creation of new container images and then it updates the services

    • rolling out changes to applications in production guaranteeing the most recent version of code is operational
  • sync restart operation = sync + rebuild processes: It begins by syncing modifications from the host file system to The Container paths and then restarting the container

    • This is beneficial during the development and testing of applications ensuring that the most recent code version is active with immediate reflection of changes in the running application
  • Done by defining the build section of .yaml file

Example compose.yaml File. with Watch

command: docker compose up

This create a "multi-container-application"

# specify the version of docker-compose
version: "3.8"

# define the services/containers to be run
services:
  # define the frontend service
  # we can use any name for the service. A standard naming convention is to use "web" for the frontend
  web:
    # we use depends_on to specify that service depends on another service
    # in this case, we specify that the web depends on the api service
    # this means that the api service will be started before the web service
    depends_on:
      - api
    # specify the build context for the web service
    # this is the directory where the Dockerfile for the web service is located
    build: ./frontend
    # specify the ports to expose for the web service
    # the first number is the port on the host machine
    # the second number is the port inside the container
    ports:
      - 5173:5173
    # specify the environment variables for the web service
    # these environment variables will be available inside the container
    environment:
      VITE_API_URL: http://localhost:8000

    # this is for docker compose watch mode
    # anything mentioned under develop will be watched for changes by docker compose watch and it will perform the action mentioned
    develop:
      # we specify the files to watch for changes
      watch:
        # it'll watch for changes in package.json and package-lock.json and rebuild the container if there are any changes
        - path: ./frontend/package.json
          action: rebuild
        - path: ./frontend/package-lock.json
          action: rebuild
        # it'll watch for changes in the frontend directory and sync the changes with the container real time
        - path: ./frontend
          target: /app
          action: sync

  # (BACKEND) define the api service/container
  api:
    # api service depends on the db service so the db service will be started before the api service
    depends_on:
      - db

    # specify the build context for the api service
    build: ./backend

    # specify the ports to expose for the api service
    # the first number is the port on the host machine
    # the second number is the port inside the container
    ports:
      - 8000:8000

    # specify environment variables for the api service
    # for demo purposes, we're using a local mongodb instance
    environment:
      DB_URL: mongodb://db/anime

    # establish docker compose watch mode for the api service
    develop:
      # specify the files to watch for changes
      watch:
        # it'll watch for changes in package.json and package-lock.json and rebuild the container and image if there are any changes
        - path: ./backend/package.json
          action: rebuild
        - path: ./backend/package-lock.json
          action: rebuild

        # it'll watch for changes in the backend directory and sync the changes with the container real time
        - path: ./backend
          target: /app
          action: sync

  # define the db service
  db:
    # specify the image to use for the db service from docker hub. If we have a custom image, we can specify that in this format
    # In the above two services, we're using the build context to build the image for the service from the Dockerfile so we specify the image as "build: ./frontend" or "build: ./backend".
    # but for the db service, we're using the image from docker hub so we specify the image as "image: mongo:latest"
    # you can find the image name and tag for mongodb from docker hub here: https://hub.docker.com/_/mongo
    image: mongo:latest

    # specify the ports to expose for the db service
    # generally, we do this in api service using mongodb atlas. But for demo purposes, we're using a local mongodb instance
    # usually, mongodb runs on port 27017. So we're exposing the port 27017 on the host machine and mapping it to the port 27017 inside the container
    ports:
      - 27017:27017

    # specify the volumes to mount for the db service
    # we're mounting the volume named "anime" inside the container at /data/db directory
    # this is done so that the data inside the mongodb container is persisted even if the container is stopped
    volumes:
      - anime:/data/db

# define the volumes to be used by the services
volumes:
  anime:

To enable/update changes in app.:

Run below command in second terminal along with docker compose up.

docker compose watch with admin rights.

REFERNCE

ย