Ratnopam Chakrabarti es un desarrollador de software que trabaja actualmente para Ericsson Inc. Lleva bastante tiempo centrado en IoT, tecnologías máquina a máquina, coches conectados y dominios de ciudades inteligentes. Le encanta aprender nuevas tecnologías y ponerlas en práctica. Cuando no está trabajando, le gusta pasar tiempo con su hijo de 3 años.

Introducción
Ejecutar Couchbase como un contenedor Docker es bastante fácil. Simplemente hereda de la última imagen oficial de Couchbase y añade tu comportamiento personalizado de acuerdo a tus necesidades. En este post, voy a mostrar cómo se puede poner en marcha una aplicación web utilizando Spring Boot, Vaadin, y por supuesto Couchbase (como backend) - todo usando Docker.
Esta es la primera parte de una serie de dos partes donde voy a describir maneras de ejecutar una aplicación web con todas las funciones impulsado por Couchbase como el backend NoSQL utilizando conjuntos de herramientas Docker. En este post, describiré los pasos para configurar un entorno Couchbase usando Docker; también mencionaré formas de Dockerizar la aplicación web (en este caso, es una aplicación Spring Boot con Vaadin) y hablar con el backend Couchbase para las operaciones CRUD.
Requisitos previos
Docker debe estar configurado y en funcionamiento. Consulte el siguiente enlace para obtener información detallada sobre la instalación: https://docs.docker.com/engine/installation/ Si estás en macOS o Windows 10, puedes optar por los paquetes nativos de Docker. Si estás en una versión anterior de Windows (7 u 8) como yo, entonces puedes usar Docker Toolbox que viene con Docker achine.
La aplicación
La nuestra es una sencilla aplicación CRUD para mantener una librería. Los usuarios de la aplicación pueden añadir libros introduciendo información como título y/o autor, y luego pueden ver la lista de libros, editar alguna información, e incluso borrar los libros. La aplicación está construida sobre Spring Boot. El backend es alimentado por Couchbase 4.6, y para el front-end he utilizado Vaadin 7 ya que tiene una integración bastante buena con el framework Spring Boot.
A continuación se indican los principales pasos para crear esta aplicación:
- Ejecutar y configurar Couchbase 4.6, incluyendo la configuración del cubo y los servicios utilizando Docker.
- Construir la aplicación utilizando Spring Boot, Vaadin, y Couchbase.
- Dockerizar y ejecutar la aplicación.
Ejecutar Couchbase 4.6 usando Docker
Comprueba la IP de tu host Docker. Usted puede utilizar:
|
1 2 3 4 5 |
docker-machine ip default to find out the docker_host ip address. You can also check the environment variables by doing printenv | grep -i docker_host; it would show something like this -> DOCKER_HOST=tcp://192.168.99.100:2376 |
La siguiente tarea es escribir el Dockerfile para ejecutar y configurar Couchbase. Para que nuestra aplicación hable con el backend de Couchbase, necesitamos configurar un bucket llamado "books" y también habilitar los servicios de consulta de índices en el nodo de Couchbase. El Dockerfile para todo esto se puede encontrar aquí.
El Dockerfile utiliza un script de configuración para configurar el nodo Couchbase. Couchbase ofrece puntos finales REST que pueden habilitar fácilmente servicios como consultas, N1QL e índices. También se pueden configurar buckets utilizando estas API REST. El script de configuración puede descargarse de aquí.
Intentemos ahora construir y ejecutar la imagen de Couchbase.
Vaya al directorio donde está el Dockerfile.
|
1 2 3 4 5 6 7 8 9 |
Build the image -> docker build -t <chakrar27>/couchbase:books . Replace chakrar27 by your image-prefix or docker hub id. Once the image is built, verify by doing $ docker images |
REPOSITORIO ETIQUETA IMAGEN ID CREADO TAMAÑO
chakrar27/couchbase books 93e7ba199eef hace 1 hora 581 MB
couchbase latest 337dab68d2d1 hace 9 días 581 MB
Ejecute la imagen escribiendo
|
1 |
docker run -p 8091-8093:8091-8093 -p 8094:8094 -p 11210:11210 chakrar27/couchbase:books |
Muestra de salida:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
Starting Couchbase Server -- Web UI available at https://<ip>:8091 and logs available in /opt/couchbase/var/lib/couchbase/logs Start configuring env by calling REST endpoints Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 192.168.99.100... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0) > POST /pools/default HTTP/1.1 > Host: 127.0.0.1:8091 > User-Agent: curl/7.49.1-DEV > Accept: */* > Content-Length: 55 > Content-Type: application/x-www-form-urlencoded > } [55 bytes data] * upload completely sent off: 55 out of 55 bytes < HTTP/1.1 200 OK < Server: Couchbase Server < Pragma: no-cache < Date: Fri, 24 Mar 2017 03:20:51 GMT < Content-Length: 0 < Cache-Control: no-cache < 100 55 0 0 100 55 0 2966 --:--:-- --:--:-- --:--:-- 3666 * Connection #0 to host 127.0.0.1 left intact * Trying 127.0.0.1... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0) > POST /node/controller/setupServices HTTP/1.1 > Host: 127.0.0.1:8091 > User-Agent: curl/7.49.1-DEV > Accept: */* > Content-Length: 32 > Content-Type: application/x-www-form-urlencoded > } [32 bytes data] * upload completely sent off: 32 out of 32 bytes < HTTP/1.1 200 OK < Server: Couchbase Server < Pragma: no-cache < Date: Fri, 24 Mar 2017 03:20:56 GMT < Content-Length: 0 < Cache-Control: no-cache < 100 32 0 0 100 32 0 3389 --:--:-- --:--:-- --:--:-- 4000 * Connection #0 to host 127.0.0.1 left intact % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 180 100 152 100 28 8068 1486 --:--:-- --:--:-- --:--:-- 8444 HTTP/1.1 200 OK Server: Couchbase Server Pragma: no-cache Date: Fri, 24 Mar 2017 03:21:01 GMT Content-Type: application/json Content-Length: 152 Cache-Control: no-cache {"storageMode":"memory_optimized","indexerThreads":0,"memorySnapshotInterval":200,"stableSnapshotInterval":5000,"maxRollbackPoints":5,"logLevel":"info"}Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 127.0.0.1... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0) > POST /settings/web HTTP/1.1 > Host: 127.0.0.1:8091 > User-Agent: curl/7.49.1-DEV > Accept: */* > Content-Length: 50 > Content-Type: application/x-www-form-urlencoded > } [50 bytes data] * upload completely sent off: 50 out of 50 bytes < HTTP/1.1 200 OK < Server: Couchbase Server < Pragma: no-cache < Date: Fri, 24 Mar 2017 03:21:01 GMT < Content-Type: application/json < Content-Length: 44 < Cache-Control: no-cache < { [44 bytes data] 100 94 100 44 100 50 1554 1765 --:--:-- --:--:-- --:--:-- 2380 * Connection #0 to host 127.0.0.1 left intact {"newBaseUri":"https://127.0.0.1:8091/"}bucket set up start bucket name = books Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 127.0.0.1... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8091 (#0) * Server auth using Basic with user 'Administrator' > POST /pools/default/buckets HTTP/1.1 > Host: 127.0.0.1:8091 > Authorization: Basic QWRtaW5pc3RyYXRvcjpwYXNzd29yZA== > User-Agent: curl/7.49.1-DEV > Accept: */* > Content-Length: 55 > Content-Type: application/x-www-form-urlencoded > } [55 bytes data] * upload completely sent off: 55 out of 55 bytes < HTTP/1.1 202 Accepted < Server: Couchbase Server < Pragma: no-cache < Location: /pools/default/buckets/books < Date: Fri, 24 Mar 2017 03:21:01 GMT < Content-Length: 0 < Cache-Control: no-cache < 100 55 0 0 100 55 0 748 --:--:-- --:--:-- --:--:-- 820 * Connection #0 to host 127.0.0.1 left intact bucket set up done /entrypoint.sh couchbase-server |
Verifique la configuración escribiendo https://192.168.99.100:8091 en tu navegador favorito.

