7
respostas

Infraestrutura docker-compose CI

Olá Douglas,

Assisti somente a parte de Networking por que estou com uma dúvida cabulosa na parte de infraestrutura e utilização do docker-compose em uma aplicação.

Uma das coisas era a comunicação entre containers que foi respondida nessa aula que assisti.

Para contextualizar, é o seguinte, atualmente tenho 3 apis, 1 sistema de autenticação em OAuth2, um sistema principal (vou chamar de SP), um repositório só para o rabbitMQ e um repositório só para o Redis.

Para cada um desses sistemas/APIs eu tenho um docker-compose + 4 docker-composes para os diferentes ambientes (Dev, test, stag e prod) e que para cada um eu subo um MySQL diferente em porta diferente.

Andei pensando em criar um repositório separado de tudo isso chamado deploy, onde eu configuraria 5 gitmodules (3 apis + 2 sistemas), criaria um docker-compose único, colocaria todo mundo na mesma rede e seria feliz.

Qual a sua experiência nesse tipo de estrutura? Seria válido criar um repositório separado? Pensando em Continuous Integration você entende que eu deveria criar uma imagem para cada API/sistema ou faria uma imagem única para tudo isso?

Minha idéia é simplificar a criação do ambiente para os devs e já pensar na CI.

Enfim, desculpe o texto longo mas não tem como ser de outra forma.

Boa noite

7 respostas

Oi Luiz, acredito que você possa criar um composer só pra subir a aplicação inteira (claro, considerando que cada uma dessas partes compoem uma aplicação só). Mas cada parte teria seu próprio repositório com um Dockerfile para buildar a imagem. Assim, no composer, cada service apontaria para uma imagem específica de cada parte da aplicação.

Outra coisa que me parece estranha é você precisar de um composer para cada ambiente. Como um ambiente deve ser espelho do outro com algumas pequenas configurações diferentes, me parece que variáveis de ambiente resolveriam os problemas. Contudo, não posso afirmar, não conheço o cenário exato.

Ola Wanderson,

Obrigado pela rápida resposta. Segue meu compose da dev e da prod

PRODUCAO

version: '3.3'
services:
  web:
    build:
      context: .
    volumes:
      - ./php/php.aws.ini:/usr/local/etc/php/php.ini
      - ./apache/resolv.conf:/etc/resolv.conf
      - ./apache/security.conf:/etc/apache2/sites-enabled/000-security.conf
    ports:
      - "8004:80"
    env_file:
      - ./envs/prod.env

DEV

version: '3.3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./php/php.dev.ini:/usr/local/etc/php/php.ini
    ports:
      - "2031:80"
    env_file:
      - ./envs/dev.env
      - ./envs/override.env
    depends_on:
      - db
    links:
      - db
  db:
    image: mysql:5.7.24
    ports:
      - "33071:3306"
    volumes:
      - ./mysql/conf.d/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./mysql/waitForMySQL.sh:/root/waitForMySQL.sh
    env_file:
      - ./envs/dev.env

Isso é de uma aplicação, veja que na prod não tem o service db, a porta é diferente da dev, utilizo outro env_file e possuo configurações de segurança do apache. Por esse motivo, uso docker-compose diferentes. Teria outra forma de fazer?

Estou realmente pensando em criar um repositório para subir todos os serviços em um unico docker-compose, inclusive seguindo a configuração de Networking que o Douglas comentou na aula (para todos os sistemas e apis ficarem na mesma rede e etc)

Mas minha dúvida ainda é na criação da imagem, se eu fizer um docker-compose unico eu iria criar somente uma imagem e subir para o Docker Hub ou uma imagem para cada serviço?

Opa, desculpa a demora, mas não, para cada serviço você pode e até deve ter uma imagem diferente, é por isso que temos a configuração de build disponível para cada configuração de service.

Eu estou vendo que você está usando volumes para substituir arquivos de configurações, quando na verdade, acredito que o comando copy dentro do Dockerfile seja a melhor solução, como é visto no curso.

E sobre variáveis de ambiente, não é recomendado ter um arquivo de env para produção no seu repositório, arquivos de env, sempre só pra dev.

