Iniciante

Empacotando sua aplicação Grails

Pessoal,

Hoje vim trazer uma dica bem fácil para vocês. Um modo de empacotar, distribuir e implantar sua aplicação WEB é por meio de um arquivo WAR. O WAR (Web Application Archive) é um arquivo que pode ser implantado (deploy) em servidores compatíveis com Java EE, e que contém os arquivos compilados da sua aplicação WEB.

Ou seja, ele é um modo padronizado de empacotar, distribuir e implantar sua aplicação em servidores WEB. Caso queira ler mais sobre WAR, sugiro esse link. Sendo assim, é claro que os desenvolvedores do Grails pensaram em um modo fácil de você poder gerar um WAR da sua aplicação. Para isso basta executar o comando war do Grails, cuja documentação, para a versão 3.2.2 do Grails, pode ser vista aqui.

Esse comando tem a seguinte sintaxe:

grails ambiente war

Por padrão o ambiente é prod (produção), mas você também pode substituir o por dev ou test. Ao executar esse comando, um arquivo war é gerado dentro do diretório build/libs, da sua aplicação. Por exemplo, se eu criar uma aplicação com o nome minhaAplicacao, dentro do diretório do meu usuário (/home/bruno), entrar no diretório dela (/home/bruno/minhaAplicacao), e executar o comando:

grails war

Um arquivo é gerado dentro do diretório /home/bruno/minhaAplicacao/build/libs. O arquivo gerado tem o seguinte formato de nome:

nome_aplicacao-versao_aplicacao.war

No exemplo que citei, o arquivo teria o seguinte nome:

minhaAplicacao-0.1.war

Uma vez que a versão inicial da aplicação recém-criada é 0.1. Para ter certeza disso, você pode alterar o seu arquivo build.gradle, alterando o version para:

version "0.2"

Ao rodar novamente o comando grails war, o arquivo minhaAplicacao-0.2.war será gerado no diretório build/libs.

Ok, legal, já conseguimos gerar nosso war. Mas e se quisermos mudar o nome dele, para vai_de_grails.war, independente da versão da nossa aplicação. Podemos fazer isso acrescentando uma clousure war, e definindo o archiveName com nome do arquivo que queremos no arquivo build.gradle. Desse modo, essa clousure ficará assim:

war {
   archiveName = "vai_de_grails.war"
}

Agora independente da versão da nossa aplicação, sempre o nome do arquivo será vai_de_grails.war.

Mas e se quisermos alterar também a localização do arquivo war gerado? Por exemplo, criá-lo dentro do diretório dist da nossa aplicação (que ainda não existe). Fácil, basta definir o destinationDir dentro da clousure war:

war {
   archiveName = "vai_de_grails.war"
   destinationDir = new File("/home/bruno/minhaAplicacao/dist")
}

Observe que agora tivemos que passar um arquivo (File) como parâmetro. Note que passamos o caminho completo da nossa aplicação: /home/bruno/minhaAplicacao. Isso é muito feio, uma vez que se outro usuário baixar nosso projeto, provavelmente ele não terá um usuário com o mesmo nome que o nosso. Um modo de resolver isso é usar as variáveis de sistema inicializadas pelo Grails. Podemos então trocar o destinatioDir para:

war {
   archiveName = "vai_de_grails.war"
   destinationDir = new File("${System.properties.getProperty("base.dir")}/dist")
}

Desse modo, agora não importa mais onde nossa aplicação esteja localizada. Vamos sempre obter o caminho completo para ela usando a propriedade base.dir, com o comando ${System.properties.getProperty(“base.dir”)}.

Outro modo é simplesmente definir um caminho relativo ao diretório da nossa aplicação:

war {
   archiveName = "vai_de_grails.war"
   destinationDir = new File("dist")
}

Outro recurso interessante é utilizar variáveis que são definidas no próprio build.gradle. A variável version que alteramos ao longo desse post pode ser utilizada caso queiramos que nosso arquivo seja nomeado vai_de_grails-versao_aplicacao.war, desse modo:

war {
   archiveName = "vai_de_grails-${version}.war"
   destinationDir = new File("dist")
}

Espero que tenha ficado claro a flexibilidade do comando grails war. Temos um controle completo sobre o local e o nome do arquivo war gerado por ele. Ele é bastante útil para por exemplo fazer o deploy da nossa aplicação no Tomcat, ou qualquer outro servidor web. Dentro do arquivo build.gradle conseguimos utilizar variáveis definidas por nós mesmos, variáveis iniciadas pelo Grails e podemos até chumbar valores.

