Linux Dev ops

Docker – Introdução e gerenciamento de containers

Docker – Introdução e gerenciamento de containers

O Docker é uma ferramenta Open Source que utiliza a tecnologia de containers, mantida pela empresa Docker Inc. Ela é projetada para auxiliar desenvolvedores e administradores de sistemas, permitindo a criação, implantação e testes de aplicações de forma rápida, simples e utilizando poucos recursos.

Simplificando, ele é uma alternativa a virtualização, sendo mais ágil e menos pesada, pois ao invés de criar um sistema virtual completo, com todos os recursos de uma máquina física (Xen, VMWare, VirtualBox, etc), o Docker utiliza os mesmos recursos da máquina hospedeira, como: kernel, bibliotecas, etc…

O Docker foi baseado no LXC (Linux Containers), que são pacotes que permitem rodar diferentes sistemas isolados em um único sistema operacional real, utilizando o mínimo necessário para seu funcionamento. Sendo possível implantar e escalonar em qualquer ambiente, aumentando o desempenho e reduzindo o tamanho da aplicação.

Grandes empresas de tecnologia como Google, Amazon, Netflix, Spotify e até mesmo a Microsoft, vem utilizando essa tecnologia, substituindo a virtualização.

Comparando a utilização de máquinas virtuais e containers nos ambientes de produção, podemos definir que as máquinas virtuais simulam o hardware, enquanto os containers simulam o software, mas precisamente uma aplicação (wordpress, python, apache, postgresql, etc).

Benefícios:

  • Simplicidade no gerenciamento dos containers;
  • Reduz o número de sistemas necessários, pelo menor tamanho e sobrecarga;
  • Menor utilização de recursos (disco, memória e cpu) que uma virtualização completa;
  • Muitos programas já projetados para serem executados em containers;
  • Agilidade da criação e disponibilização de serviços e aplicativos;
  • Melhor rapidez na solução de problemas em diferentes ambientes;
  • Facilidade de backup e transferência de aplicações entre ambientes de desenvolvimento;

O Docker está disponível em 2 edições: CE (Community Edition) e EE (Enterprise Edition).

Docker CE: Plataforma grátis, ideal para iniciantes no Docker e para pequenos desenvolvedores;
Docker EE: Plataforma empresarial com assinatura e suporte, ideal para grandes empresas que desenvolvem aplicações críticas;

Instalando o Docker

O Docker pode ser instalado em diversos sistemas Linux como CentOS, Debian, Fedora e Ubuntu, também está disponível versões para Windows e MacOS. Para nossos exemplos utilizaremos o Debian 9. Podemos adicionar o repositório para a distribuição e usar os passos abaixo para fazer a instalação:

# apt -y install apt-transport-https curl gnupg2 software-properties-common
# curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian stretch stable"
# apt update && apt -y install docker-ce

Também podemos baixar a versão mais atual, diretamente da empresa que desenvolve o Docker (precisa do curl instalado). Desta forma funcionará em qualquer distribuição. Para isso, digitamos o seguinte comando:

# curl -fsSl https://get.docker.com | bash

Após a finalização do script, o Docker já está pronto para ser utilizado, podemos verificar a versão com o comando:

# docker ––version

Vamos utilizar o usuário root para gerenciar o Docker, caso esteja utilizando um usuário comum e não queira usar sudo para cada comando, pode adicionar o seu usuário ao grupo docker:

# sudo usermod -aG docker $(whoami)

O Docker adiciona uma interface Bridge (docker0) no host hospedeiro. É através desta interface, que os containers se comunicam e também é feita o redirecionamento de portas para acesso aos aplicativos.

# ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 64:32:a8:81:59:f2 brd ff:ff:ff:ff:ff:ff
    altname wlp0s20f3
    inet 192.168.68.108/24 brd 192.168.68.255 scope global dynamic noprefixroute wlo1
       valid_lft 69604sec preferred_lft 69604sec
    inet6 fe80::3da3:abe2:ab45:c3ef/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:07:9b:a3:aa brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:7ff:fe9b:a3aa/64 scope link 
       valid_lft forever preferred_lft forever

Trabalhando com imagens