envs de produção eu colocaria direto dentro do Dockerfile, já que ele vai ser usado pra fazer o build da imagem e só.

É o que eu acho. Faz sentido pra você?

Ola Wanderson,

Em relação as imagens, estou de acordo, cada serviço tem que ter sua imagem portanto, terei uma imagem para cada API e para cada sistema.

Em relação aos arquivos de configuração, você diz os resolv.conf e security.conf? Se sim, daí eu teria que ter um DockerFile para a dev e outro para stag e outro para prod?

"Envs de produção eu colocaria direto dentro do Dockerfile": Mesma coisa aqui, eu teria que ter N arquivos DockerFile?

Teria se realmente for necessário configurar algo diferente para cada ambiente. Pensa o seguinte:

1 - Para dev, eu preciso de um Dockerfile? Por que? Geralmente não por que o container com um envfile já é suficiente. Se você usar um Dockerfile em dev, para cada alteração no projeto, eu precisaria fazer o build da imagem pra depois criar o container, etc... Então o compose já mata o problema.

Claro, se você precisa de algumas configurações especiais até mesmo pra dev, então, você faz o build de uma imagem e deixa no repositório para ser usada pela equipe.

2 - Preciso de um Dockerfile para stage? Por que? Nesse caso, provavelmente sim já que o stage é um pré-produção, então nesse passo você não precisa do código, e sim de uma versão da app rodando com basicamente o mesmo setup de produção, não?

3 - Preciso de um Dockerfile para produção? Com certeza, mas se o seu stage é um espelho do ambiente que tá em produção, por que precisaria de um Dockerfile diferente?

A justificativa cai na questão dos valores, correto? Ah, uma variável de ambiente em um estágio tem um valor, e em outro estágio, tem outro valor. Então, por que não definir apenas as variáveis de ambiente em um Dockerfile só, e nos devidos composes, informar os valores?

Faz sentido?

Ola Wanderson,

Então, você diz para definir as variaveis de ambiente em um Dockerfile só mas na produção eu uso um banco de dados e na stag uso outro, essa informação, mesmo sendo sensível, são diferentes e não daria para deixar em um Dockerfile só, isso que não estou entendendo. Qual a melhor prática para carregar variaveis de ambiente sendo que as mesmas variam de ambiente para ambiente?

Para DEV eu uso o Dockerfile para facilitar a instalação de alguns pacotes necessários para o funcionamento da aplicação, como por exemplo o wkhtmltopdf, supervisor, xdebug e etc .... portanto, no meu caso, é necessário. Você sugere criar uma imagem de desenvolvimento com um nome diferente do de produção e stag? tipo owner/dev/:, alguma coisa nesse sentido?

.... desculpe estar estendendo a conversa mas esse assunto me interessa muito, estou modelando uma estrutura para que a mesma seja sustentável e possa utilzar um Continuous Integration no futuro.

Para variáveis de ambiente, eu costumo ver como boa prática o que já se é usado nas imagens comuns que utilizamos como base. Veja por exemplo a imagem do MySQL: A documentação dela expõe várias variáveis de ambiente que podemos estar configurando. O valor delas só é atribuído de fato na hora de criar um container.

Isso pode ser no compose ou mesmo direto no ambiente. O Heroku por exemplo disponibiliza um lugar nas configurações do projeto para definir variáveis de ambiente.

Se em DEV, seu ambiente não muda muito, então ter um Dockerfile para o desenvolvedor, não faz muito sentido pra mim, então, você usaria esse Dockerfile só para criar a imagem base que todos os devs poderiam criar instâncias. Se você deixa isso direto na máquina do dev por exemplo, você gera um retrabalho, então o dev em vez de criar uma instância pronta e sair desenvolvendo, ele vai precisar criar um build antes.

(Pelo que entendi, quando você diz ambiente de dev, quer dizer que todos os devs tem uma cópia do Dockerfile). Para mim faz mais sentido ele ter só a imagem pronta, posso estar errado. Então sim, faz sentido a segunda pergunta.

Não tem por que se desculpa, eu que me desculpo por demorar na interação.