Escriba "Administrador" como nombre de usuario y "contraseña" en el campo Contraseña y haga clic en Iniciar sesión.
Comprueba la configuración del nodo Couchbase y verifica que está de acuerdo con el configure.sh que utilizamos anteriormente.

El cubo "libros".

En este punto nuestra infraestructura back-end Couchbase está lista y funcionando. Ahora necesitamos construir una aplicación que pueda utilizar este backend para construir algo funcional.
Construir la aplicación utilizando Spring Boot, Vaadin, y Couchbase
Vaya a start.spring.io y añada Couchbase como dependencia. Esto colocaría las librerías spring-data-couchbase en el classpath de la aplicación. Dado que Couchbase se considera un ciudadano de primera clase del ecosistema Spring Boot, podemos hacer uso de la función de autoconfiguración de Spring Boot para acceder al bucket de Couchbase en tiempo de ejecución.
Además, añadir Vaadin como una dependencia en el proyecto. Vamos a utilizarlo para la construcción de la capa de interfaz de usuario.
El archivo del modelo de objetos del proyecto (pom) se encuentra en aquí.
Creamos un repositorio Couchbase así:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@ViewIndexed(designDoc = "book") @N1qlPrimaryIndexed @N1qlSecondaryIndexed(indexName = "bookSecondaryIndex") public interface BookStoreRepository extends CouchbasePagingAndSortingRepository<Book, Long> { List<Book> findAll(); List<Book> findByAuthor(String author); List<Book> findByTitleStartsWithIgnoreCase(String title); List<Book> findByCategory(String category); } |
Las anotaciones garantizan que se proporcionará una vista denominada "book" en tiempo de ejecución para soportar consultas basadas en vistas. Se creará un índice primario para soportar consultas N1QL. Además, también se proporcionará un índice secundario.
Los métodos han sido definidos para devolver List. No tenemos que proporcionar ninguna implementación, ya que la spring-data-couchbase ya la proporciona entre bastidores.
Necesitamos definir la entidad, que en nuestro caso es Book. La anotamos con @Document.
@Documento
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Book { @Id private String id = UUID.randomUUID().toString(); private String title; private String author; private String isbn; private String category; } |
Para activar la configuración automática, utilice el archivo application.properties o application.yml como se muestra a continuación:
|
1 2 3 4 5 6 7 |
spring.couchbase.bootstrap-hosts=127.0.0.1 spring.couchbase.bucket.name=books spring.couchbase.bucket.password= spring.data.couchbase.auto-index=true |
Una cosa a tener en cuenta aquí es que cuando el contenedor de la aplicación se ejecuta, necesitaría conectarse al contenedor de Couchbase y establecer la auto-configuración. La propiedad spring.couchbase.bootstrap-hosts lista la dirección IP del nodo Couchbase. Aquí, he especificado 127.0.0.1 que no va a funcionar ya que en tiempo de ejecución, el contenedor de la aplicación no encontrará el contenedor Couchbase ejecutándose en esa IP. Así que tenemos que pasar una variable de entorno (variable env) al ejecutar la imagen Docker de la aplicación.
Para pasar una variable env como se mencionó anteriormente, tenemos que escribir el Dockerfile de la aplicación de tal manera que el valor de la variable env spring.couchbase.bootstrap-hosts se puede pasar como una variable env. Aquí está el Dockerfile de la aplicación:
|
1 2 3 4 5 6 7 8 9 |
FROM frolvlad/alpine-oraclejdk8:full VOLUME /tmp ADD target/bookstore-1.0.0-SNAPSHOT.jar app.jar RUN sh -c 'touch /app.jar' CMD java -Dspring.couchbase.bootstrap-hosts=$HOSTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar |
Como puede ver, básicamente estamos anulando el valor de la directiva spring.couchbase.bootstrap-hosts definida en el archivo application.properties por la variable env HOSTS.
Esto es prácticamente todo lo que tenemos que hacer para conectar Spring Boot con Couchbase.
UI (U e I)
Para la interfaz de usuario, utilizamos la integración spring-vaadin. Estoy usando la versión 7.7.3 de Vaadin, vaadin-spring versión 1.1.0, y "Viritin", un útil complemento de Vaadin. Para instalar Viritin, añada la siguiente dependencia:
|
1 2 3 4 5 6 7 8 9 |
<dependency> <groupId>org.vaadin</groupId> <artifactId>viritin</artifactId> <version>1.57</version> </dependency> |
Anote la clase UI como
@SpringUI
@Theme("valo")
public class LibreríaUI extends UI {
//////
}
Y luego enganchar los métodos del repositorio con los elementos de la UI.
Un bean que implementa el método CommandLineRunner se utiliza para prepoblar la base de datos con algunos valores iniciales.
Para obtener el código fuente completo, consulte este enlace.
Dockerizar la aplicación
Usando Maven, es muy fácil Dockerizar una aplicación usando el plugin docker-maven de Spotify. Por favor, revisa la sección de plugins del archivo pom.xml.
Alternativamente, puede construir utilizando la línea de comandos Docker ->
|
1 |
docker build -t chakrar27/books:standalone . |
Y luego ejecuta la imagen -> Ten en cuenta que necesitamos pasar el valor de la variable HOSTS que nuestro contenedor de aplicaciones va a buscar cuando intente conectarse al contenedor de Couchbase. El comando de ejecución se vería así:
|
1 |
docker run -p 8080:8080 -e HOSTS=192.168.99.100 chakrar27/books:standalone |
Una vez iniciada la aplicación, vaya a https://192.168.99.100:8080/
Aparece la siguiente página:

Una entrada puede editarse y guardarse.

La consulta N1QL que se ejecuta por debajo también ofrece una función de filtrado muy útil.

Los usuarios también pueden añadir un nuevo libro y eliminar un registro existente. Todas las funcionalidades CRUD (Create/Read/Update/Delete) de esta sencilla aplicación están potenciadas por consultas N1QL de Couchbase, que habilitamos creando el "BookStoreRepository", y, a su vez, extiende el "CouchbasePagingAndSortingRepository".
Este post forma parte del Programa de Escritura de la Comunidad Couchbase
[...] ejecutar una aplicación web Spring Boot totalmente funcional con Couchbase utilizando el conjunto de herramientas Docker. En la primera parte de la serie, demostré cómo ejecutar dos contenedores Docker para ejecutar una aplicación funcional con [...]