Em posts futuros pretendo mostrar como implantar o war gerado em uma instância do Tomcat, e novos modos de rodar nossa aplicação como um serviço. Qualquer dúvida, ou sugestão fiquem a vontade para comentar! Abraços e até a próxima.

“Porque Deus tanto amou o mundo que deu o seu Filho Unigênito, para que todo o que nele crer não pereça, mas tenha a vida eterna.
João 3:16

Intermediário

Dockerizando o ambiente de desenvolvimento! – Parte 4

Pessoal,

Esse é o último post da série “Dockerizando o ambiente de desenvolvimento!”. Mas pretendo escrever mais no futuro sobre como utilizar o Docker para melhorar o ambiente de desenvolvimento, bem como para rodar testes automatizados, e quem sabe, até colocá-lo em produção.

No entanto, vamos ao que interessa. No post passado, nós paramos no ponto que rodamos a nossa recém-criada imagem. No entanto, tínhamos basicamente dois problemas:

  • Qualquer arquivo que criássemos na imagem do docker, não ficava salvo no nosso computador, e ao fechar e reabrir a imagem, tudo o que tinhamos feito era perdido.
  • Ao rodar a aplicação com o grails run-app, não conseguíamos acessar através do nosso browser.

Esses são limitantes muito grandes na utilização de uma imagem do jeito que definimos. Felizmente, é possível superar essas duas barreiras com recursos do próprio Docker.

Primeiro, vamos ver como permitir que acessemos a porta 8080 da nossa máquina do Docker. Na definição do nosso Dockerfile, na segunda parte do nossa série, eu tinha adicionado esse trecho de código:

# Expoe as portas utilizadas para desenvolvimento
# Porta do Backend
EXPOSE 8080

Esse código informa ao Docker que ele deve expor a porta 8080 da máquina criada. No entanto, isso não basta. Ao rodarmos a imagem, temos que informar que pretendemos fazer o binding, ou seja, desejamos conectar uma porta do nosso computador com a porta liberada no Docker.

Vamos supor que queremos acessar na porta 8888 o conteúdo exposto pela porta 8080 da máquina do Docker. Ou seja, queremos acessar nossa aplicação Grails (que será rodada com o grails run-app) diretamente na porta 8888 do nosso PC. Para isso basta acrescentar esse mapeamento de portas no comando que utilizamos na terceira parte da série, reproduzido aqui:

docker run -i -t eu/meu-ambiente-grails:1.0.0 /bin/bash

Com isso, esse comando ficará assim:

docker run -i -t eu/meu-ambiente-grails:1.0.0 -p 8888:8080 /bin/bash

O parâmetro -p é responsável por definir esse mapeamento. O primeiro número (8888) é o número da porta do nosso PC. Já o segundo (8080) é a porta da imagem do Docker, que foi liberada com o comando EXPOSE no Dockerfile. Note, que se tivéssemos liberado outras portas no Dockerfile, poderíamos mapear todas para portas de nosso PC. Por exemplo, imaginando que a porta 5432 no Dockerfile estivesse liberada, poderíamos ter o seguinte comando:

docker run -i -t eu/meu-ambiente-grails:1.0.0 -p 8888:8080 -p 5555:5432 /bin/bash

Onde agora além de mapearmos a porta 8080 da imagem do Docker para nossa porta 8888, também mapeamos a porta 5432 para a nossa porta 5555.

Se rodarmos agora o comando:

docker run -i -t eu/meu-ambiente-grails:1.0.0 -p 8888:8080 /bin/bash

E dentro da imagem do Docker executarmos o comando grails run-app, poderemos abrir nosso browser, e acessar nossa aplicação digitando o seguinte endereço:

localhost:8888

De maneira análoga, podemos também mapear um diretório do nosso computador para a imagem do Docker. Desse modo, todas as alterações que fizermos no diretório respectivo da imagem do Docker, serão realizadas também no diretório de nosso computador. Com isso, mesmo parando e reiniciando a imagem do Docker, as alterações serão preservadas.

Para isso basta acrescentar o parâmetro -v, do seguinte modo:

docker run -i -t eu/meu-ambiente-grails:1.0.0 -p 8888:8080 -v $HOME/git:/home/developer/git /bin/bash

No exemplo, mapeamos o diretório git, na home de nosso usário para o diretório /home/developer/git da imagem do Docker. Portanto, ao rodarmos nossa imagem, todas as alterações feitas nos arquivos do diretório /home/developer/git serão salvas no diretório git de nosso usuário.

