Docker - Instalação, Configuração e Primeiros Passos

A instalação do Docker é o primeiro passo para abstrair a infraestrutura das suas aplicações, com ganhos tanto no desenvolvimento quanto em produção. Neste guia, você vai instalar e configurar o Docker Desktop, testar o ambiente e publicar uma API Node em um contêiner.

O que é o Docker

Com certeza você já ouviu a famosa frase "na minha máquina funciona". Então, se funciona na sua máquina, por que não enviar a própria máquina para produção?

Na prática, o Docker faz algo bem parecido com isso. Em termos gerais, ele abstrai a infraestrutura das aplicações por meio de imagens prontas.

O resultado lembra pequenas máquinas virtuais de baixo custo. Contudo, os contêineres compartilham o kernel do hospedeiro, por isso iniciam em segundos.

Por exemplo, uma das imagens mais famosas do Docker Hub é a Alpine, que ocupa apenas cerca de 5 MB. Ela contém somente o núcleo de uma distribuição Linux, que é o mínimo que a maioria das aplicações precisa para executar.

A partir dessa base, você adiciona o que precisar, como o SDK do .NET, o Node ou o PHP. Em seguida, gera um pacote com tudo isso.

Com o pacote montado, você o envia completo para produção. Assim, o servidor roda o mesmo ambiente que você testou.

Docker para desenvolvedores

Embora o Docker seja voltado para infraestrutura, um dos seus grandes usos são os ambientes de desenvolvimento. Hoje trabalhamos com vários bancos de dados, tecnologias e serviços ao mesmo tempo.

Imagine instalar SQL Server, MySQL e MongoDB na sua máquina, todos rodando como serviços do Windows. É complicado.

Nesse caso, a alternativa é usar imagens prontas desses bancos e executá-las apenas quando quiser.

Quer criar um projeto com SQL Server? Basta baixar a imagem oficial, executar o contêiner e o serviço já está no ar.

O Docker funciona no Mac, no Windows e no Linux. No Windows, o recomendado é usar o Windows 10 ou superior, porque essas versões suportam o subsistema Linux, que serve de base para o Docker.

Requisitos para a instalação do Docker

Agora vem a parte mais chata, os requisitos para a instalação do Docker. Memória e CPU variam conforme a quantidade de contêineres em execução, mas o disco sempre fará diferença.

Manter as imagens locais economiza banda e tempo, mas consome disco. Em discos pequenos, como os de 128 GB, vale excluir as imagens que não estiver usando.

Não são recomendações oficiais, mas prefira pelo menos um processador dual core e 8 GB de RAM. Também conte com cerca de 2 GB de disco só para a instalação inicial do Docker.

Outro ponto importante é a virtualização. A instalação do Docker no Windows depende da virtualização de hardware habilitada na BIOS ou UEFI do computador.

Versões e licenciamento do Docker

Durante muito tempo, o Docker foi dividido em dois produtos, o Community Edition (CE) e o Enterprise Edition (EE). O Community era gratuito e voltado à comunidade, enquanto o Enterprise atendia o uso empresarial.

Para quem está começando, tudo que precisamos para estudar está disponível gratuitamente para uso pessoal e educacional.

No entanto, fique atento ao licenciamento do Docker Desktop em empresas. Organizações maiores precisam de uma assinatura paga, então confira os termos atuais no site oficial antes de adotar a ferramenta no trabalho.

Criando a conta no Docker Hub

A primeira coisa a fazer é criar uma conta no Docker Hub. Ela serve tanto para entrar no Docker Desktop quanto para gerenciar suas imagens publicadas.

Caso ainda não tenha, acesse o site oficial do Docker, clique em Sign In e, em seguida, em Sign Up.

Preencha as informações e confirme o cadastro pelo e-mail de verificação.

Instalação do Docker Desktop passo a passo

O Docker possui uma versão para desktop que facilita muito a nossa vida. Se você gosta de linha de comando, não se preocupe, pois a instalação do Docker Desktop também inclui o CLI.

Primeiro, acesse a página de início do Docker e siga para a área de downloads. Em seguida, selecione a versão do seu sistema operacional, como Docker Desktop for Windows ou Docker Desktop for Mac.

