Skip to content

Latest commit

 

History

History
239 lines (197 loc) · 12.6 KB

ch05-compose.adoc

File metadata and controls

239 lines (197 loc) · 12.6 KB

Run Multiple Containers Using Docker Compose

Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running.
— github.com/docker/compose

An application using Docker containers will typically consist of multiple containers. With Docker Compose, there is no need to write shell scripts to start your containers. All the containers are defined in a configuration file using services, and then docker-compose script is used to start, stop, and restart the application and all the services in that application, and all the containers within that service. The complete list of commands is:

Command Purpose

build

Build or rebuild services

help

Get help on a command

kill

Kill containers

logs

View output from containers

port

Print the public port for a port binding

ps

List containers

pull

Pulls service images

restart

Restart services

rm

Remove stopped containers

run

Run a one-off command

scale

Set number of containers for a service

start

Start services

stop

Stop services

up

Create and start containers

The application used in this section will show how to query a Couchbase sample data using simple Java EE application deployed on WildFly. The Java EE application will use JAX-RS to publish REST endpoint which will then be invoked using curl.

WildFly and Couchbase will be running in two separate containers, and thus making this a multi-container application.

Configuration File

  1. Entry point to Docker Compose is Compose file, usually called docker-compose.yml. Create a new directory and a new file docker-compose.yml in it. Use the following contents:

Example 1. Docker Compose with WildFly and Couchbase
version: '2'
services:
  db:
    image: arungupta/couchbase
    ports:
      - 8091:8091
      - 8092:8092
      - 8093:8093
      - 11210:11210
  web:
    image: arungupta/wildfly-couchbase-javaee7
    environment:
      - COUCHBASE_URI=db
    ports:
      - 8080:8080
    depends_on:
      - db

In this Compose file:

  1. Two services in this Compose are defined by the name db and web attributes

  2. Image name for each service defined using image attribute

  3. The arungupta/couchbase image starts Couchbase server, configures it using Couchbase REST API, and loads a sample bucket

  4. The arungupta/wildfly-couchbase-javaee7 image starts WildFly and deploys application WAR file built from https://github.com/arun-gupta/couchbase-javaee. This image built using https://github.com/arun-gupta/docker-images/blob/master/wildfly-couchbase-javaee7/Dockerfile.

  5. Environment variable for WildFly container is defined in environment attribute

  6. Couchbase container is linked with WildFly container using COUCHBASE_URI. This is used in the application code as shown at https://github.com/arun-gupta/couchbase-javaee/blob/master/src/main/java/org/couchbase/sample/javaee/Database.java#L44.

  7. Port forwarding is achieved using ports attribute

  8. depends_on attribute allows to express dependency between services. In this case, Couchbase will be started before WildFly. Application-level health are still user’s responsibility.

Start Application

All services in the applicaiton can be started, in detached mode, by giving the command:

Example 2. Start Docker Compose Services
docker-compose up -d

An alternate compose file name can be specified using -f option.

An alternate directory where the compose file exists can be specified using -p option.

This shows the output as:

Creating network "javaee_default" with the default driver
Pulling db (arungupta/couchbase:latest)...
latest: Pulling from arungupta/couchbase
56eb14001ceb: Pull complete
7ff49c327d83: Pull complete
6e532f87f96d: Pull complete
3ce63537e70c: Pull complete
b8145bb24a3f: Pull complete
e6e203bac6d0: Pull complete
566dfc7d9e85: Pull complete
a2c938a8a28b: Pull complete
c6f4b64cd81f: Pull complete
9471cd6d0816: Pull complete
b5dbff584fd2: Pull complete
cb803d8435bd: Pull complete
5baa1a8990e4: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:30eb344986be80234b1f64e4554b7b9f57b982a1283c7ef6fc6f7d3db9bee70c
Status: Downloaded newer image for arungupta/couchbase:latest
Pulling web (arungupta/wildfly-couchbase-javaee7:latest)...
latest: Pulling from arungupta/wildfly-couchbase-javaee7
a3ed95caeb02: Pull complete
7b4fc7362304: Pull complete
564fd20c9eba: Pull complete
f877a8aab935: Pull complete
939c172e3da6: Pull complete
e375f0165ab7: Pull complete
b4c5559c47a9: Pull complete
Digest: sha256:677716c784347eadd0c11e713ce2a34e1a7bae6cbaec0dc48cde6e82575abb12
Status: Downloaded newer image for arungupta/wildfly-couchbase-javaee7:latest
Creating javaee_db_1
Creating javaee_web_1

Started services can be verified as:

Example 3. Containers Started by Docker Compose
docker-compose ps
           Name                         Command                        State                         Ports
---------------------------------------------------------------------------------------------------------------------
javaee_db_1                   /entrypoint.sh /opt/couchb    Up                            11207/tcp,
                              ...                                                         0.0.0.0:11210->11210/tcp,
                                                                                          11211/tcp, 18091/tcp,
                                                                                          18092/tcp, 18093/tcp,
                                                                                          0.0.0.0:8091->8091/tcp,
                                                                                          0.0.0.0:8092->8092/tcp,
                                                                                          0.0.0.0:8093->8093/tcp,
                                                                                          8094/tcp
javaee_web_1                  /opt/jboss/wildfly/bin/sta    Up                            0.0.0.0:8080->8080/tcp
                              ...

