Ratnopam Chakrabarti é um desenvolvedor de software que trabalha atualmente para a Ericsson Inc. Ele tem se concentrado em IoT, tecnologias máquina a máquina, carros conectados e domínios de cidades inteligentes por um bom tempo. Ele adora aprender novas tecnologias e colocá-las em prática. Quando não está trabalhando, gosta de passar o tempo com seu filho de 3 anos.

Introdução
Executar o Couchbase como um contêiner do Docker é bastante fácil. Basta herdar a imagem oficial mais recente do Couchbase e adicionar seu comportamento personalizado de acordo com suas necessidades. Nesta postagem, mostrarei como você pode iniciar um aplicativo Web usando o Spring Boot, o Vaadin e, é claro, o Couchbase (como backend), tudo isso usando o Docker.
Esta é a primeira parte de uma série de duas partes em que descreverei maneiras de executar um aplicativo da Web com todos os recursos do Couchbase como backend NoSQL usando conjuntos de ferramentas do Docker. Nesta postagem, descreverei as etapas para instalar e configurar um ambiente Couchbase usando o Docker; também mencionarei maneiras de Dockerizar o aplicativo Web (neste caso, é um aplicativo Spring Boot com Vaadin) e conversar com o backend do Couchbase para as operações CRUD.
Pré-requisitos
O Docker precisa estar configurado e funcionando. Consulte o link a seguir para obter detalhes sobre a instalação: https://docs.docker.com/engine/installation/ Se você estiver no macOS ou no Windows 10, poderá optar por pacotes nativos do Docker. Se você estiver em uma versão anterior do Windows (7 ou 8), como eu, poderá usar o Docker Toolbox, que vem com o Docker Achine.
O aplicativo
O nosso é um aplicativo CRUD simples para manter uma livraria. Os usuários do aplicativo podem adicionar livros inserindo informações como título e/ou autor e, em seguida, podem visualizar a lista de livros, editar algumas informações e até mesmo excluir os livros. O aplicativo foi desenvolvido com base no Spring Boot. O back-end é alimentado pelo Couchbase 4.6 e, para o front-end, usei o Vaadin 7, pois ele tem uma integração muito boa com a estrutura do Spring Boot.
As principais etapas para criar esse aplicativo estão listadas abaixo:
- Executar e configurar o Couchbase 4.6, incluindo a configuração do bucket e dos serviços usando o Docker.
- Crie o aplicativo usando o Spring Boot, o Vaadin e o Couchbase.
- Dockerize e execute o aplicativo.
Executar o Couchbase 4.6 usando o Docker
Verifique o IP do host do Docker. Você pode usar:
|
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 |
A próxima tarefa é escrever o Dockerfile para executar e configurar o Couchbase. Para que nosso aplicativo se comunique com o backend do Couchbase, precisamos configurar um bucket chamado "books" e também habilitar os serviços de consulta de índice no nó do Couchbase. O Dockerfile para tudo isso pode ser encontrado aqui.
O Dockerfile usa um script de configuração para configurar o nó do Couchbase. O Couchbase oferece pontos de extremidade REST que podem facilmente habilitar serviços como consulta, N1QL e índice. Também é possível configurar buckets usando essas APIs REST. O script de configuração pode ser baixado de aqui.
Vamos tentar criar e executar a imagem do Couchbase agora.
Vá para o diretório onde está o 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 |
REPOSITÓRIO TAG IMAGE ID CREATED SIZE
chakrar27/couchbase books 93e7ba199eef 1 hora atrás 581 MB
couchbase latest 337dab68d2d1 9 dias atrás 581 MB
Execute a imagem digitando
|
1 |
docker run -p 8091-8093:8091-8093 -p 8094:8094 -p 11210:11210 chakrar27/couchbase:books |
Saída de amostra:
|
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 a configuração digitando https://192.168.99.100:8091 em seu navegador favorito.

Digite "Administrator" como nome de usuário e "password" no campo Password e clique em Sign In.
Verifique as configurações do nó do Couchbase e verifique se elas estão de acordo com o configure.sh que usamos acima.

O balde "livros".