O Docker possui um repositório com diversas imagens de aplicações, tanto as oficiais como criadas por usuários, permitindo o seu compartilhamento. Esse repositório é o Docker Hub, vamos precisar baixar localmente essas imagens para criarmos nossos containers. Abaixo temos alguns comando úteis na criação e manipulação de imagens:

Pesquisando imagens no Docker Hub

O comando docker search irá pesquisar na base de dados do Docker Hub:

# docker search debian

NAME                                               DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                                             Ubuntu is a Debian-based Linux operating sys…   11681     [OK]       
debian                                             Debian is a Linux distribution that's compos…   3699      [OK]       
arm32v7/debian                                     Debian is a Linux distribution that's compos…   70                   
itscaro/debian-ssh                                 debian:jessie                                   28                   [OK]

Fazendo download de uma imagem do Docker Hub

O comando “docker pull” irá preparar o download da imagem escolhida do Docker Hub, deixando disponível localmente:

# docker pull debian

Using default tag: latest
latest: Pulling from library/debian
6c33745f49b4: Pull complete 
Digest: sha256:22d4552b9f96fd0ea943cb846d58b069d4df297673636055a3d984b3ccac6a28
Status: Downloaded newer image for debian:latest
docker.io/library/debian:latest

Fazendo download de uma versão específica da imagem

Na criação de imagens podemos definir um versionamento, quando formos baixá-la basta especificar qual versão deseja através do parâmetro :<versão>. Abaixo um exemplo baixando a versão 5 do CentOS:

# docker pull centos:5

5: Pulling from library/centos
38892065247a: Pull complete 
Digest: sha256:70fffd687ff9545662c30f9043108489c698662861cd5f76070f7e2cd350564f
Status: Downloaded newer image for centos:5
docker.io/library/centos:5

Listando todas as imagens disponíveis

O comando docker images ls ou somente docker images lista as imagens disponíveis localmente, exibindo algumas informações importantes, são elas:

REPOSITORY: Nome definido para imagem.
TAG: Utilizado para versionamento da imagem.
IMAGE ID: Identificação da imagem no Docker.
CREATED: Tempo de criação da imagem.
SIZE: Tamanho que a imagem ocupa no disco.

# docker images ls

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
debian       latest    6d6b00c22231   3 weeks ago   114MB
java         11        51ab01914c65   7 weeks ago   255MB
centos       5         1ae98b2c895d   4 years ago   285MB

Exibindo mais detalhes da imagem

O comando docker image inspect ou somente docker inspect trás mais informações detalhadas relacionadas a imagem, como autor, variáveis de sistema, comando executado, entre outras:

# docker image inspect centos:5
# docker inspect centos:5

Alterando nome e versão de uma imagem

O comando docker image tag ou somente docker tag permite alterar o nome de uma imagem e a versão. Precisamos passar os parâmetros <image id> e <repository>:<versão>. O comando irá criar uma nova imagem baseada na original:

# docker image tag 1ae98b2c895d centos:5.4
# docker tag 1ae98b2c895d centos:5.4

ou

# docker image tag centos:5.4 novonome:1.0
# docker tag centos:5.4 novonome:1.0

Removendo uma imagem

O comando docker image rm ou somente docker rmi remove uma imagem baixada anteriormente. Precisamos passar como parâmetro repository ou image id:

# docker image rm 6d83de432e98
# docker rmi 6d83de432e98

Caso a imagem esteja associada a outra, ou exista um container que é baseado nela, será preciso utilizar o parâmetro -f para forçar a remoção:

# docker image rm -f 1ae98b2c895d
# docker rmi -f 1ae98b2c895d

Untagged: centos:5
Untagged: centos@sha256:70fffd687ff9545662c30f9043108489c698662861cd5f76070f7e2cd350564f
Deleted: sha256:1ae98b2c895d1ceeba8913ff79f422f005b7f967a311da520a88ac89180b4c39
Deleted: sha256:5513565ec546b4249cb76fec6551253c611d6ee80184807324c5c4335e4a2964

Fazendo backup de uma imagem para um arquivo tar

O comando docker image save ou somente docker save salva a imagem no disco com o formato tar. Precisamos passar como parâmetro repository ou image id, e também o caminho -o </caminho/arquivo.tar>:

# docker image save debian -o ~/debian.tar
# docker save debian -o ~/debian.tar

