1 00:00:08,952 --> 00:00:13,039 Um dos passos mais importantes quando nós falamos da utilização de Docker 2 00:00:13,039 --> 00:00:16,730 é justamente aprender a criar o nosso próprio Docker, 3 00:00:16,730 --> 00:00:19,720 ou pelo menos a nossa própria imagem. 4 00:00:20,280 --> 00:00:23,406 Para isso, nós vamos ter que utilizar algumas ferramentas. 5 00:00:23,406 --> 00:00:29,686 A primeira e provavelmente mais importante nesse processo vai ser o Dockerfile. 6 00:00:29,686 --> 00:00:34,925 Ele é basicamente um arquivo que vai permitir que eu passe instruções para o Docker 7 00:00:34,925 --> 00:00:37,656 de como ele deve construir aquela imagem. 8 00:00:37,656 --> 00:00:41,498 Antes de mais nada, eu vou precisar pelo menos de algum código 9 00:00:41,498 --> 00:00:45,238 para que eu consiga colocar em desenvolvimento. 10 00:00:45,238 --> 00:00:51,153 Para isso, eu peguei um códigozinho bem simples de "hello, world" baseado em Node, 11 00:00:51,153 --> 00:00:55,238 é basicamente uma página que tem um campinho de preenchimento de busca 12 00:00:55,238 --> 00:00:59,239 e um botãozinho, mas essa função não tem nada programado, 13 00:00:59,239 --> 00:01:02,540 é realmente só para nós termos um código para utilizar. 14 00:01:02,540 --> 00:01:06,359 Nesse caso, nós vamos utilizar um código em Node 15 00:01:06,359 --> 00:01:11,328 e, justamente por isso, eu preciso utilizar, como base para a minha imagem, 16 00:01:11,328 --> 00:01:15,383 uma imagem que já tenha um Node pronto para eu poder utilizar. 17 00:01:15,383 --> 00:01:18,114 Caso nós não achemos uma imagem dessa forma, 18 00:01:18,114 --> 00:01:21,732 nós podemos passar comandos dentro de um container 19 00:01:21,732 --> 00:01:25,805 para que ele faça todo o processo de instalação daquele software 20 00:01:25,805 --> 00:01:29,387 e disponibilize todo aquele ambiente montado para nós. 21 00:01:29,387 --> 00:01:34,137 Aqui dentro da minha tela, eu vou ter, então, uma pasta chamada "app", 22 00:01:34,137 --> 00:01:39,634 que eu criei dentro do meu desktop, e nela eu vou ter alguns arquivos. 23 00:01:40,640 --> 00:01:46,613 O "yarn.lock", o "package", a pasta "src" e a pasta "spec" 24 00:01:46,613 --> 00:01:51,054 são justamente conteúdos que eu tenho dessa minha aplicação. 25 00:01:51,054 --> 00:01:56,269 Se eu abro, por exemplo, aqui, o "src", eu vou ter um "index.js", 26 00:01:56,269 --> 00:02:00,836 que vai ser, justamente, o arquivo inicial da minha aplicação. 27 00:02:02,272 --> 00:02:06,141 Aqui nessa pasta, eu ainda tenho o arquivo chamado Dockerfile. 28 00:02:06,141 --> 00:02:09,172 Esse é o arquivo que vai trazer todas as instruções 29 00:02:09,172 --> 00:02:12,757 que o Docker precisa para construir a nossa imagem. 30 00:02:13,316 --> 00:02:15,892 Existem algumas características muito importantes 31 00:02:15,892 --> 00:02:17,921 que nós temos que nos atentar nele, 32 00:02:17,921 --> 00:02:23,243 a primeira delas é que esse arquivo não tem extensão, 33 00:02:24,144 --> 00:02:27,990 a segunda é que ele sempre vai começar com D maiúsculo 34 00:02:27,990 --> 00:02:30,769 e Dockerfile vai estar escrito tudo junto. 35 00:02:30,769 --> 00:02:34,461 Eu preciso justamente prestar atenção em todos esses padrões 36 00:02:34,461 --> 00:02:37,423 para que eu não impeça o Docker de achar o arquivo 37 00:02:37,423 --> 00:02:40,125 e, assim, começar o processo de build da imagem. 38 00:02:40,125 --> 00:02:45,251 Agora, como eu valido isso aqui dentro dos meus arquivos? 39 00:02:45,251 --> 00:02:49,549 Basta eu vir na aba de visualização do Explorer no Windows 40 00:02:49,549 --> 00:02:56,029 e marcar a opção "file name extensions" ou mostrar extensões de arquivo. 41 00:02:56,029 --> 00:03:00,023 Note que agora todos os meus arquivos ganharam uma extensão, 42 00:03:00,023 --> 00:03:02,168 menos o dockerfile. 43 00:03:02,168 --> 00:03:07,812 Pode ser que, quando você criou o arquivo utilizando, por exemplo, o bloco de notas, 44 00:03:07,812 --> 00:03:11,942 ele tivesse mostrado uma opção como txt. 45 00:03:11,942 --> 00:03:16,526 Caso ele tenha aparecido como txt no final, basta apertar a tecla F2 46 00:03:16,526 --> 00:03:22,692 e renomear o arquivo, excluindo o ".txt" e deixando apenas "dockerfile". 47 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, 48 00:03:27,424 --> 00:03:30,833 basta confirmar e seguir para as próximas etapas. 49 00:03:30,833 --> 00:03:34,180 Quando nós abrimos o Dockerfile dentro de um bloco de notas, 50 00:03:34,180 --> 00:03:36,990 nós vamos ter uma estrutura até bem simples. 51 00:03:36,990 --> 00:03:40,977 A primeira coisa que nós vamos ver é justamente um comentário 52 00:03:40,977 --> 00:03:46,419 definindo qual tipo de sintaxe nós estamos utilizando para construção desse arquivo. 53 00:03:46,419 --> 00:03:49,364 Nesse caso, uma sintaxe de versão 1. 54 00:03:49,364 --> 00:03:54,531 As linhas de comando que definem a sintaxe estão lá na documentação do Docker. 55 00:03:54,531 --> 00:03:59,303 Por hora, você pode simplesmente copiar essa linha para todos os seus arquivos 56 00:03:59,303 --> 00:04:02,417 e tudo vai correr sem maiores problemas. 57 00:04:02,417 --> 00:04:05,959 Agora, caso você se torne um usuário avançado de Docker, 58 00:04:05,959 --> 00:04:12,052 algumas funções só vão estar disponíveis em versões específicas do Dockerfile, 59 00:04:12,052 --> 00:04:16,880 então você vai ter que ficar atento a qual tipo de Dockerfile utilizar 60 00:04:16,880 --> 00:04:21,237 para poder criar exatamente o container da forma que você precisa. 61 00:04:21,237 --> 00:04:25,331 Logo em seguida, eu tenho um comando chamado "FROM". 62 00:04:25,331 --> 00:04:31,171 Esse comando serve para eu especificar qual imagem de base que eu vou utilizar. 63 00:04:31,171 --> 00:04:37,259 Nesse caso, uma imagem chamada "node" na versão "12-alpine". 64 00:04:37,259 --> 00:04:42,627 É justamente aqui, por exemplo, que caso eu queira criar um container totalmente do zero 65 00:04:42,627 --> 00:04:45,562 utilizando só um sistema operacional de base, 66 00:04:45,562 --> 00:04:49,519 eu vou conseguir especificar que eu quero esse sistema operacional. 67 00:04:49,519 --> 00:04:52,992 Se eu quisesse, por exemplo, criar um servidor Apache do zero, 68 00:04:52,992 --> 00:04:58,466 eu poderia fazer um FROM Ubuntu e, nos comandos que se seguem, 69 00:04:58,466 --> 00:05:02,198 fazer todo o passo a passo de instalação do Apache. 70 00:05:02,198 --> 00:05:08,140 Nesse caso, nós já estamos reaproveitando parte da estrutura do Node que já está pronta 71 00:05:08,140 --> 00:05:11,301 e, aí, eu só preciso rodar alguns poucos comandos 72 00:05:11,301 --> 00:05:14,495 e copiar os meus arquivos para dentro do container. 73 00:05:14,495 --> 00:05:19,203 Nosso próximo passo, então, é rodar um "apk add" 74 00:05:19,203 --> 00:05:24,515 para garantir que eu tenho um python2, o compilador C 75 00:05:24,515 --> 00:05:27,246 e o make dentro da minha máquina. 76 00:05:27,777 --> 00:05:33,423 O nosso próximo passo, então, vai ser criar um diretório de trabalho, 77 00:05:33,423 --> 00:05:35,747 nesse caso, chamado "app". 78 00:05:35,747 --> 00:05:40,236 Esse diretório de trabalho vai basicamente informar para o container 79 00:05:40,236 --> 00:05:43,219 qual pasta ele deve utilizar para poder trabalhar. 80 00:05:43,219 --> 00:05:49,232 Note que todo o nosso conteúdo do arquivo está dentro de uma pasta chamada "app", 81 00:05:49,232 --> 00:05:52,665 dessa forma, eu vou conseguir navegar para dentro dessa pasta, 82 00:05:52,665 --> 00:05:55,179 utilizar ela como pasta padrão 83 00:05:55,179 --> 00:05:58,766 e, a partir de então, começar a executar os demais comandos. 84 00:05:58,766 --> 00:06:04,387 O comando "COPY" serve justamente para eu copiar arquivos para dentro do container. 85 00:06:04,387 --> 00:06:08,988 Ele vai copiar todos os arquivos da pasta que eu me encontro, 86 00:06:08,988 --> 00:06:14,627 por isso o ponto, para a pasta que eu estarei utilizando dentro do container, 87 00:06:14,627 --> 00:06:17,561 por isso, eu vou utilizar "." novamente. 88 00:06:17,561 --> 00:06:19,812 E aqui vai vir um ponto bem interessante: 89 00:06:19,812 --> 00:06:23,466 a cópia do arquivo não é exatamente uma boa prática, 90 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, 91 00:06:29,468 --> 00:06:32,826 isso vai atrapalhar o bom funcionamento de um container. 92 00:06:32,826 --> 00:06:37,397 A questão, nesse caso, é que, como eu estou criando um container novo, 93 00:06:37,397 --> 00:06:42,192 eu preciso passar todos os códigos que vão servir de base para ele, 94 00:06:42,192 --> 00:06:47,010 então eu posso copiar esses arquivos sem a menor dor de cabeça, 95 00:06:47,010 --> 00:06:50,476 já que eles vão passar a ser parte fundamental 96 00:06:50,476 --> 00:06:52,590 de todo o container que eu estou criando. 97 00:06:52,590 --> 00:06:54,267 O passo seguinte, então, 98 00:06:54,267 --> 00:07:00,560 é garantir que esse meu sistema esteja utilizando um ambiente de produção. 99 00:07:00,560 --> 00:07:03,298 Para isso, eu posso executar um "yarn install". 100 00:07:03,298 --> 00:07:06,506 Esse comando é um comando que pertence ao ambiente Node 101 00:07:06,506 --> 00:07:10,250 e serve basicamente para instalar todos os pacotes necessários 102 00:07:10,250 --> 00:07:13,622 e preparar o ambiente para a execução daquela minha aplicação. 103 00:07:13,622 --> 00:07:17,363 Em seguida, eu vou utilizar o "CMD", 104 00:07:17,363 --> 00:07:22,822 que é basicamente uma forma de criar linhas de comando dentro do container. 105 00:07:22,822 --> 00:07:27,267 Nesse caso, eu estou chamando o comando Node e informando para ele 106 00:07:27,267 --> 00:07:34,971 que o arquivo de origem da minha aplicação está dentro da pasta "src/index". 107 00:07:34,971 --> 00:07:38,591 E esse é exatamente o caminho que nós checamos agora há pouco 108 00:07:38,591 --> 00:07:41,601 de onde estava o index da minha aplicação. 109 00:07:41,601 --> 00:07:45,575 Então, a partir do momento que eu copiei esses dados para dentro do container, 110 00:07:45,575 --> 00:07:48,668 eu, agora, mostrei para o Node como executá-lo. 111 00:07:48,668 --> 00:07:53,037 Por fim, eu estou fazendo um "EXPOSE" da porta 3000. 112 00:07:53,037 --> 00:07:56,109 Esse comando serve justamente para eu informar 113 00:07:56,109 --> 00:07:59,297 que eu vou ter que acessar uma porta desse container, 114 00:07:59,297 --> 00:08:03,586 dessa forma, na hora que eu for criar o container para colocá-lo em execução, 115 00:08:03,586 --> 00:08:07,699 o Docker vai saber que eu posso ter uma conexão de rede ali 116 00:08:07,699 --> 00:08:10,289 e vai permitir a criação dessa interação. 117 00:08:10,289 --> 00:08:15,328 Outro detalhe muito importante é que eu tenho duas formas de executar comandos. 118 00:08:15,328 --> 00:08:18,931 A primeira é a partir do comando "run". 119 00:08:18,931 --> 00:08:25,004 O run vai simplesmente executar aquela linha de comando dentro do meu container 120 00:08:25,004 --> 00:08:28,875 na hora que eu estiver fazendo toda a parte de construção dele. 121 00:08:28,875 --> 00:08:33,012 Enquanto isso, CMD vão ser comandos que vão ser executados 122 00:08:33,012 --> 00:08:35,515 posteriormente à criação do meu container. 123 00:08:35,515 --> 00:08:41,521 Dessa forma, quando eu crio lá o CMD chamando um comando Node e passando o index, 124 00:08:41,521 --> 00:08:46,759 toda vez que esse container for colocado em execução, esse comando vai ser chamado. 125 00:08:46,759 --> 00:08:49,996 Agora que todo esse processo está finalizado, 126 00:08:49,996 --> 00:08:54,446 eu posso utilizar esses arquivos para construir o meu container. 127 00:08:54,446 --> 00:09:00,674 Utilizando, então, o prompt de comando, eu vou poder recorrer a uma função chamada 128 00:09:01,407 --> 00:09:02,975 "docker build". 129 00:09:02,975 --> 00:09:05,106 Esse comando é um comando bem simples 130 00:09:05,106 --> 00:09:08,281 e não tem muita coisa que nós temos que configurar nele. 131 00:09:08,281 --> 00:09:12,852 Nesse caso, por exemplo, nós só vamos nomear a imagem 132 00:09:12,852 --> 00:09:16,789 e, em seguida, informar o endereço, para o Dockerfile, que vai ser utilizado. 133 00:09:16,789 --> 00:09:21,904 Para isso, eu vou informar o "-t" seguido do nome da imagem. 134 00:09:23,629 --> 00:09:29,268 Nesse caso, eu vou chamar ela de "ola" e, em seguida, eu vou informar um ponto. 135 00:09:29,268 --> 00:09:35,509 A função desse ponto é informar que eu já estou na pasta onde eu tenho o Dockerfile, 136 00:09:35,509 --> 00:09:39,230 caso eu não esteja nessa pasta, ao invés de informar o ponto, 137 00:09:39,230 --> 00:09:43,649 eu vou ter que informar todo o endereçamento de pasta 138 00:09:43,649 --> 00:09:48,154 e esse endereçamento vai variar entre sistemas operacionais. 139 00:09:48,154 --> 00:09:52,627 A forma mais fácil, então, é utilizar os comandos de navegação de terminal, 140 00:09:52,627 --> 00:09:56,429 como CD, para poder navegar pelos diretórios 141 00:09:56,429 --> 00:09:59,365 e, chegando no diretório que tem o Dockerfile, 142 00:09:59,365 --> 00:10:03,903 simplesmente executar o "docker build" com o ponto no final. 143 00:10:03,903 --> 00:10:08,975 Executando, então, o processo de build, várias coisas vão ser executadas. 144 00:10:08,975 --> 00:10:12,445 A primeira delas é todo o download de imagens, 145 00:10:12,445 --> 00:10:17,964 seguido da construção das aplicações, e todo o teste de funcionamento 146 00:10:17,964 --> 00:10:21,253 para ver se o comando inicial vai ser executado com sucesso. 147 00:10:21,253 --> 00:10:27,960 Caso você possua alguma falha nesse processo, você pode recorrer ao "docker logs". 148 00:10:27,960 --> 00:10:32,031 Esse é um comando que nos permite checar logs no ambiente Docker. 149 00:10:32,031 --> 00:10:36,559 Inclusive é legal que você pode utilizar ele para checar logs individualmente 150 00:10:36,559 --> 00:10:37,859 de cada container. 151 00:10:37,859 --> 00:10:40,573 Com o processo de build concluído, 152 00:10:40,573 --> 00:10:45,411 o Docker sempre vai perguntar se você não quer fazer um scan de vulnerabilidades. 153 00:10:45,411 --> 00:10:47,880 Nesse caso, não vai ser preciso. 154 00:10:47,880 --> 00:10:52,885 A única coisa que nos falta agora é colocar, justamente, esse container em execução. 155 00:10:52,885 --> 00:10:56,288 Para isso, nós vamos recorrer ao comando "docker run", 156 00:10:56,288 --> 00:11:00,459 só que, dessa vez, eu vou ter que passar alguns parâmetros de execução para ele. 157 00:11:00,459 --> 00:11:03,396 O primeiro parâmetro vai ser justamente para garantir 158 00:11:03,396 --> 00:11:07,133 que essa imagem vai ficar em execução o tempo todo. 159 00:11:07,133 --> 00:11:09,769 Para isso, vou utilizar o "-d". 160 00:11:09,769 --> 00:11:17,443 Enquanto o segundo parâmetro, "-p", vai ser para informar o apontamento de portas de rede, 161 00:11:17,443 --> 00:11:21,706 dessa forma, todo o conteúdo da minha aplicação vai ficar disponível para acesso. 162 00:11:21,706 --> 00:11:25,496 Para executar, então, o container que nós acabamos de criar, 163 00:11:25,496 --> 00:11:27,591 eu vou fazer um "docker run", 164 00:11:31,665 --> 00:11:32,615 "-d", 165 00:11:33,392 --> 00:11:36,429 "-p", para informar a porta, 166 00:11:36,429 --> 00:11:44,336 e, nesse caso, eu expus a porta 3000, então eu vou utilizar "3000 : 3000". 167 00:11:44,336 --> 00:11:50,209 A razão de eu ter que repetir o 3000 duas vezes é porque eu estou falando de duas portas. 168 00:11:50,209 --> 00:11:56,062 A primeira é a porta na minha máquina base e a segunda é a porta do meu container, 169 00:11:56,857 --> 00:12:02,254 Se eu especifico, por exemplo, a primeira porta, que é a da máquina base, como 80, 170 00:12:02,254 --> 00:12:08,094 ela vai apontar um acesso realizado na porta 80 do meu servidor base 171 00:12:08,094 --> 00:12:11,355 para a porta 3000 do meu container. 172 00:12:12,198 --> 00:12:15,434 Isso é algo que nós temos que prestar bastante atenção, 173 00:12:15,434 --> 00:12:17,703 às vezes, quando nós vamos criar uma aplicação, 174 00:12:17,703 --> 00:12:22,374 nós temos vários containers que têm exposta a porta 80 175 00:12:22,374 --> 00:12:26,979 e eu posso apontar diversas portas para dentro desses containers, 176 00:12:26,979 --> 00:12:30,783 utilizando numerações diferentes no meu host base. 177 00:12:30,783 --> 00:12:36,630 O próximo passo, então, é informar o nome da minha imagem, nesse caso, "ola". 178 00:12:36,630 --> 00:12:42,361 Colocando a imagem em execução, eu vou receber o código de validação dela 179 00:12:42,361 --> 00:12:45,364 e, se eu executar um "docker ps", 180 00:12:45,364 --> 00:12:49,168 note que essa minha imagem já se encontra em execução 181 00:12:49,168 --> 00:12:55,741 e me informando que a porta 3000 está apontando para a porta 3000 do container. 182 00:12:55,741 --> 00:12:59,378 O último passo, então, é abrir o navegador web 183 00:12:59,378 --> 00:13:04,083 e acessar, justamente, a nossa máquina na porta 3000. 184 00:13:04,083 --> 00:13:11,056 O IP que eu informei aqui 127.0.0.1 é o que se chama de local host, 185 00:13:11,056 --> 00:13:13,759 ele representa a própria máquina na rede. 186 00:13:13,759 --> 00:13:19,832 Outra forma que você teria era escrever por extenso "local host: 3000". 187 00:13:19,832 --> 00:13:25,404 Qualquer uma das duas formas já faria com que toda a interface funcionasse normalmente. 188 00:13:25,404 --> 00:13:28,507 No nosso caso, após acessar a aplicação, 189 00:13:28,507 --> 00:13:33,312 todo o código que nós criamos e compilamos já está aqui disponível para uso 190 00:13:33,312 --> 00:13:39,852 e eu consigo, por exemplo, ir adicionando itens dentro dessa minha aplicação. 191 00:13:39,852 --> 00:13:42,688 Esse é um exemplo de uma aplicação bem simples, 192 00:13:42,688 --> 00:13:46,643 só para nós entendermos como é que eu começo a construir todo esse ambiente. 193 00:13:47,359 --> 00:13:50,696 A partir de agora, você pode utilizar esses conhecimentos 194 00:13:50,696 --> 00:13:54,300 para começar a containerizar as suas próprias aplicações 195 00:13:54,300 --> 00:13:58,304 e, com isso, entender um pouco mais como todo esse ecossistema funciona.