-
Um dos passos mais importantes quando
nós falamos da utilização de Docker
-
é justamente aprender a criar
o nosso próprio Docker,
-
ou pelo menos a nossa
própria imagem.
-
Para isso, nós vamos ter que utilizar
algumas ferramentas.
-
A primeira e provavelmente mais importante
nesse processo vai ser o Dockerfile.
-
Ele é basicamente um arquivo que vai permitir
que eu passe instruções para o Docker
-
de como ele deve
construir aquela imagem.
-
Antes de mais nada, eu vou precisar
pelo menos de algum código
-
para que eu consiga colocar
em desenvolvimento.
-
Para isso, eu peguei um códigozinho bem
simples de "hello, world" baseado em Node,
-
é basicamente uma página que tem
um campinho de preenchimento de busca
-
e um botãozinho, mas essa função
não tem nada programado,
-
é realmente só para nós
termos um código para utilizar.
-
Nesse caso, nós vamos
utilizar um código em Node
-
e, justamente por isso, eu preciso utilizar,
como base para a minha imagem,
-
uma imagem que já tenha um Node
pronto para eu poder utilizar.
-
Caso nós não achemos
uma imagem dessa forma,
-
nós podemos passar comandos
dentro de um container
-
para que ele faça todo o processo
de instalação daquele software
-
e disponibilize todo aquele
ambiente montado para nós.
-
Aqui dentro da minha tela, eu vou ter,
então, uma pasta chamada "app",
-
que eu criei dentro do meu desktop,
e nela eu vou ter alguns arquivos.
-
O "yarn.lock", o "package",
a pasta "src" e a pasta "spec"
-
são justamente conteúdos que eu
tenho dessa minha aplicação.
-
Se eu abro, por exemplo, aqui,
o "src", eu vou ter um "index.js",
-
que vai ser, justamente, o arquivo
inicial da minha aplicação.
-
Aqui nessa pasta, eu ainda tenho
o arquivo chamado Dockerfile.
-
Esse é o arquivo que vai
trazer todas as instruções
-
que o Docker precisa
para construir a nossa imagem.
-
Existem algumas características
muito importantes
-
que nós temos
que nos atentar nele,
-
a primeira delas é que esse
arquivo não tem extensão,
-
a segunda é que ele sempre
vai começar com D maiúsculo
-
e Dockerfile vai estar
escrito tudo junto.
-
Eu preciso justamente prestar
atenção em todos esses padrões
-
para que eu não impeça
o Docker de achar o arquivo
-
e, assim, começar o processo
de build da imagem.
-
Agora, como eu valido isso aqui
dentro dos meus arquivos?
-
Basta eu vir na aba de visualização
do Explorer no Windows
-
e marcar a opção "file name extensions"
ou mostrar extensões de arquivo.
-
Note que agora todos os meus
arquivos ganharam uma extensão,
-
menos o dockerfile.
-
Pode ser que, quando você criou o arquivo
utilizando, por exemplo, o bloco de notas,
-
ele tivesse mostrado
uma opção como txt.
-
Caso ele tenha aparecido como txt
no final, basta apertar a tecla F2
-
e renomear o arquivo, excluindo
o ".txt" e deixando apenas "dockerfile".
-
O Windows vai pedir que você confirme
que aquele arquivo não vai ter uma extensão,
-
basta confirmar e seguir
para as próximas etapas.
-
Quando nós abrimos o Dockerfile
dentro de um bloco de notas,
-
nós vamos ter uma estrutura
até bem simples.
-
A primeira coisa que nós vamos
ver é justamente um comentário
-
definindo qual tipo de sintaxe nós estamos
utilizando para construção desse arquivo.
-
Nesse caso, uma sintaxe de versão 1.
-
As linhas de comando que definem a sintaxe
estão lá na documentação do Docker.
-
Por hora, você pode simplesmente copiar
essa linha para todos os seus arquivos
-
e tudo vai correr sem
maiores problemas.
-
Agora, caso você se torne
um usuário avançado de Docker,
-
algumas funções só vão estar disponíveis
em versões específicas do Dockerfile,
-
então você vai ter que ficar atento
a qual tipo de Dockerfile utilizar
-
para poder criar exatamente
o container da forma que você precisa.
-
Logo em seguida, eu tenho
um comando chamado "FROM".
-
Esse comando serve para eu especificar
qual imagem de base que eu vou utilizar.
-
Nesse caso, uma imagem chamada
"node" na versão "12-alpine".
-
É justamente aqui, por exemplo, que caso eu
queira criar um container totalmente do zero
-
utilizando só um sistema
operacional de base,
-
eu vou conseguir especificar que eu
quero esse sistema operacional.
-
Se eu quisesse, por exemplo,
criar um servidor Apache do zero,
-
eu poderia fazer um FROM Ubuntu
e, nos comandos que se seguem,
-
fazer todo o passo a passo
de instalação do Apache.
-
Nesse caso, nós já estamos reaproveitando
parte da estrutura do Node que já está pronta
-
e, aí, eu só preciso rodar
alguns poucos comandos
-
e copiar os meus arquivos
para dentro do container.
-
Nosso próximo passo, então,
é rodar um "apk add"
-
para garantir que eu tenho
um python2, o compilador C
-
e o make dentro
da minha máquina.
-
O nosso próximo passo, então, vai
ser criar um diretório de trabalho,
-
nesse caso, chamado "app".
-
Esse diretório de trabalho vai
basicamente informar para o container
-
qual pasta ele deve utilizar
para poder trabalhar.
-
Note que todo o nosso conteúdo do arquivo
está dentro de uma pasta chamada "app",
-
dessa forma, eu vou conseguir
navegar para dentro dessa pasta,
-
utilizar ela como pasta padrão
-
e, a partir de então, começar
a executar os demais comandos.
-
O comando "COPY" serve justamente para eu
copiar arquivos para dentro do container.
-
Ele vai copiar todos os arquivos
da pasta que eu me encontro,
-
por isso o ponto, para a pasta que eu
estarei utilizando dentro do container,
-
por isso, eu vou utilizar
"." novamente.
-
E aqui vai vir um ponto
bem interessante:
-
a cópia do arquivo não é
exatamente uma boa prática,
-
como nós vimos, se nós não soubermos utilizar
o armazenamento de arquivos de forma correta,
-
isso vai atrapalhar o bom
funcionamento de um container.
-
A questão, nesse caso, é que, como eu
estou criando um container novo,
-
eu preciso passar todos os códigos
que vão servir de base para ele,
-
então eu posso copiar esses arquivos
sem a menor dor de cabeça,
-
já que eles vão passar
a ser parte fundamental
-
de todo o container
que eu estou criando.
-
O passo seguinte, então,
-
é garantir que esse meu sistema esteja
utilizando um ambiente de produção.
-
Para isso, eu posso
executar um "yarn install".
-
Esse comando é um comando
que pertence ao ambiente Node
-
e serve basicamente para instalar
todos os pacotes necessários
-
e preparar o ambiente para a execução
daquela minha aplicação.
-
Em seguida, eu vou
utilizar o "CMD",
-
que é basicamente uma forma de criar
linhas de comando dentro do container.
-
Nesse caso, eu estou chamando
o comando Node e informando para ele
-
que o arquivo de origem da minha aplicação
está dentro da pasta "src/index".
-
E esse é exatamente o caminho
que nós checamos agora há pouco
-
de onde estava o index
da minha aplicação.
-
Então, a partir do momento que eu copiei
esses dados para dentro do container,
-
eu, agora, mostrei para o Node
como executá-lo.
-
Por fim, eu estou fazendo
um "EXPOSE" da porta 3000.
-
Esse comando serve
justamente para eu informar
-
que eu vou ter que acessar
uma porta desse container,
-
dessa forma, na hora que eu for criar
o container para colocá-lo em execução,
-
o Docker vai saber que eu posso
ter uma conexão de rede ali
-
e vai permitir a criação
dessa interação.
-
Outro detalhe muito importante é que eu
tenho duas formas de executar comandos.
-
A primeira é a partir
do comando "run".
-
O run vai simplesmente executar aquela
linha de comando dentro do meu container
-
na hora que eu estiver fazendo
toda a parte de construção dele.
-
Enquanto isso, CMD vão ser
comandos que vão ser executados
-
posteriormente à criação
do meu container.
-
Dessa forma, quando eu crio lá o CMD chamando
um comando Node e passando o index,
-
toda vez que esse container for colocado
em execução, esse comando vai ser chamado.
-
Agora que todo esse
processo está finalizado,
-
eu posso utilizar esses arquivos
para construir o meu container.
-
Utilizando, então, o prompt de comando, eu
vou poder recorrer a uma função chamada
-
"docker build".
-
Esse comando é
um comando bem simples
-
e não tem muita coisa que nós
temos que configurar nele.
-
Nesse caso, por exemplo, nós
só vamos nomear a imagem
-
e, em seguida, informar o endereço,
para o Dockerfile, que vai ser utilizado.
-
Para isso, eu vou informar o "-t"
seguido do nome da imagem.
-
Nesse caso, eu vou chamar ela de "ola"
e, em seguida, eu vou informar um ponto.
-
A função desse ponto é informar que eu já
estou na pasta onde eu tenho o Dockerfile,
-
caso eu não esteja nessa pasta,
ao invés de informar o ponto,
-
eu vou ter que informar todo
o endereçamento de pasta
-
e esse endereçamento vai variar
entre sistemas operacionais.
-
A forma mais fácil, então, é utilizar
os comandos de navegação de terminal,
-
como CD, para poder
navegar pelos diretórios
-
e, chegando no diretório
que tem o Dockerfile,
-
simplesmente executar o "docker build"
com o ponto no final.
-
Executando, então, o processo de build,
várias coisas vão ser executadas.
-
A primeira delas é todo
o download de imagens,
-
seguido da construção das aplicações,
e todo o teste de funcionamento
-
para ver se o comando inicial
vai ser executado com sucesso.
-
Caso você possua alguma falha nesse processo,
você pode recorrer ao "docker logs".
-
Esse é um comando que nos permite
checar logs no ambiente Docker.
-
Inclusive é legal que você pode utilizar
ele para checar logs individualmente
-
de cada container.
-
Com o processo de build concluído,
-
o Docker sempre vai perguntar se você não
quer fazer um scan de vulnerabilidades.
-
Nesse caso, não
vai ser preciso.
-
A única coisa que nos falta agora é colocar,
justamente, esse container em execução.
-
Para isso, nós vamos recorrer
ao comando "docker run",
-
só que, dessa vez, eu vou ter que passar
alguns parâmetros de execução para ele.
-
O primeiro parâmetro vai
ser justamente para garantir
-
que essa imagem vai ficar
em execução o tempo todo.
-
Para isso, vou utilizar o "-d".
-
Enquanto o segundo parâmetro, "-p", vai ser
para informar o apontamento de portas de rede,
-
dessa forma, todo o conteúdo da minha
aplicação vai ficar disponível para acesso.
-
Para executar, então, o container
que nós acabamos de criar,
-
eu vou fazer um "docker run",
-
"-d",
-
"-p", para informar a porta,
-
e, nesse caso, eu expus a porta 3000,
então eu vou utilizar "3000 : 3000".
-
A razão de eu ter que repetir o 3000 duas vezes
é porque eu estou falando de duas portas.
-
A primeira é a porta na minha máquina base
e a segunda é a porta do meu container,
-
Se eu especifico, por exemplo, a primeira
porta, que é a da máquina base, como 80,
-
ela vai apontar um acesso realizado
na porta 80 do meu servidor base
-
para a porta 3000
do meu container.
-
Isso é algo que nós temos
que prestar bastante atenção,
-
às vezes, quando nós
vamos criar uma aplicação,
-
nós temos vários containers
que têm exposta a porta 80
-
e eu posso apontar diversas portas
para dentro desses containers,
-
utilizando numerações
diferentes no meu host base.
-
O próximo passo, então, é informar o nome
da minha imagem, nesse caso, "ola".
-
Colocando a imagem em execução, eu
vou receber o código de validação dela
-
e, se eu executar um "docker ps",
-
note que essa minha imagem
já se encontra em execução
-
e me informando que a porta 3000 está
apontando para a porta 3000 do container.
-
O último passo, então,
é abrir o navegador web
-
e acessar, justamente, a nossa
máquina na porta 3000.
-
O IP que eu informei aqui 127.0.0.1
é o que se chama de local host,
-
ele representa a própria
máquina na rede.
-
Outra forma que você teria era escrever
por extenso "local host: 3000".
-
Qualquer uma das duas formas já faria com que
toda a interface funcionasse normalmente.
-
No nosso caso, após
acessar a aplicação,
-
todo o código que nós criamos e compilamos
já está aqui disponível para uso
-
e eu consigo, por exemplo, ir adicionando
itens dentro dessa minha aplicação.
-
Esse é um exemplo
de uma aplicação bem simples,
-
só para nós entendermos como é que eu
começo a construir todo esse ambiente.
-
A partir de agora, você pode
utilizar esses conhecimentos
-
para começar a containerizar
as suas próprias aplicações
-
e, com isso, entender um pouco mais
como todo esse ecossistema funciona.