---
# System prepended metadata

title: Começando com Docker

---

# Começando com Docker

Por Fernando Furtado (Alura)
21/06/2017

Quando falamos em desenvolvimento de software é comum ter diversos ambientes, por exemplo:

- Desenvolvimento
- Teste
- Homologação
- Produção

E outra coisa comum no mundo de desenvolvimento é ter divergências entre estes ambientes.

Quem nunca ouviu a frase:

*"Na minha máquina funciona!"?*

Nesse post vamos abordar o [Docker](https://www.docker.com/) como uma alternativa para minimizar essa divergência.

## Mas o que é o Docker?
O Docker é um sistema de virtualização não convencional. Mas o que isso quer dizer? Em virtualizações convencionais temos um software instalado na máquina Host que irá gerenciar as máquinas virtuais (ex.: VirtualBox, VMWare, Parallels e etc...).

Para cada máquina virtual temos uma instalação completa do S.O. que queremos virtualizar, além de ter o próprio hardware virtualizado.

Se por exemplo eu precisar de uma biblioteca comum para todas as máquinas virtuais, preciso instalar em cada uma delas.

O Docker usa uma abordagem diferente, ele utiliza o conceito de container. Como assim [container](https://pt.wikipedia.org/wiki/Container_(transporte))?

## Compreendendo o conceito de containers
Se pensarmos em transporte de cargas, container foi uma revolução nessa área. Pois antes deles o tempo de carregar e descarregar um navio era gigantesco e o trabalho era feito manualmente. Sem contar perdas (devido a quebras ou deterioração), desvio e outros problemas.

Com a chegada dos containers foi possível transportar mercadorias de uma forma segura, de fácil manipulação e com pouco, ou nenhum, trabalho braçal no carregamento ou descarregamento. E é justamente isso que o Docker tenta fazer com nossos softwares.

## Ganhos ao usar containers do Docker
Imagine nosso software como uma mercadoria a ser transportar como por exemplo, do ambiente de Desenvolvimento para Produção.

Para fazer isso precisamos garantir que nosso ambiente de Produção tenha todos os pré-requisitos instalados, de preferência uma versão do S.O. parecida com a do ambiente de Desenvolvimento entre outros cuidados que devem ser tomados (relacionados a permissionamento, serviços dependentes e etc...).

Com o Docker temos um container com nosso software. Esse container é levado inteiro para o outro ambiente.

Com isso não precisamos nos preocupar com pré-requisitos instalados no outro ambiente, versão do S.O., permissionamento e se quisermos podemos ter containers para os serviços dependentes também. Dessa forma minimizamos muito a divergência entre os ambientes.

## Mas como o Docker faz isso?
Essa ideia de container já é bem antiga e a princípio o Docker usava internamente um projeto chamado [LXC](https://linuxcontainers.org/) (Linux Container).

O projeto LXC usa por baixo dos panos diversas funcionalidades presentes no Kernel do Linux. Abaixo vou listar algumas dessas funcionalidades:

- **chroot** - Reponsavel por mapear os diretórios do S.O. e criar o ponto de montagem (/, /etc, /dev, /proc entre outros).
- **cgroup** - Reponsável por controlar os recursos por processo. Com ele podemos por exemplo limitar o uso de memória e/ou processador para um processo específico.
- **kernel namespace** - Com ele podemos isolar processos, ponto de montagem entre outras coisas. Com esse isolamento, conseguimos a sensação de estar usando uma máquina diferente da máquina host. Pois enxergamos somente o ponto de montagem especifico e processos especificos, inclusive nossos processos começam com PID baixo.
- **kernel capabilities** - Entre outras coisas, conseguimos rodar alguns comandos de forma privilegiada.
## Mão na massa
Agora que temos uma noção do que é e para que serve o Docker, vamos fazer o download da ferramenta e começar nesse mundo de containers.

### Instalando o Docker
Atualmente Docker está disponível em duas versões [Docker Community Edition(CE)](https://www.docker.com/community-edition) e [Docker Enterprise Edition(EE)](https://www.docker.com/enterprise-edition).

Em ambas as versões temos acesso a toda a API, basicamente a diferença entre as duas versões é o perfil desejado de aplicações. No EE temos um ambiente homologado pela Docker com toda infraestrutura certificada, segura pensada para o mundo enterprise. Já na versão CE podemos chegar ao mesmo nível que EE porém de uma forma manual.

Nesse [link](https://www.docker.com/community-edition#/download) você pode encontrar as distribuições para downloads em cada sistema operacional disponível e os passos para instalação.

Feito a instalação, execute esse comando no terminal ```docker --version```. Se a instalação ocorreu com sucesso deve ser impresso algo semelhante a isso ```Docker version 17.03.1-ce, build c6d412e```.

### Imagens
O Docker trabalha com o conceito de images, ou seja, para colocar um container em funcionamento o Docker precisa ter a imagem no host.

Essas imagens podem ser baixadas de um repositório (a nomenclatura para esse repositório é registry) ou criadas localmentes e compiladas. Esse é o [link](https://hub.docker.com/) para o registry do Docker.

Nesse registry podemos ter imagens oficiais e não oficiais. Além de podermos criar nossas próprias imagens, também é possível fazer upload dela em um registry.

### Baixando Imagens
Para baixar uma imagem podemos usar o comando ```docker pull``` e o nome da imagem que queremos baixar. Vamos baixar a imagem do Ubuntu, para isso execute o seguinte comando no terminal: ```docker pull ubuntu```.

![](https://i.imgur.com/WYnaI8w.png)

Aqui o Docker baixou nossa imagem. Percebam que uma imagem é composta de várias camadas, por esse motivo teve que fazer vários Downloads/Pulls.

### Listando imagens baixadas

Para listar todas as imagens podemos usar o comando ```docker images```. O retorno desse comando é algo semelhante a isso:

![](https://i.imgur.com/YONOjnN.png)

O nome da imagem é exibido na coluna REPOSITORY, cada imagem tem um identificador único que é exibido na coluna IMAGE ID. A coluna TAG indica a "versão" da imagem do ubuntu. O latest quer dizer que é a última "versão" da imagem (a mais recente).

### Executando Containers

A partir da imagem podemos iniciar quantos containers quisermos através do comando ```docker run```.

Para acessarmos um terminal do Ubuntu podemos usar o comando ```docker run -i -t ubuntu``` ou ```docker run -it ubuntu```. O parâmetro -i indica que queremos um container interativo, o -t indica que queremos anexar o terminal virtual tty do container ao nosso host.

### Listando containers em execução

Para ver os containers em execução podemos usar o comando docker ps (em outro terminal ou aba), e ele exibirá um retorno parecido com esse:

![](https://i.imgur.com/Yx6tAix.png)

Aqui temos informações sobre os containers em execução, como id, imagem base, comando inicial, há quanto tempo foi criado, status, quais portas estão disponíveis e/ou mapeadas para acesso e o nome do mesmo. Quando não especificamos um nome ao iniciá-lo, será gerado um nome aleatóriamente.

Quando encerramos um container ele não será mais exibido na saida do comando docker ps, porém isso não significa que o container não existe mais. Para verificar os containers existentes que foram encerrados podemos usar o comando ```docker ps -a``` e teremos uma saída parecida com essa:

![](https://i.imgur.com/36TFes0.png)

Como o próprio status do container informa, o mesmo já saiu de execução e no nosso caso saiu com status 0 (ou seja saiu normalmente).

### Removendo containers
Para remover o container podemos usar o comando ```docker rm``` e informar o id do container ou o nome dele. Para nosso caso poderíamos executar o comando ```docker rm 43aac92b4c99``` ou ```docker rm dreamy_bassi``` para remover o container por completo.

Caso tenhamos a necessidade de remover todos os container (em execução ou encerrados) podemos usar o comando ```docker rm $(docker ps -qa)```. A opção -q do comando docker ps tem como saída somente os ids dos containers, essa lista de ids é passado para o docker rm e com isso será removido todos os containers.

Só será possível remover um container caso o mesmo não esteja em execução, do contrário temos que encerrar o container para removê-lo.

### Como são feitas as imagens?
Nesse momento podemos pensar que o Docker é meio mágico (e é...kkk). Dado uma imagem ele pode rodar um ou mais containers com pouco esforço, mas como são feitas as images?

Uma imagem pode ser criada a partir de um arquivo de definição chamado de Dockerfile, nesse arquivo usamos algumas diretivas para declarar o que teremos na nossa imagem. Por exemplo se olharmos a definição da imagem do Ubuntu podemos ver algo semelhante a isso:

```
FROM scratch ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz / . . . RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container

CMD \["/bin/bash"\]
```

Para ver o Dockerfile completo consulte [aqui](https://github.com/tianon/docker-brew-ubuntu-core/blob/1a5cb40f41ac4829d8c301ccd2cf3b7a13687a8b/xenial/Dockerfile).

Com um arquivo *Dockerfile* podemos compilá-lo com o comando ```docker build```. Ao compilar um arquivo Dockerfile temos uma imagem. Mas isso é um assunto para um próximo post.

Não deixe de conferir nosso curso de [docker](https://www.alura.com.br/curso-online-docker) na Alura.

Leia também:

[Criando um repositório local de imagens Docker](https://www.alura.com.br/artigos/criando-um-repositorio-local-de-imagens-docker)
[Docker Compose para compor uma aplicação](https://www.alura.com.br/artigos/compondo-uma-aplicacao-com-o-docker-compose)
[Criando volumes com Docker](https://www.alura.com.br/artigos/criando-volumes-com-docker)
[Replicando ambientes com Docker](https://www.alura.com.br/artigos/replicando-ambientes-com-docker)
[Desvendando o DockerFile](https://www.alura.com.br/artigos/desvendando-o-dockerfile)

### PODCAST [aqui](https://cursos.alura.com.br/hipsterstech-containers-e-docker-hipsters-75-a511) 

[ToC]