Depois, execute o instalador e acompanhe todo o processo. Ao terminar, recomendamos reiniciar o computador para que todas as configurações entrem em vigor.

Instalação do Docker no Windows com WSL 2

O WSL é um subsistema Linux que roda dentro do Windows e permite executar o Docker de forma mais otimizada. Por isso, recomendamos fortemente usar o WSL 2 sempre que possível, já que ele melhora o desempenho e a estabilidade.

O ideal é habilitar o WSL 2 antes da instalação do Docker. Para isso, siga o nosso guia de instalação do WSL e só depois execute o instalador.

Assim, na primeira tela do instalador aparece a opção abaixo, que deve ficar marcada.

Enable WSL 2 Windows features

Caso já tenha o Docker instalado e queira apenas rodá-lo via WSL, altere as opções em Settings > Resources > WSL Integration e marque Enable integration with my default WSL distro.

Contêineres Linux ou Windows

Durante a instalação no Windows, o Docker pode perguntar se você prefere usar contêineres Windows em vez de Linux. Fique à vontade para testar essa opção depois.

Contudo, para acompanhar nossos cursos, recomendamos não marcar essa opção. Nos cursos, sempre usamos contêineres Linux como padrão.

Configuração do Docker Desktop após a instalação

Após reiniciar o computador, abra o Docker Desktop caso ele não tenha iniciado sozinho. Você sabe que ele está em execução quando o ícone da baleia aparece perto do relógio, na bandeja do sistema.

No primeiro acesso, o Docker pede que você entre com o Docker ID criado anteriormente. Recomendamos fortemente fazer o login agora.

Se perder essa primeira tela, clique no ícone da baleia e escolha Sign In.

Como ajuste adicional, abra Settings pelo mesmo ícone. Na aba General, desmarque a opção que inicia o Docker Desktop junto com o login do usuário.

Dessa forma, a inicialização do sistema fica mais leve. Porém, em uma máquina potente, pode manter a opção marcada.

Testando a instalação do Docker

A instalação do Docker também instala o CLI, que disponibiliza o comando docker no terminal. Então, abra um terminal e digite o comando abaixo para ver a versão instalada.

docker --version

No Windows, recomendamos o Windows Terminal ou o PowerShell.

Agora execute o famoso Hello World para confirmar que tudo funciona.

docker run hello-world

Ao executar o comando, aparece a mensagem Unable to find image 'hello-world:latest' locally. Ou seja, o Docker não encontrou nenhuma imagem com esse nome na sua máquina.

Mesmo assim, o Docker procura a imagem no Docker Hub, faz o download e executa o contêiner.

Se a instalação do Docker deu certo, a saída exibe a mensagem This message shows that your installation appears to be working correctly.

Imagens e contêineres

Logo após a instalação do Docker, esses primeiros comandos fizeram duas coisas importantes. O Docker baixou uma imagem e criou um contêiner a partir dela.

Uma imagem é o pacote cru e somente leitura, enquanto o contêiner é uma instância em execução dessa imagem. Em outras palavras, nunca executamos imagens, sempre executamos contêineres baseados nelas.

Listando e removendo imagens

Para listar as imagens que você tem localmente, execute o comando abaixo.

docker image ls

Como essas imagens ocupam disco, você pode removê-las e baixá-las de novo quando quiser.

Para remover uma imagem baixada, use o comando docker image rm, que também tem o atalho docker rmi.

# substitua IMAGE_ID pelo identificador exibido no docker image ls
docker image rm IMAGE_ID

Vale frisar que o Docker não apaga uma imagem enquanto algum contêiner depende dela. Nesse caso, remova o contêiner primeiro.

Listando, iniciando e removendo contêineres

Para listar os contêineres, usamos o comando abaixo. Contudo, o hello-world não aparece nessa lista.

docker container ls

Isso acontece porque o comando mostra apenas contêineres em execução, e o hello-world termina logo após exibir a mensagem. Então, para ver todos os contêineres da máquina, acrescente --all no final.

docker container ls --all

Para iniciar ou parar um contêiner, usamos os comandos start e stop.

docker container start CONTAINER_ID
docker container stop CONTAINER_ID

Para ver a lista completa de operações disponíveis para contêineres, execute o comando de ajuda.

docker container --help

