Add chapter to reference documentation on running Apache Geode in Docker.
Resolves gh-86.
This commit is contained in:
377
spring-geode-docs/src/docs/asciidoc/_includes/docker.adoc
Normal file
377
spring-geode-docs/src/docs/asciidoc/_includes/docker.adoc
Normal 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.
|
||||
@@ -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[]
|
||||
|
||||
Reference in New Issue
Block a user