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.
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 or rebuild services |
|
Get help on a command |
|
Kill containers |
|
View output from containers |
|
Print the public port for a port binding |
|
List containers |
|
Pulls service images |
|
Restart services |
|
Remove stopped containers |
|
Run a one-off command |
|
Set number of containers for a service |
|
Start services |
|
Stop services |
|
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.
-
Entry point to Docker Compose is Compose file, usually called
docker-compose.yml
. Create a new directory and a new filedocker-compose.yml
in it. Use the following contents:
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:
-
Two services in this Compose are defined by the name
db
andweb
attributes -
Image name for each service defined using
image
attribute -
The
arungupta/couchbase
image starts Couchbase server, configures it using Couchbase REST API, and loads a sample bucket -
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. -
Environment variable for WildFly container is defined in
environment
attribute -
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. -
Port forwarding is achieved using
ports
attribute -
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.
All services in the applicaiton can be started, in detached mode, by giving the command:
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:
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:
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)
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.
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