Com o contêiner parado, você pode removê-lo com o comando abaixo. Em seguida, se quiser, remova também a imagem baixada.

docker container rm CONTAINER_ID

Publicando uma API Node em um contêiner

Com a instalação do Docker concluída, chegou a hora do desafio final. Vamos publicar uma API criada com Node e JavaScript em um contêiner e acessá-la pelo navegador.

Para esta etapa, você precisa do Git e do Visual Studio Code instalados. Se ainda não configurou o Git, veja nosso artigo sobre Git e GitHub para iniciantes.

Abra um terminal, navegue até uma pasta com caminho curto e sem caracteres especiais e execute o comando abaixo.

git clone https://github.com/andrebaltieri/docker-sample-api.git

Esse comando baixa o código de uma API de exemplo do nosso GitHub e cria a pasta docker-sample-api.

Escrevendo o Dockerfile

Com o código baixado, precisamos dizer ao Docker como empacotar a aplicação. Para isso, usamos o Dockerfile, o arquivo de instruções que define a imagem base e os passos da publicação.

Abra a pasta docker-sample-api no Visual Studio Code e crie um arquivo chamado Dockerfile na raiz. Note que esse arquivo não tem extensão, o nome é apenas Dockerfile.

O primeiro passo é definir a imagem base com a instrução FROM. Neste caso, vamos usar a imagem oficial do Node, mas o Docker Hub oferece imagens oficiais de diversas empresas.

FROM node:current-slim

O trecho depois dos dois pontos é a tag da imagem, que identifica a versão. Aqui, current aponta para a versão atual do Node e slim indica uma variante enxuta.

Portanto, consulte sempre o Docker Hub para escolher a tag certa.

Em seguida, definimos com WORKDIR a pasta, dentro da imagem, onde o código ficará.

WORKDIR /usr/src/app

Agora copiamos o package.json, que lista os pacotes de que a API precisa. No Node não instalamos um SDK, mas toda aplicação depende da pasta node_modules com suas bibliotecas.

COPY package.json .

O ponto no fim do comando indica que o arquivo vai para a pasta definida no WORKDIR. Depois, rodamos o npm install com a instrução RUN.

RUN npm install

Copiar o package.json antes do código permite que o Docker reaproveite a camada de pacotes em cache.

Na sequência, copiamos o restante da aplicação, da raiz do projeto para a raiz definida no WORKDIR.

COPY . .

Porta e comando de inicialização

Também informamos a porta da API com a instrução EXPOSE. Nossa API roda internamente na porta 3000, conforme definido no arquivo bin/www do projeto.

EXPOSE 3000

Vale um detalhe importante: o EXPOSE funciona como documentação. Ele não publica a porta sozinho, quem faz isso é o parâmetro --publish na hora de rodar o contêiner.

Por fim, a instrução CMD define o comando que inicia a aplicação. Na forma de lista, o Docker exige aspas duplas, porque interpreta o valor como JSON.

CMD ["npm", "start"]

O arquivo Dockerfile completo fica assim.

# imagem base com o Node em versão enxuta
FROM node:current-slim

# pasta de trabalho dentro da imagem
WORKDIR /usr/src/app

# copia o package.json e instala as dependências
COPY package.json .
RUN npm install

# copia o restante do código da aplicação
COPY . .

# documenta a porta em que a API escuta
EXPOSE 3000

# comando executado quando o contêiner inicia
CMD ["npm", "start"]

Criando a imagem

Nosso desafio agora é criar uma imagem customizada, algo que a instalação do Docker já deixou pronto para fazer. Para isso, usamos o comando docker image build.

Confirme que você está na raiz da API, a pasta docker-sample-api, e execute o comando abaixo.

docker image build -t dockerapi:1.0 .

O parâmetro -t dá um nome à imagem no formato nome:versão, o que facilita as próximas execuções. Já o ponto final indica a pasta onde está o Dockerfile, que no caso é a raiz da API.

Para conferir se deu certo, execute docker image ls e procure a imagem dockerapi na lista.

Rodando o contêiner

A última etapa é executar essa imagem como um contêiner. Para isso, usamos o comando docker container run.

docker container run --publish 8080:3000 --detach --name api dockerapi:1.0

