Agora você vai entender para que serve Docker e por em prática em um exemplo criando 3 containers, um com banco de dados mysql, outro com API Node que consulta o banco e a terceira que é uma página PHP que consome da API Node e joga para uma página HTML. Olá pessoal, eu sou Ayrton e esse é o Programador a Bordo! Galera, já se inscreva no canal, comente e compartilhe para que possamos criar cada vez mais conteúdo de qualidade aqui no canal!
E vamos lá aprender Docker, agora! Imagine que você tenha uma aplicação que precise de dois sistemas para funcionar, cada um com suas dependências, otimizações e configurações. Uma em PHP, a outra em Node.
A em Node, precisa realizar operações no banco dados MySQL e que seu sistema operacional seja o Windows 10 Agora você precisa que outros desenvolvedores rode sua a aplicação nas máquinas deles, pois você trabalha em uma equipe. Bom, qual o problema aqui? É que todas as dependências e configurações está instalado diretamente na sua máquina.
E para um desenvolvedor rodar na máquina dele, precisa instalar todas elas também. Deixar as configurações na máquina dele a mais fiel da sua possível Porém, pode ser que ele já tenha outra versão do php instalado, ou do mysql, ou do apache e com isso ele tenha bastante dificuldade para rodar sua aplicação, gerando o famoso problema: na minha máquina não funciona Além do que, ao instalar tudo que sua aplicação precisa na sua máquina, você pode entrar em um problema de dependência, pois sua APP necessita da lib xpto na versão x. x enquanto seu banco de dados depende da mesma lib xpto mas na versão y.
z e elas são diferente. Bom. .
. E como é que o docker resolve esses problemas? Primeiro, o que é Docker?
É um software que fornece containers virtuais que empacota a sua aplicação e suas dependências para dentro de um container. A partir desse momento, o container se torna portável para você utilizar em qualquer outro lugar que tenha o docker instalado, seja na máquina de outras pessoas ou em servidores. Ou seja, podemos transferir os containers E como resolve Imagine um mundo utópico onde o sistema operacional não fosse mais um problema, e se você pudesse dizer exatamente como e em quais circunstâncias as suas aplicações devem rodar, independente do sistema operacional que vai estar instalado Imagine que você diga que sua aplicação deve rodar sempre em um Sistema Operacional Debian com configurações e binários XYZ e, independente de onde sua aplicação vai estar, ela vai sempre rodar da mesma forma, ela vai sempre rodar como se estivesse no Debian com bibliotecas e binários XYZ.
Mesmo que esteja no Windows. Com isso sua aplicação sempre funciona da mesma forma em qualquer lugar! Parece surreal, certo?
Mas é isso que o Docker se propôe! Como eu disse, o docker trabalha com o conceito de containers, onde ele consegue isolar a sua aplicação através de um container virtual, como se fosse em um host, que é o sistema operacional hospedeiro, o seu principal sistema. Nesses containers, você diz exatamente tudo que ele vai ter, como as bibliotecas que a linguagem que você está sendo desenvolvendo precisa, o sistema operacional que melhor se adequa, de preferência distribuição linux.
Veja nesta imagem que agora todas as dependências ficam isoladas apenas em seu container, não afetando os outros containers. São processos totalmente isolados. O Node está instalado apenas no container do node, ele não existe no container do MySQL, por exemplo.
Agora sua aplicação vai rodar sempre da mesma forma em qualquer lugar, basta este outro lugar ter o Docker instalado! Todas essas configurações que sua aplicação precisa, você define uma vez, no universo Docker, ela se chama imagem. Com uma imagem Docker, você pode passar ela para qualquer pessoa e executar em diversos ambientes sem precisar configurar mais.
Uma imagem é como um template/modelo, onde você define o sistema operacional, dependências e regras e disponibiliza para uso nos containers. Você executa uma imagem Docker dentro de um container e você pode ter a mesma imagem Docker sendo executada em vários containers, que falam entre si, se precisar. Isso se assemelha muito com máquinas virtuais, tipo virtual box e VMWare.
Tem diferença? Posso usar eles no lugar de Docker? De fato se assemelha, porém o Docker traz algumas vantagens.
Vamos a estrutura de cada um. Aqui na base temos a infraestrutura, que no caso é o hardware. Em cima temos o sistema operacional principal, que pode ser qualquer um, vamos supor que seja um Ubuntu.
Em cima temos o Hypervisor que é o principal componente nessa estrutura, é ele o responsável, nas VMs, disponibilizar recursos de hardware para os sistemas operacionais visitantes, que são as máquinas virtuais. Resumindo: Hypervisor é uma camada de software que fica entre o hardware e as máquinas virtuais, sendo responsável por fornecer recursos, como armazenamento, CPU, memória, rede, etc. , da máquina física para a virtual.
Ele permite que vários sistemas operacionais possam ser executados em um mesmo host, que é o Sistema operacional hospedeiro. Em cima dele, temos as máquinas virtuais, os sistemas operacionais visitantes, que em cima tem seus binários, bibliotecas e finalmente, por último, sua aplicação. Então nesse exemplo, temos 3 aplicações rodando em um host.
Qual o problema aqui? Utilizar VM's se torna custoso devido ao uso do Hypervisor, há muito desperdício de recurso nesse cenário. Todo o sistema operacional é reproduzido nessa camada de cima e ainda dependemos do Hypervisor para conseguir utilizar as VMs.
Já o Docker consegue reaproveitar muito melhor os recursos. Aqui na base também temos a nossa infraestrutura/hardware, em cima o sistema operacional, o host e daqui para cima temos o Docker e seus containers. O Docker não depende de um software como Hypervisor para rodar os containers, ele simplesmente utiliza features do próprio kernel do sistema operacional hospedeiro para gerar os containers.
Com isso o Docker consegue inicializar mais rápido e utilizar menos memória e armazenamento. Para você ter reaproveitamento de Kernel, você precisa que seu sistema operacional hospedeiro seja distribuição linux. Com isso, havendo compartilhamento de recursos Ah.
. Eu tenho Windows ou Mac, não consigo utilizar docker para desenvolver? Consegue!
Neste caso você precisa instalar uma versão do docker desktop para windows e mac, ele se encarrega do Hypervisor(para mac) ou Hyper-V para windows para você utilizar. Humm… Mas se o docker é totalmente baseado em linux, e se minha aplicação for dotnet e eu precisar rodar em uma imagem de windows, não consigo utilizar docker? Consegue sim!
Para utilizar o máximo proveito de compartilhamento de features do kernel, etc. como tem no linux, você precisa que a versão do sistema operacional hospedeiro seja a mesma do container, ou seja, ambos devem ter o windows server na mesma versão. Caso não, Hiper-V será utilizado --- Eu já comentei sobre imagens Docker, muitas vezes não precisamos criar nossa imagem ou pelo menos não do zero.
Existe um repositório oficial do próprio Docker com diversas imagens prontas para uso. Lá tem imagens oficiais e da comunidade, que podemos utilizar diretamente pois já vem toda pré-configurada e pronta para rodar nossas aplicações. Então aqui temos uma imagem oficial do Node, pronta para uso.
Temos do PHP, temos do MySQL que vamos utilizar agora para criar essa aplicação: Eu criei um banco de dados MySQL em um container com uma tabela chamada products, onde cadastro produtos informando seu nome e preço. Também criei um outro container com uma aplicação node, onde ele pega todos os produtos desse banco de dados e disponibiliza como uma API, acessando o endpoint localhost 9001 products Depois, criei uma aplicação PHP em outro container que vai acessar esse endpoint, consumir os produtos e disponibilizar em uma página HTML, dentro de uma tabela. Beleza?
Então. vamos lá…. Instale o Docker, vou deixar os links na descrição da instalação para windows, mac e linux.
Abra seu editor de código na pasta que você vai fazer todo esse projeto, cria uma pasta chamada api e dentro dela, uma chamada db, de database. Aqui, vamos criar um arquivo chamado Dockerfile. É neste arquivo que a gente define a nossa imagem, o sistema operacional, as dependências, os arquivos que precisamos jogar para o container, os comandos a serem executados, etc.
Você pode ver mais detalhadamente sobre Dockerfile na próprio documentação do Docker, que explica cada comando. Como eu mostrei antes no Docker HUB, já existe uma imagem oficial disponibilizada para trabalhar com MySQL Olhando aqui no Docker HUB, vemos que o nome da imagem é mysql. Para colocarmos na nossa imagem docker, basta utilizar o comando FROM seguido do nome da imagem: FROM mysql Para utilizar esta imagem, podemos passar algumas variáveis de ambiente que servem para configurar o banco, uma delas é a senha Para utilizar no Dockerfile, utilizamos o comando ENV seguido do nome da variável, seguido do seu valor Para nossos objetivos, isso basta no nosso Dockerfile.
Já temos o nosso arquivo modelo para gerar nossa imagem Para construir a imagem, vamos utilizar o comando docker build em nosso terminal. Navegue até a pasta raíz do projeto e execute: docker build t mysql mage f api db Dockerfile ponto Está baixando a imagem aqui. Terminou A flag t significa tag e que estamos dando um nome para a nossa imagem, vai nos ajudar a identificar a imagem mais facilmente.
Este nome é totalmente escolhido por você, defina um nome que faça sentido. A flag f especifica o arquivo Dockerfile para gerar a imagem O ponto no final, significa que o contexto para gerar a imagem vai ser da pasta que estou executando o comando no momento, ou seja, como se a imagem estivesse sendo construída na pasta atual. Agora, para ver as imagens disponíveis para uso, execute o comando: docker image ls Agora vamos criar nosso container que vai utilizar esta imagem que acabamos de criar!
Execute o comando docker run com algumas opções A flag d significa detach e que vamos executar em background, ou seja, o nosso terminal não vai ficar preso na exibição de informações que o container disponibiliza. Se não utilizarmos essa flag -d, não vamos mais conseguir utilizar esta aba do terminal enquanto o container estiver de pé. A flag rm significa que se o container já existir, ele vai ser removido para que um novo possa ser criado.
A flag name seguido do mysql-container informa o nome do container, vai nos ajudar bastante como um identificador. Este nome é definido por você, escolha com sabedoria. mysql image é o nome da imagem que vamos utilizar no container, que criamos antes.
Ok. Dê enter Terminando, execute: docker ps Com esse comando conseguimos ver os containers que estão de pé através do seu status Agora temos um container MySQL. Vamos criar um banco de dados, uma tabela e inserir alguns valores, em seguida vamos acessar o mysql via linha de comando e visualizar essa tabela.
Crie um arquivo chamado script. sql na pasta db e vamos brincar um pouco de SQL. Criar um banco caso ele não exista Acessar esse banco Criar a tabela products com os campos id, name e price E inserir dois produtos Salve, volte para o terminal e execute o docker exec: docker exec significa que vamos executar comandos dentro de um container que está rodando.
A flag i significa que estamos executando um comando no modo interativo. Sempre que precisarmos rodar um processo interativo, como um shell, precisamos utilizar esta flag. Ou seja, como aqui precisamos que o mysql leia todo o arquivo script.
sql e faça o restore, a flag i permite que o processo não vai ser finalizado até que seja concluído. mysql-container logo após a flag i, é o nome do container que vamos utilizar no comando. Depois do nome do container, temos exatamente o comando que queremos executar, que é executar os comandos do script.
sql dentro do nosso MySQL. Tecle enter, após isso, ele terá criado o banco de dados, a tabela e seus valores. Agora vamos acessar o nosso container para ver essa tabela.
Execute novamente o docker exec: Agora utilizamos as flags i e t A flag t significa que vamos utilizar o tty, que muito resumidamente, significa terminal Posteriormente temos o nome do container seguido do comando que queremos executar. bin bash significa que vamos utilizar o bash, que é uma linguagem de comandos Tecle enter, agora temos acesso ao "terminal" do nosso container. acesse o banco selecione a tabela Ótimo, está tudo aqui!
Vamos sair Saia do container No container, tudo que você faz dentro dele, é perdido quanto o container é parado, excluído, etc. Muitas vezes isso não é o desejado. Por exemplo, se eu parar o container agora, docker stop mysql container E executar ele novamente Acessar o container Acessar o banco e tentar ver meu banco Vocês vão ver que ele sumiu!
Imagine que a gente adicionou vários dados fakes para testar e agora está tudo perdido. Bom, é claro que o Docker resolve isso, uma das formas de trabalhar é com volumes Você consegue compartilhar uma pasta do seu host com seu container, então tudo que você faz em um, reflete em outro. Ou seja, as coisas que você faz no container não é perdido.
Para isso, pare seu container E agora vamos executar o docker run só que com uma flag a mais, chamada volume A flag v que significa volume informa a pasta do seu host que está compartilhado com o container, o caminho de cada pasta é separado por dois pontos. pasta host dois pontos pasta container O pwd é um comando que retorna o diretório atual. A pasta var lib mysql é a pasta de onde fica o mysql e toda a estrutura do seu banco.
Execute o comando e em seguida faça o restore do seu script sql novamente Com isso, você vai ver aqui que dentro de api db data tem vários arquivos do seu banco. Talvez este não seja o melhor lugar para salvar a estrutura do banco do seu container, mas para fins didáticos vamos mantê-lo aqui. Agora você pode parar seu o container e executá-lo novamente e vai ver que o banco se mantém.
Eu vou continuar daqui mesmo. Nosso banco está pronto, vamos criar agora nosso container Node! Certifique-se de ter o Node instalado na sua máquina, de preferência o Node na mesma versão que vamos utilizar na imagem, que nesse caso vai ser o Node 10.
Dentro da pasta api, vamos instalar as dependências do Node na nossa máquina. Execute npm init Responda as perguntas pronto Vamos instalar o nodemon para manter nossa aplicação Node rodando e fazer reload sempre que atualizarmos os arquivos javascripts Vamos instalar também o express pra fazer a rota que vai retornar os produtos e o driver do mysql, que vai nos facilitar fazer o acesso ao banco npm install save express mysql Aqui no package json, crie o comando start executando o nodemon: Agora vamos criar esta pasta src e o arquivo index. js importe o express e o mysql instancie o express e diga a porta que a aplicação vai estar ouvindo e respondendo Crie uma conexão com o banco utilizando o método create connection Aqui você vai informar o host, que vai ser o IP do container do mysql.
Ambos precisam estar na mesma rede. O docker por padrão cria seus containers em uma mesma rede, porém você pode criar diferentes redes no docker, ele permite isso. Como os containers estão na mesma rede, basta sabermos o IP que o container do MySQL utiliza Para isso, vá no terminal e execute docker inspect mysql container Procure por IPAddress e pegue o endereço IP e coloque no host O usuário do nosso banco é root Nome do banco e senha é programadorabordo Estabeleça uma conexão Agora vamos criar a rota no express pra responder quando digitar o endereço /products Aqui dentro, para fins didáticos, vou fazer o select de produtos do banco de dados e cuspir o resultado.
Então aqui eu faço o select de todos os produtos Se ocorrer algum erro, eu aborto Se der tudo certo, eu passo o resultado com o res send Beleza, nosso JS está pronto, agora vamos criar a imagem e o container para nossa aplicação. Crie um Dockerfile Vamos utilizar a imagem que está aqui no docker hub, do node, na versão 10 slim FROM node: 10 slim Nossos arquivos javascript vai ficar na pasta do container /home/node/app Para isso, utilize o comando WORKDIR no Dockerfile E quando o container* estiver de pé, a gente precisa executar npm start E informar ao Dockerfile, utilize o comando CMD CMD npm start Já que especificamos que o WORKDIR é a pasta /home/node/app, então o comando npm start vai ser executado exatamente nessa pasta. Vamos construir esta imagem utilizando o comando docker build que a gente já aprendeu docker build t node-image f api Dockerfile .
Execute este comando na pasta raíz do projeto Ele vai baixar a imagem, aguarde. Pronto! Imagem construída, você pode olhar ela aqui com docker image ls Agora vamos rodar esta imagem dentro de um container Nesse comando, a única flag que ainda não falamos foi a flag p.
Como vamos acessar essa rota fora do container, precisamos dizer que a porta que estamos utilizando dentro do container, vai estar exposta para acesso na porta do nosso host Ou seja, aqui fazemos um mapeamento, que na porta 9001 do nosso host vai acessar a porta 9001 do container Veja o container de pé: Agora vamos acessar, abra seu navegador e digite: localhost 9001 products e voilà Você vai ver este resultado! Agora, pare o container docker stop node-container Vamos para uma dica! Aqui no host, colocamos exatamente o IP do container que queremos acessar.
Porém o docker disponibiliza uma feature bem legal, que ele cria um apelido para o container, e aqui não precisamos colocar o endereço ip, basta utilizarmos o nome do container que queremos acessar Rode o container novamente com docker run, observe que agora estamos passando a flag link Aqui eu digo para o docker, que este container tem um link com o container mysql-container. Agora podemos trocar o host, o ip pelo nome do container e vai funcionar perfeitamente! Agora vamos fazer a aplicação PHP que vai consumir dessa API!
Crie uma pasta na raíz chamada website Dentro, crie um arquivo index. php Adicione uma markup básica de html No corpo do html, vamos criar as funções PHP que vai bater na roda da API Node e pegar o resultado Nessa linha, aqui fazemos o request, passando o apelido junto com a porta Transformamos em json e armazenamos na variável products Crie uma tabela com duas colunas, Produto e preço No corpo da tabela, vamos iterar sobre os produtos para listar eles na página Pronto, agora vamos containizar ele e rodar Crie um Dockerfile Vamos utilizar a imagem oficial do PHP na versão 7. 2 com apache O diretório padrão que seu PHP vai ser executado, deve ficar na pasta /var/www/html Construa a imagem com docker build docker build -t php-image -f website/Dockerfile .
Rode o container com esta imagem: Aqui também estamos utilizando o modo detach, passando o volume que são os arquivos da pasta website para dentro da pasta /var/www/html do container O PHP no container vai rodar na porta 80 mas vamos externalizar ela para acessar através da porta 8888 Estamos fazendo um link com o container node-container para utilizar este "apelido" lá no request do PHP No fim, nomeamos o container e especificamos a imagem a ser utilizada Acesse localhost 8888 e veja o resultado! ! Vamos finalizar só deixando esta tabela mais bonitinha com o bootstrap!
Acesse o site, baixe a versão compilada e descompacte dentro da pasta website/vendor Renomeie apenas para bootstrap No index. php, importe o css bootstrap min E agora, só estruturar para ficar melhor visualmente utilizando os recursos do bootstrap Crie uma classe container, adicione a classe table na tabela e pronto! !
Olha que bonito! Vou acessar meu container do mysql e inserir um produto na mão para vermos refletir na API e no site. Acessando o container Acessando banco Inserindo mais um valor Veja que refletiu tanto na aplicação PHP, quanto na API!
Bom… Era isso, galera! Curtiram? Deu para entender para que serve Docker e um cheirinho de como utilizar?
Espero que sim, preparei esta aula com muito cuidado para que todos entendam. A próxima aula vai ser sobre docker compose e você vai perceber a facilidade que esta ferramenta traz para gente na hora de levantar e gerenciar os containers, vamos utilizar este mesmo projeto, só que com docker-compose! É isso, se gostaram, já se inscreva no canal caso não seja inscrito, ative o sino para receber as notificações e o mais importante galera, compartilhem este vídeo!
Você vai me ajudar demais junto com as pessoas que querem aprender Docker! ! Um forte abraço e até a próxima!