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 que 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 no 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 ".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.
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 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 permite a gente
checar logo o ambiente Docker.
Inclusive é legal que você pode utilizar
ele para checar logs
individualmente de cada contêiner
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 a gente vai 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 ao menos o D,
enquanto o segundo parâmetro menos 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 a gente acabou de criar,
eu vou fazer um Docker run
em menos de
menos P para informar a porta
e nesse caso eu expus a porta 3000.
Então vou utilizar 3002 pontos, 3000.
A razão de eu ter que repetir O31000
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,
que específico 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 a gente tem que prestar
bastante atenção.
Às vezes,
quando a gente vai criar uma aplicação,
a gente tem vários containers
que tem expostas a porta 80
e eu posso apontar diversas portas
para dentro desses containers,
utilizando numerações diferentes
no meu rosto base.
O próximo passo então é informar o nome da
minha imagem, nesse caso o LA
colocando a imagem em execução
eu vou receber o código de validação dela
e se eu executar um Docker PRS?
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 contêiner.
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
ponto zero
ponto um é o que se chama de local Rust.
Ele representa a própria máquina na rede.
Outra forma que você teria era escrever
por extenso local rows de 2,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 a gente criou e compilou
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ó pra gente entender como é que eu começo
a construir todo esse ambiente.
A partir de agora,
você pode utilizar esses conhecimentos
para começar a renderizar
as suas próprias aplicações
e com isso entender um pouco mais
de como todo esse ecossistema funciona.