# ls -lh ~
total 134M
-rw-------  1 cesar cesar 114M jan  2 18:32  debian.tar

Restaurando backup a partir de um arquivo tar

O comando docker image load ou somente docker load carrega o arquivo para as imagens do Docker. Precisamos passar o parâmetro -i </caminho/arquivo.tar>:

# docker image load -i ~/debian.tar
# docker load -i ~/debian.tar

Trabalhando com containers

Para começarmos a trabalhar com containers vamos utilizar o comando “docker run”. Para iniciar, vamos utilizar a imagem hello-world do repositório do Docker Hub, que trará uma mensagem de Hello e algumas informações. Caso a imagem não exista localmente, ele irá baixá-la:

# docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete 
Digest: sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Criando um container e executando um comando

# docker run debian /bin/echo "Bem-vindo ao Docker"
Bem-vindo ao Docker

Criando um container e conectando ao console

Para podermos criar um container acessando o console, temos que passar os parâmetros -t (terminal) e -i (interatividade) junto com o comando docker run.

# docker run -it centos

Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
7a0437f04f83: Pull complete 
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
[root@76edfe69d86a /]#

Após criar o container já iremos cair direto no console, podemos ver que o usuário padrão é root e o nome do host é o container id.

Ao sair do console com exit, o container será finalizado. Para que ele continue executando, saia do console com CTRL + P, CTRL + Q, assim ele continuará em segundo plano.

Visualizando os containers em execução

O comando docker container ls ou somente docker ps lista os containers que estão em execução, exibindo algumas informações, são elas:

CONTAINER ID: Identificação do container no docker.
IMAGE: Imagem utilizada na criação do container.
COMMAND: Comando executado dentro do container.
CREATED: Tempo de criação do container.
STATUS: Status atual do container (Execução, pausado, etc).
PORTS: Portas utilizadas no container e se tem direcionamento de porta com o host hospedeiro.
NAMES: Nome do container (quando não é definido um nome o docker seleciona um aleatório).

# docker container ls

CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS          PORTS     NAMES
76edfe69d86a   centos    "/bin/bash"   About a minute ago   Up 56 seconds             sad_bose

ou

# docker ps

CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS          PORTS     NAMES
76edfe69d86a   centos    "/bin/bash"   About a minute ago   Up 56 seconds             sad_bose

Definindo um nome na criação do container

O parâmetro --name é utilizado para definir um nome para o container:

# docker container run -ti --name teste debian

# docker ps

CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
b4458c3a9806   debian    "bash"    8 seconds ago   Up 8 seconds             teste

Criando container sem iniciá-lo

O comando docker container create ou somente docker create cria um container sem iniciá-lo:

# docker create --name ubu ubuntu

b70a310eb6dbf840864df3afca26b0e09720ecdac7debda695657bd4218a0fcd

ou

# docker container create --name ubu ubuntu

b70a310eb6dbf840864df3afca26b0e09720ecdac7debda695657bd4218a0fcd

Visualizando todos  os containers criados

Durante a manipulação dos containers, vários são criados e finalizamos, mas não excluídos. Para visualizá-los execute o comando docker container ls com o parâmetro -a:

# docker container ls -a

ou

# docker ps -a

CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS                       PORTS     NAMES
b70a310eb6db   ubuntu         "/bin/bash"              About a minute ago   Created                                ubu
b4458c3a9806   debian         "bash"                   4 minutes ago        Exited (130) 3 minutes ago             teste
45db32663556   debian         "bash"                   4 minutes ago        Exited (130) 4 minutes ago             blissful_feistel
76edfe69d86a   centos         "/bin/bash"              7 minutes ago        Exited (0) 4 minutes ago               sad_bose
d5e46c091716   debian         "/bin/echo 'Bem-vind…"   8 minutes ago        Exited (0) 8 minutes ago               distracted_galileo
8154bcf02123   hello-world    "/hello"                 9 minutes ago        Exited (0) 9 minutes ago               condescending_ellis
7cfe02e2ab06   java:11        "sh"                     7 weeks ago          Exited (137) 7 weeks ago               frosty_torvalds
67a99cc3d75b   java:11        "sh"                     7 weeks ago          Exited (0) 7 weeks ago                 strange_dirac
ca44ee5edcab   994d899f58bf   "sh"                     7 weeks ago          Exited (0) 7 weeks ago                 tender_matsumoto