This provides a consolidated view of all the started services, and containers within them.

Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual docker ps command:

Example 4. Containers Started by Docker Compose using docker ps
docker ps
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS                                                                                                         NAMES
325b7b05ee17        arungupta/wildfly-couchbase-javaee7   "/opt/jboss/wildfly/b"   3 minutes ago       Up 3 minutes        0.0.0.0:8080->8080/tcp                                                                                        javaee_web_1
5023a9883de5        arungupta/couchbase                   "/entrypoint.sh /opt/"   3 minutes ago       Up 3 minutes        8094/tcp, 0.0.0.0:8091-8093->8091-8093/tcp, 11207/tcp, 11211/tcp, 0.0.0.0:11210->11210/tcp, 18091-18093/tcp   javaee_db_1

Service logs can be seen using docker-compose logs command. The logs will show some errors. These are because the Java EE application deployed in WildFly is not able to communicate with Couchbase. Let’s understand why.

depends_on attribute in Compose definition file ensures the container start up order. But application-level start up needs to be ensured by the applications running inside container. In our case, WildFly starts up rather quickly but takes a few seconds for the database to start up. This means the Java EE application deployed in WildFly is not able to communicate with the database.

So we need to restart the WildFly service after ~15 seconds to ensure enough time for the Couchbase database to start. Restart the WildFly service using docker-compose restart web command.

Now, the logs will show the application is deployed successfully in WildFly. This can be verified by looking at the logs:

web_1  | 00:06:16,820 INFO  [com.couchbase.client.core.node.Node] (cb-io-1-1) Connected to Node db
web_1  | 00:06:17,096 INFO  [com.couchbase.client.core.config.ConfigurationProvider] (cb-computations-1) Opened bucket travel-sample
web_1  | 00:06:17,968 INFO  [org.jboss.resteasy.spi.ResteasyDeployment] (ServerService Thread Pool -- 59) Deploying javax.ws.rs.core.Application: class org.couchbase.sample.javaee.MyApplication
web_1  | 00:06:18,042 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 59) WFLYUT0021: Registered web context: /airlines
web_1  | 00:06:18,077 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 34) WFLYSRV0010: Deployed "airlines.war" (runtime-name : "airlines.war")
web_1  | 00:06:18,157 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
web_1  | 00:06:18,157 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
web_1  | 00:06:18,158 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 9.0.2.Final (WildFly Core 1.0.2.Final) started in 7958ms - Started 313 of 493 services (221 services are lazy, passive or on-demand)

Verify Application

Access the application by invoking the REST API using curl http://localhost:8080/airlines/resources/airline. This will show the following output:

[{"travel-sample":{"country":"United States","iata":"Q5","callsign":"MILE-AIR","name":"40-Mile Air","icao":"MLA","id":10,"type":"airline"}}, {"travel-sample":{"country":"United States","iata":"TQ","callsign":"TXW","name":"Texas Wings","icao":"TXW","id":10123,"type":"airline"}}, {"travel-sample":{"country":"United States","iata":"A1","callsign":"atifly","name":"Atifly","icao":"A1F","id":10226,"type":"airline"}}, {"travel-sample":{"country":"United Kingdom","iata":null,"callsign":null,"name":"Jc royal.britannica","icao":"JRB","id":10642,"type":"airline"}}, {"travel-sample":{"country":"United States","iata":"ZQ","callsign":"LOCAIR","name":"Locair","icao":"LOC","id":10748,"type":"airline"}}, {"travel-sample":{"country":"United States","iata":"K5","callsign":"SASQUATCH","name":"SeaPort Airlines","icao":"SQH","id":10765,"type":"airline"}}, {"travel-sample":{"country":"United States","iata":"KO","callsign":"ACE AIR","name":"Alaska Central Express","icao":"AER","id":109,"type":"airline"}}, {"travel-sample":{"country":"United Kingdom","iata":"5W","callsign":"FLYSTAR","name":"Astraeus","icao":"AEU","id":112,"type":"airline"}}, {"travel-sample":{"country":"France","iata":"UU","callsign":"REUNION","name":"Air Austral","icao":"REU","id":1191,"type":"airline"}}, {"travel-sample":{"country":"France","iata":"A5","callsign":"AIRLINAIR","name":"Airlinair","icao":"RLA","id":1203,"type":"airline"}}]

Complete set of REST APIs for this application are explained at https://github.com/arun-gupta/couchbase-javaee.

Stop Application

The application can be stopped using docker-compose down command. This will remove the containers for each service defined in the Compose file. It will also remove the networks defined in the networks section of the Compose file.

Remove the application as:

docker-compose up -d
Creating network "javaee_default" with the default driver
Creating javaee_db_1
Creating javaee_web_1
javaee > docker-compose down
Stopping javaee_web_1 ... done
Stopping javaee_db_1 ... done
Removing javaee_web_1 ... done
Removing javaee_db_1 ... done
Removing network javaee_default

Alternatively, only services can be stopped using docker-compose stop command:

docker-compose stop
Stopping javaee_web_1 ... done
Stopping javaee_db_1 ... done

The containers can be removed using docker-compose rm command:

docker-compose rm -f
Going to remove javaee_web_1, javaee_db_1
Removing javaee_web_1 ... done
Removing javaee_db_1 ... done