O parâmetro --publish redireciona o tráfego da porta 8080 da sua máquina para a porta 3000 do contêiner. Assim, você acessa a API em http://localhost:8080, enquanto ela continua rodando na porta 3000 internamente.

Já o --detach executa o contêiner em segundo plano, sem travar o terminal.

O --name define o nome do contêiner, desde que não tenha espaços nem caracteres especiais. Por fim, informamos a imagem que acabamos de criar.

Agora abra o navegador em http://localhost:8080 e veja a mensagem Docker Node API Running. Isso significa que a API está no ar.

Daqui em diante, docker container stop api e docker container start api param ou iniciam o contêiner.

Acessando os logs

Para ver os logs da API, clique no ícone que a instalação do Docker adicionou à bandeja e abra a opção Dashboard. Uma nova tela lista o contêiner que acabamos de criar.

Em seguida, clique no contêiner e abra a aba Logs para acompanhar tudo que acontece nele. Se preferir o terminal, o comando docker container logs api mostra a mesma saída.

Rodando o SQL Server após a instalação do Docker

Nas versões mais recentes, o Kitematic foi descontinuado e deu lugar ao Dashboard do Docker Desktop. No entanto, o Dashboard não serve para navegar no Docker Hub e baixar imagens, então esse primeiro passo acontece pela linha de comando.

Por exemplo, após a instalação do Docker, você baixa a imagem do SQL Server com o comando abaixo.

docker pull mcr.microsoft.com/mssql/server

Em seguida, inicie o contêiner baseado nessa imagem. No Mac e no Linux, o comando fica assim.

docker run --name sqlserver -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=1q2w3e4r@#$" -p 1433:1433 -d mcr.microsoft.com/mssql/server

No Windows, o comando inclui também o parâmetro -v para mapear um volume.

docker run -v ~/docker --name sqlserver -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=1q2w3e4r@#$" -p 1433:1433 -d mcr.microsoft.com/mssql/server

A variável ACCEPT_EULA confirma o aceite da licença, e a MSSQL_SA_PASSWORD define a senha do usuário sa. Segundo a documentação do SQL Server em contêineres, a senha precisa ter pelo menos oito caracteres e combinar letras, números e símbolos.

Se a senha não atender a essa política, o contêiner para logo após iniciar. Nesse caso, o comando docker logs sqlserver mostra o erro.

A partir daí, o contêiner aparece no Dashboard do Docker Desktop. Para um passo a passo completo, veja nossos artigos sobre SQL Server no Docker e MongoDB no Docker.

Problemas comuns na instalação do Docker

O erro mais comum na instalação do Docker no Windows é a virtualização desabilitada. Nesse caso, entre na BIOS ou UEFI e ative a opção de virtualização do processador.

Outro problema frequente é um WSL desatualizado. Então, execute wsl --update em um terminal com permissão de administrador e reinicie o Docker Desktop.

Por fim, se o comando docker não for reconhecido, abra um novo terminal, já que o instalador altera o PATH.

Conclusão sobre a instalação do Docker

Criar e executar imagens e contêineres no Docker não é uma tarefa difícil. Neste artigo, você fez a instalação do Docker, configurou o Docker Desktop e publicou sua primeira API em um contêiner.

Os próximos passos são volumes, redes e Docker Compose. Em .NET, veja também como publicar aplicações .NET como contêineres sem Dockerfile.

FAQ

O Docker é gratuito?

O Docker Engine é open source e o Docker Desktop é gratuito para uso pessoal, educacional e pequenas empresas. Organizações maiores precisam de uma assinatura paga.

Preciso do WSL 2 para usar o Docker no Windows?

O WSL 2 é o backend recomendado para o Docker Desktop no Windows. Ele oferece melhor desempenho e integração com distribuições Linux.

Qual a diferença entre imagem e contêiner?

A imagem é o pacote somente leitura com a aplicação e suas dependências. O contêiner é uma instância em execução criada a partir dessa imagem.

Por que o hello-world não aparece no docker container ls?

Esse comando lista apenas contêineres em execução. Como o hello-world encerra logo depois de exibir a mensagem, você precisa usar o parâmetro --all.

O EXPOSE publica a porta do contêiner?

Não, o EXPOSE apenas documenta a porta em que a aplicação escuta. Quem publica a porta para a máquina é o parâmetro --publish do docker container run.