Eu normalmente faço esse mapeamento, pois todos os projetos que trabalho usam como controle de versão o GIT (recomendo fortemente que façam o mesmo), e portanto salvo todos dentro do diretório git do meu usuário.

No caso do git, como podemos conectar com nossos repositórios com chave SSH, é interessante também, caso quisermos fazer commits, pulls, e outros comandos dele, mapear também nossa pasta $HOME/.ssh para a pasta /home/developer/.ssh. Desse modo, a chave SSH do nosso computador será utilizada pela imagem do Docker, e portanto conseguiremos acessar normalmente nossos repositórios. Para fazer isso, basta acrescentar um novo parâmetro -v com o mapeamento:

docker run -i -t eu/meu-ambiente-grails:1.0.0 -p 8888:8080 -v $HOME/git:/home/developer/git -v $HOME/.ssh:/home/developer/.ssh /bin/bash

Ou seja, se na nossa equipe todos os desenvolvedores rodarem desse mesmo jeito a imagem que criamos, todos terão acesso a mesma versão do Grails, poderão acessar a aplicação rodando em localhost:8888, e poderão fazer seus commits e pulls da vida no GIT, usando suas próprias chaves SSH.

Isso é apenas o básico de um ambiente padronizado de desenvolvimento. Como eu disse, pretendo no futuro escrever mais sobre essas questões, mas já dá pra ter uma ideia de quanto o Docker ajuda. E talvez para alguns já seja um grande ponta-pé em direção a um ambiente padronizado!

Espero que tenham gostado da série, e sintam-se a vontade para escrever sobre suas dúvidas ou sugestões. Se quiserem saber mais de Grails e Docker, recomendo também que entrem em nosso grupo no Linkedin. Abraços a todos e até a próxima!!!

O escarnecedor busca sabedoria e não acha nenhuma, para o prudente, porém, o conhecimento é fácil.

Provérbios 14:6

Intermediário

Dockerizando o ambiente de desenvolvimento! – Parte 3

Olá pessoal!

Continuando nossa jornada no mundo “Dockerizado“, vamos ver como gerar a imagem que construímos na parte 2 e como listar nossas imagens Docker. Essa é uma parte muito importante, uma vez que veremos se o código que programamos no Dockerfile está correto. Além disso, poderemos definir também o nome da nossa imagem, e sua versão.

O modo mais fácil de gerar uma imagem Docker é entrar no diretório que contém o Dockerfile, e executar o seguinte comando:

docker build .

No entanto, desse modo, sua imagem terá um “nome” aleatório. O mais legal, é definir como será chamada a sua imagem. Isso pode ser feito acrescentando o parâmetro -t. Com ele, você pode definir um nome e uma tag para identificar a sua imagem. Esse comando tem a seguinte sintaxe:

docker build -t <usuario>/<repositorio>:<tag> .

Por exemplo, no caso da imagem do ambiente de desenvolvimento criada pelo Vai de Grails!, o comando utilizado foi assim:

docker build -t vaidegrails/ambiente-grails-basico:3.1.9 .

Nesse caso vaidegrails é o nome do usuário utilizado no Docker Hub, ambiente-grails-basico é o nome do nosso repositório (como se fosse um repositório no GitHub), e 3.1.9 é nossa tag. Note que a tag pode ter o formato que você quiser. Por exemplo, poderia ser v2.

Vamos utilizar como exemplo o Dockerfile mostrado no post anterior. Copie-o e coloque em um diretório qualquer. Entre no diretório e execute o comando:

docker build -t eu/meu-ambiente-grails:1.0.0

Ao executar esse comando, vão aparecer linhas como as seguintes:

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:14.04
14.04: Pulling from library/ubuntu
862a3e9af0ae: Pull complete
6498e51874bf: Pull complete
159ebdd1959b: Pull complete
0fdbedd3771a: Pull complete
7a1f7116d1e3: Pull complete

Serão listados todos os steps (definidos no Dockerfile) que serão executados para a geração da sua imagem. No final, será mostrada a mensagem Successfully built, indicando que sua imagem foi criada com sucesso. Após a geração da sua imagem, você pode confirmar que ela foi criada usando esse comando:

docker images

REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
eu/meu-ambiente-grails   latest              46b0ee272f11        3 months ago        911.7 MB

Esse comando mostra todas as imagens que você tem disponíveis no seu Docker. Podemos reparar que agora a imagem que acabamos de criar encontra-se entre as disponíveis. Também está disponível a imagem ubuntu14.04 que definimos como base para a nossa imagem no Dockerfile. O comando docker images mostra o repository (nome de usuário mais o repositório), tag, id da imagem, quando ela foi criada e o tamanho em disco que cada imagem ocupa.

