DevSecOps

24 dez, 2018

Devops: CI/CD Azure Pipeline + Docker + YAML

Publicidade

Microsoft Azure sempre foi uma das clouds mais queridas senão a mais pelos desenvolvedores Microsoft. Recentemente, o Azure VSTS se tornou o Azure Devops e agora, no quarto trimestre de 2018, o Azure Devops liberou uma feature muito bacana! Feature que irá aumentar muito a flexibilidade de configuração de pipelines. Agora, é possível realizar as configurações de CI/CD através de arquivos YAML.

Para exemplificar como funciona, vamos configurar integração contínua e deploy contínuo para uma aplicação docker no Azure. Este artigo cobrirá os seguintes passos:

  1. Criação do arquivo azure-pipelines.docker.yaml;
  2. Configuração da CI no Azure Devops a partir do arquivo azure-pipelines.docker.yaml;
  3. Criação de um Web App com Docker no Azure;
  4. Configuração do CD no Azure/Docker Hub. Criaremos um web hook no Docker Hub para que, toda vez que um novo push da imagem for realizado o container docker rodando no Azure seja atualizado.

Azure Pipeline com Docker

Para continuarmos é necessário que você tenha um pequeno projeto docker para realizarmos as configurações, caso queira algo mais prático, pode baixar o projeto que eu deixei preparado para este exemplo aqui.

Crie um arquivo chamado azure-pipelines.docker.yaml. A primeira configuração do arquivo deve ser qual pool será utilizada para buscar um agent para realizar as tasks que configuraremos no arquivo azure-pipelines.docker.yaml.

pool:
  vmImage: 'Ubuntu 16.04'

Neste caso, especificamos uma máquina ubuntu com versão 16.04. Depois da seção pool, entraremos na seção variables do arquivo, onde apenas configuraremos o tipo do build e o nome da nossa imagem docker.

variables:
  buildConfiguration: 'Release'
  imageName: 'devops:latest'

Na sequência da seção variables podemos configurar os steps do build. Veja, nosso primeiro step, como de costume em qualquer build, é a restauração dos pacotes NuGet. Para isto, executaremos o comando dotnet restore com a chave script.

steps:
- script: dotnet restore
  displayName: 'Restoring Packages'

Após a restauração dos pacotes, vamos realizar o build do projeto com o comando dotnet build –configuration $(buildConfiguration) parametrizado na chave script. Onde $(buildConfiguration) é o valor da variável configurado na seção variables.

- script: dotnet build --configuration $(buildConfiguration)
  displayName: 'Building Project'

Finalizado o build dos projetos da solução, já podemos embarcar na seção de execução dos testes do projeto.

- task: DotNetCoreCLI@2
  displayName: 'Testing'
  inputs:
    command: test
    projects: '**/*Tests/*.csproj'

Perceba agora a utilização da chave task, para que tudo não precise ser realizado “na mão” a microsoft nos disponibiliza algumas tasks prontas, onde podemos as utilizar dentro do arquivo azure-pipelines.docker.yaml, apenas passando os parâmetros que ela solicita. Na figura acima, estamos utilizando a task DotNetCoreCli na versão 2 para realizar os testes da nossa solução, a partir de todos projetos encontrados com o regex parametrizado (você pode conferir a lista completa de tasks disponivéis aqui).

Agora, o próximo passo é realizar o build da imagem docker:

- script: docker build --no-cache -f Dockerfile -t $(dockerId)/$(imageName) .
  displayName: 'Building Docker Image'

Na figura acima, você deve ter notado que foi utilizado uma variável não declarada na seção variables, a variável $(dockerId). Mais a frente, utilizaremos também a variável $(dockerPassword). Não é boa prática que essas variáveis fiquem chumbadas e expostas dentro do arquivo, por isso as configuraremos como variáveis do build. Não se preocupe com elas por enquanto.

Por último, basta realizar o push da imagem para o Docker Hub:

- script: |
    docker login -u $(dockerId) -p $(dockerPassword)
    docker push $(dockerId)/$(imageName)
  displayName: 'Sending Image to Docker Hub'

