WEBVTT 00:00:08.952 --> 00:00:13.039 Um dos passos mais importantes quando nós falamos da utilização de Docker 00:00:13.039 --> 00:00:16.730 é justamente aprender a criar o nosso próprio Docker, 00:00:16.730 --> 00:00:19.720 ou pelo menos a nossa própria imagem. 00:00:20.280 --> 00:00:23.406 Para isso, nós vamos ter que utilizar algumas ferramentas. 00:00:23.406 --> 00:00:29.686 A primeira e provavelmente mais importante nesse processo vai ser o Dockerfile. 00:00:29.686 --> 00:00:34.925 Ele é basicamente um arquivo que vai permitir que eu passe instruções para o Docker 00:00:34.925 --> 00:00:37.656 de como ele deve construir aquela imagem. 00:00:37.656 --> 00:00:41.498 Antes de mais nada, eu vou precisar pelo menos de algum código 00:00:41.498 --> 00:00:45.238 para que eu consiga colocar em desenvolvimento. 00:00:45.238 --> 00:00:51.153 Para isso, eu peguei um códigozinho bem simples de "hello, world" baseado em Node, 00:00:51.153 --> 00:00:55.238 é basicamente uma página que tem um campinho de preenchimento de busca 00:00:55.238 --> 00:00:59.239 e um botãozinho, mas essa função não tem nada programado, 00:00:59.239 --> 00:01:02.540 é realmente só para nós termos um código para utilizar. 00:01:02.540 --> 00:01:06.359 Nesse caso, nós vamos utilizar um código em Node 00:01:06.359 --> 00:01:11.328 e, justamente por isso, eu preciso utilizar, como base para a minha imagem, 00:01:11.328 --> 00:01:15.383 uma imagem que já tenha um Node pronto para eu poder utilizar. 00:01:15.383 --> 00:01:18.114 Caso nós não achemos uma imagem dessa forma, 00:01:18.114 --> 00:01:21.732 nós podemos passar comandos dentro de um container 00:01:21.732 --> 00:01:25.805 para que ele faça todo o processo de instalação daquele software 00:01:25.805 --> 00:01:29.387 e disponibilize todo aquele ambiente montado para nós. 00:01:29.387 --> 00:01:34.137 Aqui dentro da minha tela, eu vou ter, então, uma pasta chamada "app", 00:01:34.137 --> 00:01:39.634 que eu criei dentro do meu desktop, e nela eu vou ter alguns arquivos. 00:01:40.640 --> 00:01:46.613 O "yarn.lock", o "package", a pasta "src" e a pasta "spec" 00:01:46.613 --> 00:01:51.054 são justamente conteúdos que eu tenho dessa minha aplicação. 00:01:51.054 --> 00:01:56.269 Se eu abro, por exemplo, aqui, o "src", eu vou ter um "index.js", 00:01:56.269 --> 00:02:00.836 que vai ser, justamente, o arquivo inicial da minha aplicação. 00:02:02.272 --> 00:02:06.141 Aqui nessa pasta, eu ainda tenho o arquivo chamado Dockerfile. 00:02:06.141 --> 00:02:09.172 Esse é o arquivo que vai trazer todas as instruções 00:02:09.172 --> 00:02:12.757 que o Docker precisa para construir a nossa imagem. 00:02:13.316 --> 00:02:15.892 Existem algumas características muito importantes 00:02:15.892 --> 00:02:17.921 que nós temos que nos atentar nele, 00:02:17.921 --> 00:02:23.243 a primeira delas é que esse arquivo não tem extensão, 00:02:24.144 --> 00:02:27.990 a segunda é que ele sempre vai começar com D maiúsculo 00:02:27.990 --> 00:02:30.769 e Dockerfile vai estar escrito tudo junto. 00:02:30.769 --> 00:02:34.461 Eu preciso justamente prestar atenção em todos esses padrões 00:02:34.461 --> 00:02:37.423 para que eu não impeça o Docker de achar o arquivo 00:02:37.423 --> 00:02:40.125 e, assim, começar o processo de build da imagem. 00:02:40.125 --> 00:02:45.251 Agora, como eu valido isso aqui dentro dos meus arquivos? 00:02:45.251 --> 00:02:49.549 Basta eu vir na aba de visualização do Explorer no Windows 00:02:49.549 --> 00:02:56.029 e marcar a opção "file name extensions" ou mostrar extensões de arquivo. 00:02:56.029 --> 00:03:00.023 Note que agora todos os meus arquivos ganharam uma extensão, 00:03:00.023 --> 00:03:02.168 menos o dockerfile. 00:03:02.168 --> 00:03:07.812 Pode ser que, quando você criou o arquivo utilizando, por exemplo, o bloco de notas, 00:03:07.812 --> 00:03:11.942 ele tivesse mostrado uma opção como txt. 00:03:11.942 --> 00:03:16.526 Caso ele tenha aparecido como txt no final, basta apertar a tecla F2 00:03:16.526 --> 00:03:22.692 e renomear o arquivo, excluindo o ".txt" e deixando apenas "dockerfile". 00:03:22.692 --> 00:03:27.424 O Windows vai pedir que você confirme que aquele arquivo não vai ter uma extensão, 00:03:27.424 --> 00:03:30.833 basta confirmar e seguir para as próximas etapas. 00:03:30.833 --> 00:03:34.180 Quando nós abrimos o Dockerfile dentro de um bloco de notas, 00:03:34.180 --> 00:03:36.990 nós vamos ter uma estrutura até bem simples. 00:03:36.990 --> 00:03:40.977 A primeira coisa que nós vamos ver é justamente um comentário 00:03:40.977 --> 00:03:46.419 definindo qual tipo de sintaxe nós estamos utilizando para construção desse arquivo. 00:03:46.419 --> 00:03:49.364 Nesse caso, uma sintaxe de versão 1. 00:03:49.364 --> 00:03:54.531 As linhas de comando que definem a sintaxe estão lá na documentação do Docker. 00:03:54.531 --> 00:03:59.303 Por hora, você pode simplesmente copiar essa linha para todos os seus arquivos 00:03:59.303 --> 00:04:02.417 e tudo vai correr sem maiores problemas. 00:04:02.417 --> 00:04:05.959 Agora, caso você se torne um usuário avançado de Docker, 00:04:05.959 --> 00:04:12.052 algumas funções só vão estar disponíveis em versões específicas do Dockerfile, 00:04:12.052 --> 00:04:16.880 então você vai ter que ficar atento a qual tipo de Dockerfile utilizar 00:04:16.880 --> 00:04:21.237 para poder criar exatamente o container da forma que você precisa. 00:04:21.237 --> 00:04:25.331 Logo em seguida, eu tenho um comando chamado "FROM". 00:04:25.331 --> 00:04:31.171 Esse comando serve para eu especificar qual imagem de base que eu vou utilizar. 00:04:31.171 --> 00:04:37.259 Nesse caso, uma imagem chamada "node" na versão "12-alpine". 00:04:37.259 --> 00:04:42.627 É justamente aqui, por exemplo, que caso eu queira criar um container totalmente do zero 00:04:42.627 --> 00:04:45.562 utilizando só um sistema operacional de base, 00:04:45.562 --> 00:04:49.519 eu vou conseguir especificar que eu quero esse sistema operacional. 00:04:49.519 --> 00:04:52.992 Se eu quisesse, por exemplo, criar um servidor Apache do zero, 00:04:52.992 --> 00:04:58.466 eu poderia fazer um FROM Ubuntu e, nos comandos que se seguem, 00:04:58.466 --> 00:05:02.198 fazer todo o passo a passo de instalação do Apache. 00:05:02.198 --> 00:05:08.140 Nesse caso, nós já estamos reaproveitando parte da estrutura do Node que já está pronta 00:05:08.140 --> 00:05:11.301 e, aí, eu só preciso rodar alguns poucos comandos 00:05:11.301 --> 00:05:14.495 e copiar os meus arquivos para dentro do container. 00:05:14.495 --> 00:05:19.203 Nosso próximo passo, então, é rodar um "apk add" 00:05:19.203 --> 00:05:24.515 para garantir que eu tenho um python2, o compilador C 00:05:24.515 --> 00:05:27.246 e o make dentro da minha máquina. 00:05:27.777 --> 00:05:33.423 O nosso próximo passo, então, vai ser criar um diretório de trabalho, 00:05:33.423 --> 00:05:35.747 nesse caso, chamado "app". 00:05:35.747 --> 00:05:40.236 Esse diretório de trabalho vai basicamente informar para o container 00:05:40.236 --> 00:05:43.219 qual pasta ele deve utilizar para poder trabalhar. 00:05:43.219 --> 00:05:49.232 Note que todo o nosso conteúdo do arquivo está dentro de uma pasta chamada "app", 00:05:49.232 --> 00:05:52.665 dessa forma, eu vou conseguir navegar para dentro dessa pasta, 00:05:52.665 --> 00:05:55.179 utilizar ela como pasta padrão 00:05:55.179 --> 00:05:58.766 e, a partir de então, começar a executar os demais comandos. 00:05:58.766 --> 00:06:04.387 O comando "COPY" serve justamente para eu copiar arquivos para dentro do container. 00:06:04.387 --> 00:06:08.988 Ele vai copiar todos os arquivos da pasta que eu me encontro, 00:06:08.988 --> 00:06:14.627 por isso o ponto, para a pasta que eu estarei utilizando dentro do container, 00:06:14.627 --> 00:06:17.561 por isso, eu vou utilizar "." novamente. 00:06:17.561 --> 00:06:19.812 E aqui vai vir um ponto bem interessante: 00:06:19.812 --> 00:06:23.466 a cópia do arquivo não é exatamente uma boa prática, 00:06:23.466 --> 00:06:29.468 como nós vimos, se nós não soubermos utilizar o armazenamento de arquivos de forma correta, 00:06:29.468 --> 00:06:32.826 isso vai atrapalhar o bom funcionamento de um container. 00:06:32.826 --> 00:06:37.397 A questão, nesse caso, é que, como eu estou criando um container novo, 00:06:37.397 --> 00:06:42.192 eu preciso passar todos os códigos que vão servir de base para ele, 00:06:42.192 --> 00:06:47.010 então eu posso copiar esses arquivos sem a menor dor de cabeça, 00:06:47.010 --> 00:06:50.476 já que eles vão passar a ser parte fundamental 00:06:50.476 --> 00:06:52.590 de todo o container que eu estou criando. 00:06:52.590 --> 00:06:54.267 O passo seguinte, então, 00:06:54.267 --> 00:07:00.560 é garantir que esse meu sistema esteja utilizando um ambiente de produção. 00:07:00.560 --> 00:07:03.298 Para isso, eu posso executar um "yarn install". 00:07:03.298 --> 00:07:06.506 Esse comando é um comando que pertence ao ambiente Node 00:07:06.506 --> 00:07:10.250 e serve basicamente para instalar todos os pacotes necessários 00:07:10.250 --> 00:07:13.622 e preparar o ambiente para a execução daquela minha aplicação. 00:07:13.622 --> 00:07:17.363 Em seguida, eu vou utilizar o "CMD", 00:07:17.363 --> 00:07:22.822 que é basicamente uma forma de criar linhas de comando dentro do container. 00:07:22.822 --> 00:07:27.267 Nesse caso, eu estou chamando o comando Node e informando para ele 00:07:27.267 --> 00:07:34.971 que o arquivo de origem da minha aplicação está dentro da pasta "src/index". 00:07:34.971 --> 00:07:38.591 E esse é exatamente o caminho que nós checamos agora há pouco 00:07:38.591 --> 00:07:41.601 de onde estava o index da minha aplicação. 00:07:41.601 --> 00:07:45.575 Então, a partir do momento que eu copiei esses dados para dentro do container, 00:07:45.575 --> 00:07:48.668 eu, agora, mostrei para o Node como executá-lo. 00:07:48.668 --> 00:07:53.037 Por fim, eu estou fazendo um "EXPOSE" da porta 3000. 00:07:53.037 --> 00:07:56.109 Esse comando serve justamente para eu informar 00:07:56.109 --> 00:07:59.261 que eu vou ter que acessar uma porta desse container, 00:07:59.261 --> 00:08:03.866 dessa forma, na hora que eu for criar o container para colocá-lo em execução, 00:08:03.866 --> 00:08:07.689 o Docker vai saber que eu posso ter uma conexão de rede ali 00:08:07.689 --> 00:08:10.193 e vai permitir a criação dessa interação. 00:08:10.193 --> 00:08:15.138 Outro detalhe muito importante é que eu tenho duas formas de executar comandos. 00:08:15.138 --> 00:08:18.761 A primeira é a partir do comando "run". 00:08:18.761 --> 00:08:24.834 O run vai simplesmente executar aquela linha de comando dentro do meu container 00:08:24.834 --> 00:08:28.742 na hora que eu estiver fazendo toda a parte de construção dele. 00:08:28.742 --> 00:08:32.882 Enquanto isso, CMD vão ser comandos que vão ser executados 00:08:32.882 --> 00:08:35.433 posteriormente à criação do meu container. 00:08:35.433 --> 00:08:41.371 Dessa forma, quando eu crio lá o CMD chamando um comando Node e passando o index, 00:08:41.371 --> 00:08:46.603 toda vez que esse container for colocado em execução, esse comando vai ser chamado. 00:08:46.603 --> 00:08:49.776 Agora que todo esse processo está finalizado, 00:08:49.776 --> 00:08:54.446 eu posso utilizar esses arquivos para construir o meu container. 00:08:54.446 --> 00:09:00.519 Utilizando, então, o prompt de comando, eu vou poder recorrer a uma função chamada 00:09:01.297 --> 00:09:02.780 "docker build". 00:09:02.780 --> 00:09:04.966 Esse comando é um comando bem simples 00:09:04.966 --> 00:09:08.091 e não tem muita coisa que nós temos que configurar nele. 00:09:08.091 --> 00:09:12.702 Nesse caso, por exemplo, nós só vamos nomear a imagem 00:09:12.702 --> 00:09:16.608 e, em seguida, informar o endereço, para o Dockerfile, que vai ser utilizado. 00:09:16.608 --> 00:09:21.904 Para isso, eu vou informar o "-t" seguido do nome da imagem. 00:09:23.509 --> 00:09:29.148 Nesse caso, eu vou chamar ela de "ola" e, em seguida, eu vou informar um ponto. 00:09:29.148 --> 00:09:35.657 A função desse ponto é informar que eu já estou na pasta onde eu tenho o Dockerfile, 00:09:35.657 --> 00:09:39.080 caso eu não esteja nessa pasta, ao invés de informar o ponto, 00:09:39.080 --> 00:09:43.419 eu vou ter que informar todo o endereçamento de pasta 00:09:43.419 --> 00:09:47.884 e esse endereçamento vai variar entre sistemas operacionais. 00:09:47.884 --> 00:09:52.487 A forma mais fácil, então, é utilizar os comandos de navegação de terminal, 00:09:52.487 --> 00:09:56.269 como CD, para poder navegar pelos diretórios 00:09:56.269 --> 00:09:59.305 e, chegando no diretório que tem o Dockerfile, 00:09:59.305 --> 00:10:03.759 simplesmente executar o "docker build" com o ponto no final. 00:10:03.759 --> 00:10:08.855 Executando, então, o processo de build, várias coisas vão ser executadas. 00:10:08.855 --> 00:10:12.305 A primeira delas é todo o download de imagens, 00:10:12.305 --> 00:10:17.794 seguido da construção das aplicações, e todo o teste de funcionamento 00:10:17.794 --> 00:10:21.208 para ver se o comando inicial vai ser executado com sucesso. 00:10:21.208 --> 00:10:27.790 Caso você possua alguma falha nesse processo, você pode recorrer ao "docker logs". 00:10:27.790 --> 00:10:31.821 Esse é um comando que nos permite checar logs no ambiente Docker. 00:10:31.821 --> 00:10:36.509 Inclusive é legal que você pode utilizar ele para checar logs individualmente 00:10:36.509 --> 00:10:37.918 de cada container. 00:10:37.918 --> 00:10:40.413 Com o processo de build concluído, 00:10:40.413 --> 00:10:45.211 o Docker sempre vai perguntar se você não quer fazer um scan de vulnerabilidades. 00:10:45.211 --> 00:10:47.670 Nesse caso, não vai ser preciso. 00:10:47.670 --> 00:10:52.879 A única coisa que nos falta, agora, é colocar, justamente, esse container em execução. 00:10:52.879 --> 00:10:56.138 Para isso, nós vamos recorrer ao comando "docker run", 00:10:56.138 --> 00:11:00.376 só que, dessa vez, eu vou ter que passar alguns parâmetros de execução para ele. 00:11:00.376 --> 00:11:03.306 O primeiro parâmetro vai ser justamente para garantir 00:11:03.306 --> 00:11:06.963 que essa imagem vai ficar em execução o tempo todo. 00:11:06.963 --> 00:11:09.529 Para isso, vou utilizar o "-d". 00:11:09.529 --> 00:11:17.283 Enquanto o segundo parâmetro, "-p", vai ser para informar o apontamento de portas de rede, 00:11:17.283 --> 00:11:21.675 dessa forma, todo o conteúdo da minha aplicação vai ficar disponível para acesso. 00:11:21.675 --> 00:11:25.316 Para executar, então, o container que nós acabamos de criar, 00:11:25.316 --> 00:11:27.522 eu vou fazer um "docker run", 00:11:31.295 --> 00:11:32.525 "-d", 00:11:33.302 --> 00:11:36.289 "-p", para informar a porta, 00:11:36.289 --> 00:11:44.259 e, nesse caso, eu expus a porta 3000, então eu vou utilizar "3000 : 3000". 00:11:44.259 --> 00:11:49.989 A razão de eu ter que repetir o 3000 duas vezes é porque eu estou falando de duas portas. 00:11:49.989 --> 00:11:56.240 A primeira é a porta na minha máquina base e a segunda é a porta do meu container, 00:11:56.777 --> 00:12:02.064 Se eu especifico, por exemplo, a primeira porta, que é a da máquina base, como 80, 00:12:02.064 --> 00:12:07.914 ela vai apontar um acesso realizado na porta 80 do meu servidor base 00:12:07.914 --> 00:12:11.263 para a porta 3000 do meu container. 00:12:12.058 --> 00:12:15.254 Isso é algo que nós temos que prestar bastante atenção, 00:12:15.254 --> 00:12:17.523 às vezes, quando nós vamos criar uma aplicação, 00:12:17.523 --> 00:12:22.280 nós temos vários containers que têm exposta a porta 80 00:12:22.280 --> 00:12:26.799 e eu posso apontar diversas portas para dentro desses containers, 00:12:26.799 --> 00:12:30.666 utilizando numerações diferentes no meu host base. 00:12:30.666 --> 00:12:37.020 O próximo passo, então, é informar o nome da minha imagem, nesse caso, "ola". 00:12:37.020 --> 00:12:42.181 Colocando a imagem em execução, eu vou receber o código de validação dela 00:12:42.181 --> 00:12:45.234 e, se eu executar um "docker ps", 00:12:45.234 --> 00:12:48.978 note que essa minha imagem já se encontra em execução 00:12:48.978 --> 00:12:55.609 e me informando que a porta 3000 está apontando para a porta 3000 do container. 00:12:55.609 --> 00:12:59.208 O último passo, então, é abrir o navegador web 00:12:59.208 --> 00:13:03.858 e acessar, justamente, a nossa máquina na porta 3000. 00:13:03.858 --> 00:13:10.846 O IP que eu informei aqui 127.0.0.1 é o que se chama de local host, 00:13:10.846 --> 00:13:13.684 ele representa a própria máquina na rede. 00:13:13.684 --> 00:13:19.662 Outra forma que você teria era escrever por extenso "local host: 3000". 00:13:19.662 --> 00:13:25.315 Qualquer uma das duas formas já faria com que toda a interface funcionasse normalmente. 00:13:25.315 --> 00:13:28.347 No nosso caso, após acessar a aplicação, 00:13:28.347 --> 00:13:33.102 todo o código que nós criamos e compilamos já está aqui disponível para uso 00:13:33.102 --> 00:13:39.769 e eu consigo, por exemplo, ir adicionando itens dentro dessa minha aplicação. 00:13:39.769 --> 00:13:42.478 Esse é um exemplo de uma aplicação bem simples, 00:13:42.478 --> 00:13:46.643 só para nós entendermos como é que eu começo a construir todo esse ambiente. 00:13:47.209 --> 00:13:50.486 A partir de agora, você pode utilizar esses conhecimentos 00:13:50.486 --> 00:13:54.120 para começar a containerizar as suas próprias aplicações 00:13:54.120 --> 00:13:58.324 e, com isso, entender um pouco mais como todo esse ecossistema funciona.