Removendo containers que não estão em execução

O comando docker container prune irá remover todos os containers que estão parados. Cuidado!!! Será solicitado confirmação e ao confirmar, não conseguirá desfazer o processo:

# docker container prune

WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
b70a310eb6dbf840864df3afca26b0e09720ecdac7debda695657bd4218a0fcd
b4458c3a9806de465faf08a0175b46f467a753783593e3ec53d28e6f65e683cf
45db32663556587d107d490cd7a0c67d1447947458af003c810e64a682560cf3
76edfe69d86ad3078b5cfc914034d0d3eecec5d50e34f5299426c54d34edf6a3
d5e46c0917164931f433e0009afd1611ac5280d0ff5fa7b33662aecea2a3e891
8154bcf02123e4c21444accdf81a1c19d95e37976cecf0ca9753f937f07045eb
7cfe02e2ab060a50c1a2906add4790d731a2f44454607498c67763baf53cfce6
67a99cc3d75b1560cf445395e34e05525adbc8858736ca31d4977a86fb316054
ca44ee5edcab9144a845501ec504ce04d158cab927a8d5863fa6b002d2fb4ccf

Total reclaimed space: 32B

Criando containers auto destrutivos

Podemos utilizar o parâmetro --rm, para criar containers que serão destruídos ao sairmos da sessão:

# docker run --rm -it ––name testando debian

Iniciar um container que está parado

O comando docker container start ou somente docker start inicia um container parado. Precisamos passar como parâmetro o <nome> ou o <container id>:

# docker container start teste
# docker start f162d3a30804

Parando um container ativo

O comando docker container stop ou somente docker stop  interrompe um container ativo. Precisamos passar como parâmetro o <nome> ou <container id>:

# docker container stop 8a6c279623fb
# docker stop suspicious_jepsen

Pausando um container que está em execução

O comando docker container pause ou somente docker pause interromper temporariamente um container. Precisamos passar como parâmetro o ou o :

# docker container pause teste

ou

# docker pause c07c68aa29f7

# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED              STATUS                   PORTS     NAMES
c07c68aa29f7   debian    "bash"    About a minute ago   Up 29 seconds (Paused)             teste

Tirando a pausa do container

O comando docker container unpause ou somente docker unpause retira a pausa do container. Precisamos passar como parâmetro o <nome> ou o <container id>:

# docker container unpause teste

ou

# docker unpause c07c68aa29f7
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
c07c68aa29f7   debian    "bash"    4 minutes ago   Up 3 minutes             teste

Executa um comando num container ativo

O comando docker container exec ou somente docker exec executa comandos dentro de um container em execução. Precisamos passar como parâmetro o <nome> ou o <container id>, seguido do comando desejado:

# docker container exec teste apt update && apt -y install apache2

ou

# docker exec teste apt update && apt -y install apache2

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://security.debian.org/debian-security buster/updates InRelease
Hit:2 http://deb.debian.org/debian buster InRelease
Hit:3 http://deb.debian.org/debian buster-updates InRelease
Reading package lists...
Building dependency tree...
Reading state information...
...

Salvando alterações do container numa imagem

Após criar um container e instalar programas, mudar configurações, você pode querer replicar estas alterações em outros containers, assim, precisamos salvar estas alterações como uma imagem. Para isso, utilizamos o comando docker commit e passamos como parâmetros o <container> e depois o <novo repository>:

# docker commit webapp nginx-webapp

Conectando no console de um containers em execução

O comando docker container attach ou somente docker attach é utilizado para acessar o console de um container que está em execução em segundo plano. Precisamos passar como parâmetro o <nome> ou <container id>:

# docker container attach teste

ou

# docker attach c07c68aa29f7

root@c07c68aa29f7:/# 

Removendo um container

O comando docker container rm ou docker rm é utilizado para remover um container. Precisamos passar como parâmetro o <nome> ou <container id>:

# docker container rm c07c68aa29f7

ou

# docker rm c07c68aa29f7

Error response from daemon: You cannot remove a running container c07c68aa29f7ca919a0bb9e69be762fc99169fad58682563ba87c5dd389569eb. Stop the container before attempting removal or force remove

