Add chapter to reference documentation on running Apache Geode in Docker.

Resolves gh-86.
This commit is contained in:
John Blum
2020-06-04 02:08:43 -07:00
parent df69b414cc
commit 5a5edb9e67
2 changed files with 379 additions and 0 deletions

View File

@@ -0,0 +1,377 @@
[[geode-docker]]
== Docker
:docker-docs-url: https://docs.docker.com
:docker-site-url: https://www.docker.com/
:geode-name: Apache Geode
:testcontainers-url: https://www.testcontainers.org
The state of modern software application development is moving towards https://www.docker.com/resources/what-container[_containerization_].
Containers offer a controlled environment to predictably build (configure & package), run and manage your applications
in a reliable and repeatable manner regardless of context. The intrinsic benefit of using Containers is a no brainer.
Understandably, {docker-site-url}[Docker's] popularity took off like wildfire given its highly powerful and simplified
model for creating, using and managing Containers to run packaged applications.
Docker's ecosystem is also quite impressive, with the event of {testcontainers-url}[Testcontainers]
along with Spring Boot's now {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[dedicated support]
to create packaged Spring Boot apps in {docker-docs-url}/get-started/overview/#docker-objects[Docker Images]
that are then later run in a Docker Container.
TIP: Also see {spring-boot-docs-html}/deployment.html#containers-deployment[Deploying to Containers] to learn more.
{geode-name} is no exception to being able to run in a controlled, containerized environment. The goal of this chapter
is to get you started running {geode-name} in a Container and interfacing to a containerized {geode-name} cluster from
your Spring Boot, {geode-name} client applications.
This chapter does not cover how to run your Spring Boot, {geode-name} client applications in a Container since that is
already covered by Spring Boot (again, see {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[here]
and {spring-boot-docs-html}/deployment.html#containers-deployment[here], along with Docker's {docker-docs-url}/get-started/overview/[docs]).
Instead, our focus is on how to run an {geode-name} cluster in a Container and connect to it from a Spring Boot,
{geode-name} client application, regardless of whether the app is running in a Container or not.
Let's get started.
[[geode-docker-image]]
=== Acquiring the {geode-name} Docker Image
To run an {geode-name} cluster inside a Docker Container you must first acquire the Docker Image.
While {geode-name}'s official {apache-geode-docs}[documentation] is less than clear on how to use {geode-name} in Docker,
we find a bit of relief in the {apache-geode-wiki}/How+to+use+Geode+on+Docker[Wiki]. However, for a complete write up,
please refer to the instructions in the https://github.com/markito/geode-docker#building-the-container-image[README]
from this https://github.com/markito/geode-docker[GitHub Repo].
The {geode-name} Docker Image can be acquired from https://hub.docker.com/r/apachegeode/geode/[Docker Hub].
NOTE: You must have {docker-docs-url}/get-docker[Docker] installed on your local system to complete the following steps.
Effectively, the high-level steps are as follows:
1) Acquire the {geode-name} Docker Image from Docker Hub using the `docker pull` command from the command-line:
.Download/Install the {geode-name} Docker Image
[source,text]
----
$ docker pull apachegeode/geode
Using default tag: latest
latest: Pulling from apachegeode/geode
Digest: sha256:6a6218f22a2895bb706175727c7d76f654f9162acac22b2d950d09a2649f9cf4
Status: Image is up to date for apachegeode/geode:latest
docker.io/apachegeode/geode:latest
----
Instead of pulling from the `nightly` TAG as suggested, the Spring Team highly recommends that you pull from the
`latest` TAG, which pulls a stable, production-grade {geode-name} Docker Image based on the latest {geode-name}
GA version.
2) Verify the {geode-name} Docker Image was downloaded and installed successfully:
[source,text]
----
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
apachegeode/geode latest a2e210950712 2 months ago 224MB
cloudfoundry/run base-cnb 3a7d172559c2 8 weeks ago 71.2MB
open-liberty 19.0.0.9-webProfile8 dece75feff1a 3 months ago 364MB
tomee 11-jre-8.0.0-M3-webprofile 0d03e4d395e6 3 months ago 678MB
...
----
Now, you are ready to run {geode-name} in a Docker Container.
[[geode-docker-container]]
=== Running {geode-name} in a Docker Container
Now that we have acquired the Docker Image, we can run {geode-name} in a Docker Container. Use the following
`docker run` command to start the {geode-name} Docker Container:
.Start the {geode-name} Docker Container
[source,text]
----
$ docker run -it -p 10334:10334 -p 40404:40404 -p 1099:1099 -p 7070:7070 -p 7575:7575 apachegeode/geode
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.12.0
Monitor and Manage Apache Geode
gfsh>
----
Since the {geode-name} Docker Container was started in interactive mode, you must open a separate command-line shell
to verify the {geode-name} Docker Container is in fact running:
.Verify the {geode-name} Docker Container is Running
[source,text]
----
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b30b9ffc5dc apachegeode/geode "gfsh" 44 seconds ago Up 43 seconds 0.0.0.0:1099->1099/tcp, 0.0.0.0:7070->7070/tcp, 0.0.0.0:7575->7575/tcp, 0.0.0.0:10334->10334/tcp, 0.0.0.0:40404->40404/tcp, 8080/tcp awesome_khorana
----
Of course, we know that the {geode-name} Docker Container is running since we ended up at a _Gfsh_ command prompt in the
interactive shell.
We also mapped ports between the Docker Container and the host system, exposing well-known ports used by {geode-name}
server-side, cluster processes, such as Locators and Cache Servers.
.{geode-name} Ports
[width=30%, options="header", cols="2,1"]
|===
| Process | Port
| HTTP | 7070
| Locator | 10334
| Manager | 1099
| Server | 40404
|===
It is unfortunate that the {geode-name} Docker Image only gives you a _Gfsh_ command prompt, leaving you to provision a
cluster. It would have been more useful to provide preconfigured Docker Images with different {geode-name} cluster
configurations, such as 1 Locator + 1 Server, or 2 Locators + 4 Servers, etc. But, no matter, we can start the cluster
ourselves.
[[geode-docker-cluster]]
=== Run an {geode-name} Cluster
From inside the {geode-name} Docker Container we can start a Locator and a Server.
.Start {geode-name} Locator & Server
[source, text]
----
gfsh>start locator --name=LocatorOne --log-level=config --hostname-for-clients=localhost
Starting a Geode Locator in /LocatorOne...
.........
Locator in /LocatorOne on 3b30b9ffc5dc[10334] as LocatorOne is currently online.
Process ID: 167
Uptime: 9 seconds
Geode Version: 1.12.0
Java Version: 1.8.0_212
Log File: /LocatorOne/LocatorOne.log
JVM Arguments: -Dgemfire.enable-cluster-configuration=true -Dgemfire.load-cluster-configuration-from-dir=false -Dgemfire.log-level=config -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /geode/lib/geode-core-1.12.0.jar:/geode/lib/geode-dependencies.jar
Successfully connected to: JMX Manager [host=3b30b9ffc5dc, port=1099]
Cluster configuration service is up and running.
gfsh>start server --name=ServerOne --log-level=config --hostname-for-clients=localhost
Starting a Geode Server in /ServerOne...
.......
Server in /ServerOne on 3b30b9ffc5dc[40404] as ServerOne is currently online.
Process ID: 267
Uptime: 7 seconds
Geode Version: 1.12.0
Java Version: 1.8.0_212
Log File: /ServerOne/ServerOne.log
JVM Arguments: -Dgemfire.default.locators=172.17.0.2[10334] -Dgemfire.start-dev-rest-api=false -Dgemfire.use-cluster-configuration=true -Dgemfire.log-level=config -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /geode/lib/geode-core-1.12.0.jar:/geode/lib/geode-dependencies.jar
gfsh>list members
Member Count : 2
Name | Id
---------- | --------------------------------------------------------------
LocatorOne | 172.17.0.2(LocatorOne:167:locator)<ec><v0>:41000 [Coordinator]
ServerOne | 172.17.0.2(ServerOne:267)<v1>:41001
gfsh>describe member --name=LocatorOne
Name : LocatorOne
Id : 172.17.0.2(LocatorOne:167:locator)<ec><v0>:41000
Host : 3b30b9ffc5dc
Regions :
PID : 167
Groups :
Used Heap : 50M
Max Heap : 443M
Working Dir : /LocatorOne
Log file : /LocatorOne/LocatorOne.log
Locators : 172.17.0.2[10334]
gfsh>describe member --name=ServerOne
Name : ServerOne
Id : 172.17.0.2(ServerOne:267)<v1>:41001
Host : 3b30b9ffc5dc
Regions :
PID : 267
Groups :
Used Heap : 77M
Max Heap : 443M
Working Dir : /ServerOne
Log file : /ServerOne/ServerOne.log
Locators : 172.17.0.2[10334]
Cache Server Information
Server Bind :
Server Port : 40404
Running : true
Client Connections : 0
----
We now have an {geode-name} cluster running with 1 Locator and 1 Server inside a Docker Container. We deliberately
started the cluster with a minimal configuration. For example, we have no Regions in which to store data:
[source,text]
----
gfsh>list regions
No Regions Found
----
But, that is OK. Once more, we want to showcase the full power of SBDG and let the Spring Boot application drive
the configuration of the {geode-name} cluster running in the Docker Container as required by the application.
Let's have a quick look at our Spring Boot application.
[[geode-docker-application]]
=== The Spring Boot, {geode-name} client application explained
The Spring Boot, {geode-name} `ClientCache` application we will use to connect to our {geode-name} cluster running in
the Docker Container, appears as follows:
.Spring Boot, {geode-name} Docker client application
[source,java]
----
include::{docs-src-dir}/org/springframework/geode/docs/example/app/docker/SpringBootApacheGeodeDockerClientCacheApplication.java[tags=class]
----
Our `Customer` application domain model object type is defined as:
.`Customer` class
[source,java]
----
@Region("Customers")
class Customer {
@Id
private Long id;
private String name;
}
----
And, we define a Spring Data CRUD _Repository_ to persist and access `Customers` stored in {geode-name},
"/Customers" Region:
.`CustomerRepository` interface
[source,java]
----
interface CustomerRepository extends CrudRepository<Customer, Long> {
Customer findByNameLike(String name);
}
----
Our main class is annotated with `@SpringBootApplication` making it a proper Spring Boot application.
We additionally annotate the main class with SBDG's `@EnableClusterAware` to automatically detect the {geode-name}
cluster running in the Docker Container as well as to push cluster configuration metadata from the application to
the cluster as required by the application.
Specifically, the application requires that a Region called "Customers", as defined by the `@Region` mapping annotation
on the `Customer` application domain model class, exists on the server(s) in the cluster to persist `Customer` data.
We use the SDG `@EnableEntityDefinedRegions` annotation to define the matching, client `PROXY` "Customers" Region.
Optionally, we have also annotated our main class with SBDG's `@UseMemberName` annotation to give the `ClientCache`
a name, which will assert in the `assertClientCacheAndConfigureMappingPdxSerializer(:ClientCache)` method.
The primary work performed by this application is done in the Spring Boot `ApplicationRunner` bean definition. We
essentially create a `Customer` instance, "Jon Doe", save "Jon Doe" to the "Customers" Region on the server(s) in
the cluster, and then query for "Jon Doe" using OQL, asserting that the result is equal to the expected.
We log the output from the application's operations to see the application in action.
[[geode-docker-application-run]]
=== Running the Spring Boot, {geode-name} client application
When you run the Spring Boot, {geode-name} client, application, you should see output similar to:
.Application log output
[source,text]
----
/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java ...
org.springframework.geode.docs.example.app.docker.SpringBootApacheGeodeDockerClientCacheApplication
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.0.RELEASE)
Saving Customer [Customer(name=Jon Doe)]...
Querying for Customer [SELECT * FROM /Customers WHERE name LIKE '%Doe']...
Customer was [Customer(name=Jon Doe)]
Process finished with exit code 0
----
Now when we review the configuration of the cluster, we see that the "/Customers" Region was created
once the application has run:
./Customers Region Configuration
[source,text]
----
gfsh>list regions
List of regions
---------------
Customers
gfsh>describe region --name=/Customers
Name : Customers
Data Policy : partition
Hosting Members : ServerOne
Non-Default Attributes Shared By Hosting Members
Type | Name | Value
------ | ----------- | ---------
Region | size | 1
| data-policy | PARTITION
----
Our "/Customers" Region contains a value, "Jon Doe", and we can verify this by running an OQL Query using _Gfsh_:
.Query the "/Customers" Region
[source,text]
----
gfsh>query --query="SELECT customer.name FROM /Customers customer"
Result : true
Limit : 100
Rows : 1
Result
-------
Jon Doe
----
Indeed, our application ran successfully!
[[geode-docker-application-conclusion]]
=== Conclusion
In this chapter, we saw how to connect a Spring Boot, {geode-name} `ClientCache` application to an {geode-name} cluster
running in a Docker Container.
Later, we will provide more information on how to scale up, or rather scale out, our {geode-name} cluster running in
Docker. Additionally, we will provide details on how you can use {geode-name}'s Docker Image with **Testcontainers**
when writing _Integration Tests_, which will formally become part of the Spring Test for Apache Geode (STDG) project.

View File

@@ -16,6 +16,7 @@ John Blum
:apache-geode-docs: https://geode.apache.org/docs/guide/{apache-geode-version}
:apache-geode-javadoc: https://geode.apache.org/releases/latest/javadoc
:apache-geode-website: https://geode.apache.org/
:apache-geode-wiki: https://cwiki.apache.org/confluence/display/GEODE
:pivotal-cloudcache-version: {master-pivotal-cloudcache-version}
:pivotal-cloudcache-docs: https://docs.pivotal.io/p-cloud-cache/{pivotal-cloudcache-version}
:pivotal-cloudcache-website: https://pivotal.io/pivotal-cloud-cache
@@ -250,5 +251,6 @@ include::{include-dir}/geode-api-ext.adoc[]
include::{include-dir}/actuator.adoc[]
include::{include-dir}/session.adoc[]
include::{include-dir}/cloudfoundry.adoc[]
include::{include-dir}/docker.adoc[]
include::{include-dir}/samples.adoc[]
include::{include-dir}/appendix.adoc[]