No final, seu arquivo azure-pipelines.docker.yaml deve ficar da seguinte maneira:

pool:
  vmImage: 'Ubuntu 16.04'

variables:
  buildConfiguration: 'Release'
  imageName: 'devops:latest'

steps:
- script: dotnet restore
  displayName: 'Restoring Packages'

- script: dotnet build --configuration $(buildConfiguration)
  displayName: 'Building Project'

- task: DotNetCoreCLI@2
  displayName: 'Testing'
  inputs:
    command: test
    projects: '**/*Tests/*.csproj'

- script: docker build --no-cache -f Dockerfile -t $(dockerId)/$(imageName) .
  displayName: 'Building Docker Image'

- script: |
    docker login -u $(dockerId) -p $(dockerPassword)
    docker push $(dockerId)/$(imageName)
  displayName: 'Sending Image to Docker Hub'

Pronto! Agora que todas as configurações do nosso build estão finalizadas, basta seguir para o Azure Devops.

Configurando Build Azure Devops

Já criado o arquivo azure-pipelines.docker.yaml,agora precisamos criar um pipeline no Azure Devops que o utilize. Para criar um novo pipeline no Azure Devops, vá até Pipelines > Builds > New Build Pipeline. A primeira coisa a se fazer é configurar a fonte/repositório do código. Neste caso, se você estiver utilizando o mesmo projeto que disponibilizei basta apontar o endereço no GitHub (você precisará realizar login, então suba o projeto no seu GitHub). Clique em Continue.

Feito isso, agora você terá a opção de escolher qual o template a ser utilizado no build. Em Configuration as code, selecione a opção YAML e clique em APPLY.

Agora, basta escolher um nome para este projeto de integração contínua, configurar o mesmo Agent pool que foi configurado no arquivo azure-pipelines.docker.yaml e, então, parametrizar o caminho do arquivo azure-pipelines.docker.yaml.

Se lembra daquelas variáveis que iríamos configurar no build? Precisamos configurá-las agora. Clique em Variables, ao lado da guia atual, YAML. Defina as variáveis dockerId e dockerPassword, parâmetros necessários para realizar login na sua conta no DockerHub. Clique em Save & queue.

Finalmente, aqui está o build executado com sucesso!

E aqui está a imagem no Docker Hub!

Como agora já temos uma imagem disponivel no Docker Hub, precisamos apenas criar uma aplicação no Azure para consumi-la.

Configurando Deploy Contínuo Azure

Dentro do Portal Azure, crie um novo aplicativo. Como de prache, será solicitado a escolha do nome do aplicativo, assinatura e grupo de recursos (Procedimento padrão). Atenção na escolha do sistema operacional! Escolha Linux e, na sequência, em Publish, selecione Docker Image.

Agora sim! Vamos configurar o container do Web App para olhar para nossa imagem kenerry/devops:latest no Docker Hub. Selecione Configure container, escolha as opções Single container > Docker Hub > Public (imagem a seguir).Por último, coloque o nome da imagem que a aplicação utilizará para criar o container. Neste caso, kenerry/devops:latest. Clique em Apply e depois em Create para finalizar a criação do Web APP.

Após implantação com sucesso do aplicativo, clique nele e entre na guia Container settings. Dentro de Container settings, habilite a opção Continuous Deployment.

Antes de clicar em Save, copie a url do campo Webhook URL para que possamos colocar no Docker Hub, para que toda vez que nossa imagem receber um novo push, o container no azure seja atualizado. Copiou? Agora sim clique em Save.

Com o deploy contínuo habilitado no container Azure, basta entrar no repositório da imagem kenerry/devops no docker Hub, selecionar Webhooks e adicionar a URL coletada do Azure.

Muito bem! Agora qualquer novo push na imagem atualizará o container no azure. Confira já o aplicativo no ar!

Por hoje é só, pessoal! Espero que tenham gostado, até mais e um grande abraço! Qualquer dúvida, me procurem!