Caso o container esteja em execução, será preciso utilizar a opção -f para forçar:

# docker container rm -f c07c68aa29f7

ou

# docker rm -f c07c68aa29f7

c07c68aa29f7

Criando container em background

Para deixar um container em background, precisamos passar o parâmetro -d na criação do container. Entretanto, para que funcione corretamente, o container precisa de um aplicativo rodando, por exemplo um servidor web:

# docker container run -d --name web httpd

2f42ceb3af7b0aa3f77d2996975f99c940e8001a4db87b077c660186314bea52

# docker ps

CONTAINER ID   IMAGE     COMMAND              CREATED              STATUS              PORTS     NAMES
5019c5b80b5d   httpd     "httpd-foreground"   2 seconds ago        Up 2 seconds        80/tcp    web

Definir que um container fique sempre ativo

Para que um container fique sempre em execução, mesmo quando o host hospedeiro for reiniciado, utilizamos o parâmetro --restart=always:

# docker run -d --restart=always --name webserver httpd

82b8673bc16cc2ef6ab726c66f4a376335e02e82aee6676e8bf01e764998e322

Trabalhando com volumes

Quando trabalhamos com containers de aplicativos, precisamos que os usuários acrescentem arquivos aos projetos que estão trabalhando (ex. webserver), mas o ideal é não dar acesso direto via ssh nesse container, então, podemos adicionar volumes que são acessados pelo host hospedeiro. Abaixo temos alguns exemplos de utilização:

Definindo um volume na criação de um container

Para definir um volume utilizamos o parâmetro -v seguido do <nome do volume>. O container acrescentará a partição mapeada /volume ao sistema de arquivos do container. Os volumes geralmente ficam na pasta /var/lib/docker/volumes.

# docker run -ti -v /volume ––name files ubuntu

Mapeando volume na criação de um container

Podemos especificar um diretório que servirá de volume para o container, usando a opção -v <dir no host>:<volume no container>:

# mkdir -p ~/volumes/www
# echo 'echo $(hostname)' > ~/volume/data/host.sh
# docker run -d -v ~/volume/www:/usr/local/apache2/htdocs/ --name www httpd

Criando um container de volume (data-only)

Podemos criar um container que tem como objetivo servir como um volume que poderá ser compartilhado entre os outros containers. Ele é um container que não fica em execução, abaixo temos um exemplo:

# mkdir -p ~/volume/data
# docker create -v ~/volume/data:/data --name dados centos:6

Compartilhando volume entre containers

Criaremos dois containers que irão mapear o nosso container de volume criado anteriormente (dados), para testar se ambos acessam o mesmo volume, iremos criar um script para exibir o hostname (container id) de cada um deles. Execute os comandos abaixo:

# echo 'echo $(hostname)' > ~/volume/data/host.sh

# docker run -d --name ubuntu --volumes-from dados ubuntu bash -c "while true; do sleep 1; done"
d779c53d78011306e1d2e6bc7767a13306791c9b06570912325f8d221b6ca03a

# docker run -d --name centos --volumes-from dados centos bash -c "while true; do sleep 1; done"
82868f52eb05295a1bdaaea70134792abd939d146faf4558831b360781a87465

# docker ps -a

CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS     NAMES
82868f52eb05   centos     "bash -c 'while true…"   9 seconds ago    Up 8 seconds              centos
d779c53d7801   ubuntu     "bash -c 'while true…"   17 seconds ago   Up 16 seconds             ubuntu
e545b3cb8cea   centos:6   "/bin/bash"              54 seconds ago   Created                   dados

# docker exec ubuntu sh /data/host.sh
d779c53d7801

# docker exec centos sh /data/host.sh
82868f52eb05

Para mais informações sobre Docker e Containers, veja as referências utilizadas abaixo:

Referências:

https://docs.docker.com
https://linuxcontainers.org
https://www.howtoforge.com/tutorial/how-to-use-docker-introduction
https://www.server-world.info/en/note?os=Debian_9&p=docker&f=1
https://youtube.com/user/linuxtipscanal

comments powered by Disqus

Assine nossa Newsletter! 🐧

Se una com os assinantes de nossa Newsletter, sempre que tiver postagem nova você será notificado.