Neste ponto, nossa infraestrutura de back-end do Couchbase está funcionando. Agora precisamos criar um aplicativo que possa usar esse backend para criar algo funcional.
Criar o aplicativo usando o Spring Boot, o Vaadin e o Couchbase
Vá para start.spring.io e adicione o Couchbase como uma dependência. Isso colocaria as bibliotecas spring-data-couchbase no classpath do aplicativo. Como o Couchbase é considerado um cidadão de primeira classe do ecossistema do Spring Boot, podemos usar o recurso de configuração automática do Spring Boot para acessar o bucket do Couchbase em tempo de execução.
Além disso, adicione o Vaadin como uma dependência no projeto. Vamos usá-lo para criar a camada de interface do usuário.
O arquivo de modelo de objeto de projeto (pom) pode ser encontrado aqui.
Criamos um repositório do Couchbase como este:
|
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); } |
As anotações garantem que uma visualização chamada "book" será fornecida em tempo de execução para dar suporte a consultas baseadas em visualização. Um índice primário será criado para dar suporte a consultas N1QL. Além disso, um índice secundário também será fornecido.
Os métodos foram definidos para retornar List. Não precisamos fornecer nenhuma implementação, pois isso já é fornecido nos bastidores pelo spring-data-couchbase.
Precisamos definir a entidade, que, no nosso caso, é o livro. Nós a anotamos com @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 ativar a configuração automática, use o arquivo application.properties ou application.yml, conforme mostrado abaixo:
|
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 |
Um aspecto a ser observado aqui é que, quando o contêiner do aplicativo for executado, ele precisará se conectar ao contêiner do Couchbase e definir a configuração automática. A propriedade spring.couchbase.bootstrap-hosts lista o endereço IP do nó do Couchbase. Aqui, especifiquei 127.0.0.1, o que não funcionará, pois, no tempo de execução, o contêiner do aplicativo não encontrará o contêiner do Couchbase em execução nesse IP. Portanto, precisamos passar uma variável de ambiente (variável env) ao executar a imagem do Docker do aplicativo.
Para passar uma variável env conforme mencionado acima, precisamos escrever o Dockerfile do aplicativo de modo que o valor da variável spring.couchbase.bootstrap-hosts pode ser passada como uma variável env. Aqui está o Dockerfile do aplicativo:
|
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 você pode ver, estamos basicamente substituindo o valor da variável spring.couchbase.bootstrap-hosts definida no arquivo application.properties pela variável env HOSTS.
Isso é praticamente tudo o que precisamos fazer para conectar o Spring Boot ao Couchbase.
UI (U e I)
Para a interface do usuário, usamos a integração spring-vaadin. Estou usando a versão 7.7.3 do Vaadin, o vaadin-spring versão 1.1.0 e o "Viritin", um complemento útil do Vaadin. Para instalar o Viritin, adicione a seguinte dependência:
|
1 2 3 4 5 6 7 8 9 |
<dependency> <groupId>org.vaadin</groupId> <artifactId>viritin</artifactId> <version>1.57</version> </dependency> |
Anote a classe UI como
@SpringUI
@Theme("valo")
public class BookstoreUI extends UI {
//////
}
Em seguida, conecte os métodos do repositório com os elementos da interface do usuário.
Um bean que implementa o CommandLineRunner é usada para preencher previamente o banco de dados com alguns valores iniciais.
Para obter o código-fonte completo, consulte este link.
Dockerize o aplicativo
Usando o Maven, é muito fácil Dockerizar um aplicativo usando o plug-in docker-maven do Spotify. Verifique a seção do plug-in do arquivo pom.xml.
Como alternativa, você pode criar usando a linha de comando do Docker ->
|
1 |
docker build -t chakrar27/books:standalone . |
E, em seguida, execute a imagem -> Observe que precisamos passar o valor da variável HOSTS que o nosso contêiner de aplicativo procurará quando tentar se conectar ao contêiner do Couchbase. O comando de execução seria semelhante a:
|
1 |
docker run -p 8080:8080 -e HOSTS=192.168.99.100 chakrar27/books:standalone |
Quando o aplicativo for iniciado, navegue até https://192.168.99.100:8080/
A página a seguir é exibida:

Uma entrada pode ser editada e salva.

Há também um recurso de filtragem interessante fornecido pela consulta N1QL executada abaixo.

Os usuários também podem adicionar um novo livro e excluir um registro existente. Todos os recursos CRUD (Create/Read/Update/Delete) desse aplicativo simples são alimentados por consultas N1QL do Couchbase, que ativamos criando o "BookStoreRepository" e, por sua vez, estende o "CouchbasePagingAndSortingRepository".
Esta postagem faz parte do Programa de Redação da Comunidade Couchbase
[...] executar um aplicativo da Web do Spring Boot totalmente funcional e alimentado pelo Couchbase usando o conjunto de ferramentas do Docker. Na primeira parte da série, demonstrei como executar dois contêineres do Docker para executar um aplicativo funcional com [...]