Agora finalmente poderemos utilizar nossa imagem. Para isso, basta rodar:

docker run -i -t eu/meu-ambiente-grails:1.0.0 /bin/bash

Esse comando, além de rodar nossa imagem (eu/meu-ambiente-grails:1.0.0), define que deve ser criado um pseudo terminal (-t) e que ele deve estar conectado a sua entrada stdin (-i). Por fim, definimos que vamos rodar o programa /bin/bash. Com isso, teremos acesso a um terminal Linux completo, onde poderemos utilizar todos os comandos Linux que estamos acostumados, como ls, cd, mkdir, etc.

Como instalamos o Grails na nossa imagem, poderemos utilizar os comandos do Grails, como:

grails create-app novaApp

No entanto tem um problema, se sairmos da nossa imagem, digitando exit, e colocarmos ela para rodar novamente, veremos que a aplicação que criamos não existe mais. Isso ocorre porque as imagens Docker não são persistentes, ou seja, ao rodarmos ela novamente, tudo estará como definimos na imagem, e todas as alterações realizadas serão descartadas. Além disso, ao rodarmos a aplicação Grails, não conseguiremos acessar pelo browser nossa aplicação.

Mas calma aí, então quer dizer que eu falei de Docker para ajudar a criar um ambiente de desenvolvimento durante 3 posts, e ele tem todas essas limitações? Sim e não. Explico: sim, o Docker tem essas limitações se utilizarmos do modo simples como utilizamos. E não, não precisamos conviver com essas restrições. O Docker tem mecanismos para superarmos esses problemas.

No próximo post verificaremos como manter salvas as aplicações que criamos e como acessá-las diretamente do nosso navegador, tornando ele uma ótima opção para mantermos nosso ambiente de desenvolvimento! Até lá pessoal!

Intermediário

Dockerizando o ambiente de desenvolvimento! – Parte 2

Olá pessoal,

No post passado  nós vimos como instalar o Docker e rodamos uma imagem de exemplo, denominada hello-world (muito original… :D). Até então, não ficou muito claro qual o objetivo de instalarmos o Docker no nosso ambiente de desenvolvimento. No post de hoje, vamos começar a ver algumas das vantagens dessa abordagem, uma vez que vamos definir como será nosso ambiente de desenvolvimento Grails definindo uma imagem do Docker.

No entanto, para isso é necessário primeiro entender alguns conceitos do Docker. Tudo se inicia pela definição de uma imagem, utilizando um Dockerfile, que nada mais é que uma série de passos que devemos executar para que uma máquina fique com as características que desejamos. Fazendo uma analogia muito manjada, o Dockerfile pode ser entendido como a receita de um bolo. A receita não é um bolo, mas contém os passos necessários para a preparação de um tipo específico de bolo.

Um Dockerfile se resume a uma série de instruções, acompanhadas de seus argumentos, no seguinte formato:

INSTRUCTION arguments

Uma convenção adotada é que a instrução deve aparecer sempre com letras maiúsculas, apesar de não ser necessário. Obrigatoriamente, a primeira instrução que deve aparecer  em um Dockerfile é a instrução FROM. Essa instrução define qual é a imagem base que estamos utilizando na nossa “receita”. Uma imagem base não se baseia em nenhuma outra imagem, ou seja, não tem imagens pai. Normalmente essas imagens definem algum sistema operacional, como por exemplo Ubuntu ou CentOS.

Vamos começar então a criar nosso próprio Dockerfile. Assumindo que você esteja em um ambiente Linux, crie primeiro um diretório para armazenar o Dockerfile:

mkdir ambiente-grails-basico

Entre nele, e crie um arquivo Dockerfile com os seguintes comandos:

cd ambiente-grails-basico

touch Dockerfile

Edite o seu Dockerfile com o editor de texto da sua preferência e adicione a seguinte linha:

FROM ubuntu:14.04

Como vimos, essa linha define que nossa imagem base é a versão 14.04 do Ubuntu. Abaixo dessa linha, você pode (e deve :D) definir quem é o responsável por manter essa imagem, utilizando a instrução MAINTAINER, que tem o seguinte formato:

MAINTAINER Seu nome <seu e-mail>

No caso do Vai de Grails! fica assim:

Vai de Grails! <contato@vaidegrails.com>

Agora podemos começar a instalar os programas que queremos na nossa imagem. Como estamos utilizando uma versão do Ubuntu, podemos utilizar o apt-get install, do mesmo modo que fazemos em nossa máquina. É importante dizer, que como não definimos qual usuário estamos utilizando, por padrão estaremos utilizando um usuário ROOT, por tanto não precisamos adicionar o sudo na frente do apt-get install.

