Docker Compose

Docker Compose is a tool that enables you to define multiple containers and their dependencies in a declarative yml file. YAML (YAML Ain’t Markup Language) is a declarative language similar to JSON but aimed at making it more readable by humans. Rather than surrounding everything in quotes and brackets like JSON does, it uses indentation for hierarchy. Developers like Docker Compose because it’s more readable than the Docker command line and makes it easy to compose and connect multiple containers in a declarative way. The best way to understand Compose is by opening the Docker Compose file at:

c:Users<username>DocumentsDockerBookcatalogsrcProductCatalog
docker-compose.yml

or on a Mac

~/DockerBook/catalog/ProductCatalog/src/ProductCatalog/docker-
compose.yml.


Image Visual Studio Code

Visual Studio Code has awesome support for Docker Compose files, including IntelliSense, colorization, formatting, inline help (mouse over a Compose element to see help pulled directly from Docker’s web site), and even real-time image name lookup (start typing the name of an image and it’ll pull the image metadata directly from Docker Hub).


As you can see, this compose file does many of the same things we did on the Docker command line. Read through the file and we’ll review in more detail below:

productcatalog:
  image: "thedanfernandez/productcatalog"
  ports:
    - "80:80"
  tty: true
  links:
    - elasticsearch
  environment:
    - server.urls=http://*:80
elasticsearch:
  image: "elasticsearch"
  ports:
    - "9200:9200"

At a high level, this compose file creates two containers using the arbitrary labels, “productcatalog” and “elasticsearch.” The elasticsearch container is simple to explain as it does what our previous Docker run instruction did: it uses the official elasticsearch image and listens on port 9200.

The “productcatalog” container represents the ASP.NET Core 1.0 microservice and has many similarities to the Docker run command we used before. It uses a base image from thedanfernandez/productcatalog which includes the source code “baked” into the image using the Dockerfile ADD command, which adds the source code into the image. It also does the common steps you’ve seen before such as opening port 80 for the host and container, turning on tty, and setting the server.urls environment variable to tell the ASP.NET web server to listen on port 80.

Linked Containers

Container linking is a special Docker feature that creates a connection between two running containers. productcatalog has a link defined to the elasticsearch container. Instead of having to define a brittle connection string in our app to a specific IP address to the elasticsearch data store, container linking will inject a set of environment variables into the productcatalog container that includes a connection string to the elasticsearch service so that two containers can easily communicate to each other without a hardcoded connection string.

One thing to keep in mind is that you cannot link containers across multiple Docker hosts as both containers must run on the same host. To achieve that, you can use Docker’s overlay networking feature which provides a way to connect multiple Docker hosts using a discovery service like Consul. We will discuss Docker networking in more detail in Chapter 5.

Container Dependencies

Container linking also defines a dependency and order of instantiation for containers. Because the productcatalog container is linked to and depends on the elasticsearch container to run, Docker Compose will create the elasticsearch container first, and then create the productcatalog container.

ASP.NET and Environment Variables

ASP.NET Core 1.0 includes a fully extensible way to store configuration settings. In the example below, we have two sets of configuration settings, a JSON file named config.json and environment variables. Because environment variables are added after the JSON file in the ConfigurationBuilder class, they take precedence, and overwrite any variable with the same name defined in the config.json file. This is perfect for our container linking example as we can take the injected environment variables from the linked container (ELASTICSEARCH_PORT) and replace the connection URL to elasticsearch defined in config.json dynamically.

Public Iconfiguration Configuration { get; private set; }
public Startup(IapplicationEnvironment env)
{
  var builder = new ConfigurationBuilder(env.ApplicationBasePath)
  .AddJsonFile("config.json")
  .AddEnvironmentVariables();
  Configuration = builder.Build();
}

To run our Docker Compose file and have the containers run detached (in the background), type the following command. Your working directory needs to be the directory that contains the docker-compose.yml file. This is shown in Figure 4.7:

docker-compose –d up

Image

FIGURE 4.7: Running Docker Compose

Notice that Docker Compose created the elasticsearch container first, and then the productcatalog container based on the linked container dependency. The name of the running container is the lowercased folder name, so creating the elasticsearch image in the “ProductCatalog” folder created “productcatalog_elasticsearch_1.” You can run further commands with Docker Compose, like docker-compose ps to see the status of the two containers. Similarly, we can type docker-compose stop to stop both containers.

Smart Restart

Docker Compose is also smart in that, where possible, it will detect the current state of containers and only change/restart if there is something newer. For example, if you change the Catalog microservice and don’t change the Elasticsearch container, and then run a docker-compose up command, Docker Compose won’t stop and recreate the Elasticsearch container because it can detect there are no changes. This is shown in Figure 4.8.

Image

FIGURE 4.8: Docker Compose recreating only changed containers

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.123.34