Para rodar o apt-get install, ou qualquer outro comando, temos que utilizar a instrução RUN. Vamos instalar inicialmente os seguintes programas:

  • curl – Utilizado para poder baixar o SDKMAN
  • git – Para versionamento de código
  • gitg – Visualização gráfica do repositório git
  • nano – Editor de texto leve
  • software-properties-common – Certificados CA utilizados para instalar o SDKMAN
  • unzip – Utilizado pelo SDKMAN para descompactar arquivos zipados

Essa instalação pode ser realizada com o comando a seguir:

RUN apt-get update \
&& apt-get install -y \
curl \
git \
gitg \
nano \
software-properties-common \
unzip \
&& rm -rf /var/lib/apt/lists/*

Observe que podemos utilizar o caracter ‘\‘ no fim da linha, pois desse modo podemos colocar cada programa que será instalado em uma linha, o que facilita a leitura do Dockerfile, e é uma boa prática estimulada pela equipe do Docker.

O símbolo ‘&&‘ é utilizado quando vamos executar outro comando na sequencia. É importante ressaltar que sempre quando formos utilizar o apt-get install, devemos realizar o apt-get update e separá-los com o ‘&&‘. Se não fizermos eles no mesmo comando RUN, o apt-get install não considerará os repositórios atualizados. Essa é uma característica do Docker.

Por último, sempre é bom remover o conteúdo do diretório /var/lib/apt/lists, uma vez que queremos deixar nossa imagem o mais enxuta possível. O conteúdo desse diretório sempre é recriado quando utilizamos o apt-get update. Para removê-lo utilizamos o comando rm -rf.

Outro componente necessário para configurarmos o ambiente de desenvolvimento Grails é o OpenJDK. A versão 8, com a qual o Grails 3 é compatível, será instalada. Vamos instalá-la adicionando o repositório ppa:openjdk-r/ppa. A adição do repositório e a instalação do OpenJDK é realizada com o seguinte comando:

RUN add-apt-repository ppa:openjdk-r/ppa -y \
&& apt-get update \
&& apt-get install -y openjdk-8-jdk \
&& rm -rf /var/lib/apt/lists/*

Nesse momento, já temos todos os programas necessários para instalarmos o SDKMAN. No entanto, antes de instalarmos esse fácil utilitário, vamos definir um novo usuário Linux. Esse usuário terá como login o nome developer. Para criá-lo, vamos utilizar também o comando RUN e o comando useradd para definir que nosso usuário não terá password (-p “”) e utilizará o bash (-ms /bin/bash):

### Criação do usuário developer ###
RUN useradd -p "" -ms /bin/bash developer

Com o usuário criado, vamos definir a variável de ambiente HOME como sendo o diretório do usuário developer:

ENV HOME /home/developer

E informar ao Docker que ele deve utilizar o usuário developer para executar os próximos comandos:

USER developer

Também é importante definir que o diretório atual de trabalho é o diretório do nosso novo usuário. Essa é uma boa prática também de arquivos Dockerfile, ao invés de utilizar o comando linux cd para definir o diretório atual:

WORKDIR $HOME

Observe que utilizamos a variável HOME que setamos anteriormente. Esse uso é feito por meio da sintaxe $<NOME_DA_VARIÁVEL>, tal como fazemos no Linux.

Podemos agora instalar o SDKMAN seguindo o esse post, obviamente que adaptando para o formato esperado pelo Docker:

RUN curl -s get.sdkman.io | bash
RUN /bin/bash -c "source $HOME/.sdkman/bin/sdkman-init.sh \
&& sdk install grails 3.1.9"

Então primeiro utilizamos o curl para baixar o SDKMAN, e depois rodamos o source para inicializar as variáveis de ambiente utilizadas pelo SDKMAN. Por último, instalamos a versão do Grails, no caso do exemplo, a versão 3.1.9 (a mais atual disponível na data desta postagem).

O último passo que executaremos será expor a porta 8080 do nosso container, que é a porta padrão onde rodam as aplicações do Grails.

# Expoe as portas utilizadas para desenvolvimento
# Porta do Backend
EXPOSE 8080

Com isso, conseguiremos rodar uma aplicação Grails no container, e acessar da nossa máquina. Mas antes disso, teremos que dar um build nele, para gerar a imagem que vai ser utilizada pelo Docker. Esse passo veremos no próximo post dessa série. O projeto no Github, com o Dockerfile criado nesse post pode ser encontrado aqui.

Nos próximos posts veremos como construir essa imagem e como rodá-la em nossos computadores. Qualquer dúvida, ou sugestão, fiquem a vontade para mandar aqui.

Abraços e até a próxima!

“Fazei todas as coisas sem murmurações nem críticas, a fim de serdes irrepreensíveis e inocentes, filhos de Deus íntegros, no meio de uma sociedades depravada e maliciosa, onde brilhais como luzeiros no mundo.”

Filipenses 2:14-15

 

Intermediário

Dockerizando o ambiente de desenvolvimento! – Parte 1

Olá pessoal,

Cada vez mais temos ouvido falar no Docker. Ele é bastante interessante, pois conseguimos criar uma “receita de bolo”, especificando como queremos configurar uma determinada máquina. O Docker cria um container em nossa própria máquina, e esse container será configurado igual especificamos na receita.

Você deve estar pensando, nossa, qual a vantagem disso? Vamos imaginar por exemplo num ambiente de desenvolvimento, onde cada desenvolvedor utiliza uma versão do Linux. Um usa Ubuntu, outro Fedora, outro usa Slackware… Como garantir que todos vão utilizar a mesma versão do Grails e do banco de dados por exemplo?

Um modo seria criar essa receita de bolo, e compartilhá-la entre os desenvolvedores. Sendo assim, todos conseguiriam usar um container igual, independente da sua versão do Linux. É isso o que vamos abordar nessa pequena série. Hoje vamos ver como instalar o Docker. Nas próximas partes veremos como criar uma receita para termos o Grails e o PostgreSQL instalados no container, assim como comandos para gerenciarmos as imagens e containers disponíveis em nosso sistema.

Sendo assim, vamos começar vendo como preparar o ambiente para instalar o Docker no seu Ubuntu ou Mint. Se você utiliza o Mint (como eu), pode rodar o seguinte comando para descobrir em qual versão do Ubuntu seu Mint é baseado:

$ grep "PRETTY_NAME" /etc/os-release | awk '{ print $2 }'

Um exemplo de resposta é:

14.04.4

Nesse caso, sua versão é a 14.04 (Ubuntu Trusty). Portanto, considere essa como sua “versão do Ubuntu”). O resto do tutorial é igual tanto para Mint quanto para Ubuntu.

Preparando o ambiente

Voltando então ao que interessa, vamos começar a instalação do Docker na nossa máquina. O primeiro passo é descobrir a versão do seu kernel Linux. A versão do Kernel deve ser no mínimo 3.10.0. Para isso vamos utilizar o comando uname -r. No exemplo de resposta abaixo, a resposta foi 3.2.0-52-generic:

$ uname -r
3.2.0-52-generic

Ou seja, como a versão 3.2.0 é menor do que a 3.10.0, eu não conseguiria rodar o Docker. Seria necessário atualizar o kernel. Caso você já tenha uma versão igual ou maior a 3.10.0, por exemplo 3.13.0-37-generic, você pode ir par ao próximo passo, que é atualizar o índice de pacotes do APT e instalar o módulo para ele utilizar o protocolo HTTPS, e ter os certificados CA instalados:

$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates

Podemos então instalar uma nova chave GPG que será utilizada para acessar o repositório do Docker:

sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

É necessário então criar (caso não exista) o arquivo /etc/apt/sources.list.d/docker.list e se ele já existir, deve-se retirar todo o seu conteúdo e adicionar somente a linha abaixo, alterando a parte em negrito de acordo com a versão do seu Ubuntu:

deb https://apt.dockerproject.org/repo versao_do_ubuntu main

Abaixo temos uma listagem com as versões do Ubuntu, e qual o valor da variável versao_do_ubuntu respectiva:

Versão do Ubuntu Variável versao_do_ubuntu
Ubuntu Precise 12.04 ubuntu-precise
Ubuntu Trusty 14.04 ubuntu-trusty
Ubuntu Wily 15.10 ubuntu-wily
Ubuntu Xenial 16.04 ubuntu-xenial

Portanto se sua versão for a Ubuntu Trusty 14.04, a linha que você vai ter no arquivo /etc/apt/sources.list.d/docker.list será:

deb https://apt.dockerproject.org/repo ubuntu-trusty main

Salve seu arquivo e depois atualize novamente o índice do APT:

$ sudo apt-get update

Remova o repositório antigo do Docker (caso exista):

$ sudo apt-get purge lxc-docker

Verifique que o apt está buscando o docker no repositório coreto:

$ apt-cache policy docker-engine

Aqui o resultado foi o seguinte:

docker-engine:
  Instalado: (nenhum)
  Candidato: 1.11.2-0~precise
  Tabela de versão:
     1.11.2-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.11.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.11.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.10.3-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.10.2-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.10.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.10.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.9.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.9.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.8.3-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.8.2-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.8.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.8.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.7.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.6.2-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.6.1-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.6.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages
     1.5.0-0~precise 0
        500 https://apt.dockerproject.org/repo/ ubuntu-precise/main amd64 Packages

Mais uma vez vamos atualizar o índice do APT:

$ sudo apt-get update

Agora os próximos passos vão depender da versão do seu Ubuntu:

Versões Ubuntu Xenial 16.04 e Ubuntu Wily 15.10

Basta instalar o o pacote linux-image-extra:

$ sudo apt-get install linux-image-extra-$(uname -r)

Versão Ubuntu Trusty 14.04

Instale o linux-image-extra e o apparmor

$ sudo apt-get install linux-image-extra-$(uname -r) apparmor

Versão Ubuntu Precise 12.04

Instale o linux-image-extra, o apparmor, o linux-image-generic-lts-trusty, o linux-headers-generic-lts-trusty, o xserver-xorg-lts-trusty e o libgl1-mesa-glx-lts-trusty

$ sudo apt-get install linux-image-extra-$(uname -r) apparmor linux-headers-generic-lts-trusty xserver-xorg-lts-trusty libgl1-mesa-glx-lts-trusty

O xserver-xorg-lts-trusty e o libgl1-mesa-glx-lts-trusty são opcionais, somente necessários se você estiver em uma máquina com ambiente gráfico.

Faça o reboot do sistema:

$ sudo reboot

Instalando (finalmente) o Docker

Agora que tudo já foi preparado, vamos atualizar o índice de pacotes do APT:

$ sudo apt-get update

Instale o Docker (aaewwww \o/)

$ sudo apt-get install docker-engine

Inicialize o daemon do Docker:

$ sudo service docker start

E finalmente mande rodar o Hello World do Docker para verificar se tudo está funcionando adequadamente:

$ sudo docker run hello-world

A saída desse comando será mais ou menos a seguinte:


Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world

a9d36faac0fe: Pull complete
Digest: sha256:e52be8ffeeb1f374f440893189cd32f44cb166650e7ab185fa7735b7dc48d619
Status: Downloaded newer image for hello-world:latest

Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com

For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/

Pronto, o Docker está instalado corretamente! Acompanhem o Vai de Grails! para as próximas partes da série. Qualquer dúvida ou comentário, postem aqui!

Obrigado e até a próxima pessoal!

Iniciante

Mostrando os comandos SQL do Hibernate

Pessoal,

Hoje vou apresentar uma dica fácil de fazer, mas muito útil. Vamos apresentar no log da nossa aplicação os comandos SQL executados pelo Hibernate. Desse modo, é possível ver os creates, selects, updates, deletes e outras consultas que estão sendo executadas pela nossa aplicação e analisar se estão de acordo com o esperado.

Para isso, vamos criar um projeto novo sobre futebol:

grails create-app Futebol

Vamos também adicionar uma nova classe chamada Campeonato:

grails create-domain-class com.vaidegrails.futebol.Campeonato

E vamos alterar a classe para que fique assim:

package com.vaidegrails.futebol

class Campeonato {

    String nome
    static constraints = {
    }
}

Vamos também alterar nosso BootStrap.groovy para manipular o banco de dados, assim conseguiremos ver o que o Hibernate está fazendo:

import com.vaidegrails.futebol.Campeonato

class BootStrap {

    def init = { servletContext ->
        10.times { i->
            Campeonato campeonato = new Campeonato(nome: "Campeonato $i").save(flush: true)
        }

        def todosCampeonatos = Campeonato.all
        def campeonato3 = Campeonato.findByNome("Campeonato 3")
        def campeonato5 = Campeonato.findByNome("Campeonato 5")
        campeonato3.delete(flush: true)
        campeonato5.nome = "Campeonato 3"
        campeonato5.save(flush: true)
    }
    def destroy = {
    }
}

Nesse trecho de código, primeiro utilizamos o código 10.times, o qual significa que vamos repetir 10 vezes o código que está dentro da clousure (delimitada pelas chaves). Essa síntaxe do Groovy é muito legal, pois fica bem legível e semântico o código. Definimos a variável i, que é o índice do looping. E então criamos um campeonato usando essa variável i. Então teremos 10 campeonatos salvos na base, desde o Campeonato 0, até o Campeonato 9.

Após salvar os campeonatos, vamos obter do banco todos os campeonatos cadastrados (Campeonato.all). Também vamos buscar pelo nome (Campeonato.findByNome) os campeonatos 3 e 5.

Por fim, vamos remover do banco de dados o campeonato 3 (campeonato3.delete) e alterar o nome do Campeonato 5 para Campeonato 3, e salvar essa atualização (campeonato5.save).

Se executarmos o código nesse momento, não veremos o log do Hibernate. Para conseguirmos ver o log, vamos alterar a seção datasource do arquivo application.yml para que fique assim:

dataSource:
    pooled: true
    jmxExport: true
    driverClassName: org.h2.Driver
    username: sa
    password:
    logSql: true

Observe em negrito o logSql: true. É essa a configuração responsável por exibir o log. Ao rodarmos novamente a aplicação, conseguiremos ver a seguinte saída no console:

Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: insert into campeonato (id, version, nome) values (null, ?, ?)
Hibernate: select this_.id as id1_0_0_, this_.version as version2_0_0_, this_.nome as nome3_0_0_ from campeonato this_
Hibernate: select this_.id as id1_0_0_, this_.version as version2_0_0_, this_.nome as nome3_0_0_ from campeonato this_ where this_.nome=? limit ?
Hibernate: select this_.id as id1_0_0_, this_.version as version2_0_0_, this_.nome as nome3_0_0_ from campeonato this_ where this_.nome=? limit ?
Hibernate: delete from campeonato where id=? and version=?
Hibernate: update campeonato set version=?, nome=? where id=? and version=?

Nas 10 primeiras linhas, vemos os inserts dos campeonatos. É importante ressaltar que os sinais de interrogação representam parâmetros passados pelo nosso código em Grails, nesse caso, o version e o nome.

Depois dos inserts, temos um select na tabela campeonato retornando todos os registros. Na sequencia, dois selects passando como parâmetro o nome, para retornar os campeonatos 3 e 5. As duas últimas linhas são referentes a remoção do Campeonato 3 e a atualização do campeonato 5, definindo um novo version e um novo nome.

Esses casos que apresentei são bem simples, mas pode ser muito interessante mostrar as consultas realizadas em casos mais complexos, onde existem joins, por exemplo.

Outra questão importante, é que ao configurar o logSql na seção datasource, igual fizemos, todos os ambientes de desenvolvimento (development, test e production). Isso não é desejável. Para mostrar o log somente em development, basta colocar o logSql: true dentro da seção environments -> development -> datasource, ou seja, o arquivo application.yml deve ficar assim:

environments:
    development:
        dataSource:
            dbCreate: create-drop
            url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
            logSql: true

E claro, retirar do datasource (caso você tenha colocado lá no início). Espero que tenham gostado! Qualquer dúvida, ou sugestão, postem comentários. Até a próxima.

Iniciante

Como instalar o Grails?

Pessoal,

Anteriormente eu havia mostrado um jeito de configurar um ambiente de desenvolvimento Grails. Muita coisa mudou de lá pra cá. Novas versões do Grails surgiram, o gvm mudou e passou a se chamar sdkman, entre outras.

O que não mudou foi a facilidade de instalar o Grails. Existem dois modos muito simples de instalá-lo na sua máquina. O primeiro é utilizando o sdkman (http://sdkman.io):

curl -s “https://get.sdkman.io” | bash
source “$HOME/.sdkman/bin/sdkman-init.sh
sdk install grails 3.1.6

O segundo é o Jenv (http://jenv.io/):

curl -L -s get.jenv.io | bash jenv install grails
source /home/bruno/.jenv/bin/jenv-init.sh
jenv install grails 3.1.4

O sdkman tem a versão mais recente do Grails (3.1.6), o Jenv por enquanto está um pouco atrasado (3.1.4), mas os dois são muito práticos e úteis, e permitem instalar diversos outros frameworks. Vale a pena dar uma olhada!

Se você não passar a versão ao dar os comandos sdk e jenv, ele instala a versão mais recente disponível. Agora não tem mais desculpa para não “ir de Grails”😀.

Após a instalação basta digitar Grails no terminal e ser feliz. Caso você utilize o IntelliJ Idea (recomendo), configure ele para usar o Grails a partir de um dos diretórios abaixo (use o primero se utilizou o sdkman para instalar e o segundo se usou o Jenv):

/home/nome_do_seu_usuario/.sdkman/candidates/grails/3.1.6

/home/nome_do_seu_usuario/.jenv/candidates/grails/3.1.4

E é só isso! Abraços e até a próxima.