Desenvolvimento

19 nov, 2015

Moby Docker – a fera da virtualização

Publicidade

Quando li sobre Docker e containers pela primeira vez, meu pensamento foi “ah… outra forma de ter uma VM”. Eu não sabia das facilidades que isso geraria no meu dia a dia de trabalho em relação aos outros métodos de virtualização.

Docker, ao contrário de outras formas de virtualização, não é um sistema isolado no qual se carrega um sistema operacional inteiro. Por exemplo, em KVM/Qemu ou KVM/Xen, é possível instalar Windows, Android ou FreeBSD, pois é um sistema completo de virtualização, que emula até uma camada de BIOS. Já em containers, como o Docker, não. Eu não consigo rodar outro sistema que não seja aquele que roda na minha máquina em termos de versão de kernel e libc. Então enquanto Qemu e Xen rodam em servidores com Linux ou FreeBSD, Docker é inerente somente ao Linux.

containers_vs_virtualization

A parte de containers é relativamente nova no Linux. Ela já existe faz uns 10 anos no FreeBSD com jails e mais ainda em Solaris com o zoneadm. Depois que implementaram o cgroups no kernel que o Linux começou a explorar essa possibilidade. Os primeiros containers que surgiram no Linux foram via LXC, que criava um segundo ambiente dentro do seu. Em FreeBSD e Solaris, containers significam compartilhar seu sistema em vários pequenos sistemas, o que faz sentido afinal, mas em Linux… Linux é um kernel. Dizemos Linux por simplicidade, mas o sistema operacional que inclui kernel, Linux e aplicativos, GNU por exemplo, é o que chamamos de distro. Ubuntu é um sistema operacional, RedHat é outro sistema operacional, Debian outro, e assim por diante. Então eles não rodam com as mesmas bibliotecas, nem usam o mesmos sistemas de pacotes. E isso é um problema. Os containers em LXC são capazes de criar um ambiente baseado no que está rodando, mas não uma outra distro dentro dessa distro original.

Nesse ambiente de possibilidades, surgiu o Docker. Ele permite rodar um container que tenha outra distro completamente diferente daquela que roda no sistema principal. Mais ainda: Docker tem um repositório no estilo do GitHub que permite carregar ou baixar máquinas virtuais criadas por outras pessoas.

Então, basta instalar Docker para começar a brincar. Apesar de ter servidores Debian, eu rodo bastante Docker no meu laptop. Então sei o procedimento pra Ubuntu via ppa, mas acredito que Debian deve ser bem parecido. Outras distros não devem ser muito diferentes.

Instalando Docker no Ubuntu

Adicione diretamente o repositório nas configurações de fontes do apt:

root@laptop:~# cat << EOF > /etc/apt/sources.list.d/docker.list
deb https://get.docker.io/ubuntu docker main
EOF

Depois atualize a listagem de pacotes disponíveis e instale docker.io.

root@laptop:~# apt-get update; apt-get install docker.io

Então é preciso adicionar seu usuário ao grupo docker pra poder rodar sem precisar usar “sudo”:

root@laptop:~# usermod -a -G docker helio

Reiniciada sua sessão (não precisa rebootar), o Docker deve estar disponível pra uso.

Docker – primeiros passos

Com o Docker é possível verificar quais imagens estão disponíveis pra uso no repositório público.

helio@laptop:~$ docker search centos
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                          The official build of CentOS.                   1575      [OK]       
ansible/centos7-ansible         Ansible on Centos7                              60                   [OK]
jdeathe/centos-ssh-apache-php   CentOS-6 6.6 x86_64 / Apache / PHP / PHP m...   11                   [OK]
blalor/centos                   Bare-bones base CentOS 6.5 image                9                    [OK]
jdeathe/centos-ssh              CentOS-6 6.6 x86_64 / EPEL/IUS Repos / Ope...   8                    [OK]
torusware/speedus-centos        Always updated official CentOS docker imag...   7                    [OK]
million12/centos-supervisor     Base CentOS-7 with supervisord launcher, h...   7                    [OK]
nimmis/java-centos              This is docker images of CentOS 7 with dif...   6                    [OK]
feduxorg/centos                                                                 3                    [OK]
nathonfowlie/centos-jre         Latest CentOS image with the JRE pre-insta...   3                    [OK]
centos/mariadb55-centos7                                                        2                    [OK]
tcnksm/centos-node              Dockerfile for CentOS packaging node            2                    [OK]
nathonfowlie/centos-jira        JIRA running on the latest version of CentOS    1                    [OK]
feduxorg/centos-postgresql      Centos Image with postgres                      1                    [OK]
lighthopper/orientdb-centos     A Dockerfile for creating an OrientDB imag...   1                    [OK]
yajo/centos-epel                CentOS with EPEL and fully updated              1                    [OK]
layerworx/centos                CentOS container with etcd, etcdctl, confd...   1                    [OK]
feduxorg/centos-apache          Run Apache Event MPM on Centos                  1                    [OK]
blacklabelops/centos            Blacklabelops Centos 7.1.503 base image wi...   0                    [OK]
feduxorg/centos-rack            Centos to run rack applications like Ruby ...   0                    [OK]
jsmigel/centos-epel             Docker base image of CentOS w/ EPEL installed   0                    [OK]
lighthopper/openjdk-centos      A Dockerfile for creating an OpenJDK image...   0                    [OK]
jasonish/centos-suricata        Suricata base image based on CentOS 7.          0                    [OK]
pdericson/centos                Docker image for CentOS                         0                    [OK]
feduxorg/centos-geminabox       Gem in a box on centos                          0                    [OK]

É possível adicionar outros repositórios e, claro, fazer sua própria instalação. Um problema sobre esse repositório público é que não existe garantia de não ter um malware junto. Se o seu uso for como o meu, corporativo, não use. Se for pra brincar e testar, vale o tempo.

A beleza do Docker é que, pra rodar, basta chamar o comando. Se o container não existe, ele busca imediatamente no repositório e roda.

helio@laptop:~$ docker run -it centos bash
Unable to find image 'centos:latest' locally
latest: Pulling from centos
47d44cb6f252: Pull complete 
168a69b62202: Pull complete 
812e9d9d677f: Pull complete 
4234bfdd88f8: Pull complete 
ce20c473cd8a: Pull complete 
centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:3aaab9f1297db9b013063c781cfe901e2aa6e7e334c1d1f4df12f25ce356f2e5
Status: Downloaded newer image for centos:latest
[root@1512dcd70309 /]# hostname 
1512dcd70309

Então, em outro terminal é possível ver a instância de Docker ativa.

helio@laptop:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1512dcd70309        centos:latest       "bash"              2 minutes ago       Up 2 minutes                            jolly_sinoussi

A cada nova chamada pra rodar Docker, uma nova instância é criada.

helio@laptop:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3b48633e67cc        centos:latest       "bash"              8 seconds ago       Up 6 seconds                            romantic_turing     
1512dcd70309        centos:latest       "bash"              4 minutes ago       Up 4 minutes                            jolly_sinoussi

Como se deve imaginar, cada instância de Docker é completamente diferente uma da outra. E não persistente. Uma vez terminada a sessão, os dados adicionados são removidos. Assim, se aplicar um upgrade ao container e quiser manter, tem que criar um “snapshot” dele. Então, pra salvar uma atualização no container:

[root@1512dcd70309 /]# yum update
Loaded plugins: fastestmirror
base                                                                                                                                              | 3.6 kB  00:00:00     
extras                                                                                                                                            | 3.4 kB  00:00:00     
systemdcontainer                                                                                                                                  | 2.9 kB  00:00:00     
updates                                                                                                                                           | 3.4 kB  00:00:00     
(1/5): base/7/x86_64/group_gz                                                                                                                     | 154 kB  00:00:00     
[... várias coisas seguem...]

é preciso fazer:

helio@laptop:~$ docker commit -m "Atualizado com yum update" 1512dcd70309 centos-atualizado
ff0f333c4abd4d9045ff074121df8fea7d109e87cc1dcb88317254fa0cfd66e4

É preciso usar o ID do container, uma vez que várias instâncias podem existir originadas da mesma imagem “centos”. Pra verificar suas imagens de containers, basta usar:

helio@laptop:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos-atualizado   latest              ff0f333c4abd        40 seconds ago      269.9 MB
fedora2             latest              d97facef5329        31 minutes ago      398.7 MB
fedora              latest              c7d2f0130dae        5 days ago          204.3 MB
centos              latest              ce20c473cd8a        3 weeks ago         172.3 MB
susebuilder4        latest              97c67ab3589f        4 weeks ago         882.1 MB
susebuilder3        latest              15af476bea7b        4 weeks ago         784.6 MB
susebuilder2        latest              299ff2fa953d        4 weeks ago         685.6 MB
susebuilder         latest              9ca4e4487b77        4 weeks ago         661.3 MB
kiwi                latest              a037d86af491        12 weeks ago        436.7 MB
aekeroth/synapse    latest              a56b155c49a4        5 months ago        450.4 MB

Pra remover algumas dessas imagens, como aekeroth/synapse que nem lembro o motivo de estar ali, onde todos os “snapshots” relacionados serão removidos também, use:

helio@laptop:~$ docker rmi aekeroth/synapse
Untagged: aekeroth/synapse:latest
Deleted: a56b155c49a427661055b1a45c9233107b59fc6ec801467f04a29659a8330624
Deleted: b1c70ec40fcc659efd9da36beade75b8c2505c56c53499b231be692e29330d15
Deleted: 051d6978b0a8d3f344c0b6fdbdcae3e172f8e24c839d3969e118f2e6c1c64174
Deleted: b856d151b9c77a47d3d706e64880f898939afeb8312727a8fb5d715ef64ccf86
Deleted: c908ae302de39cb78669241ab2a65dfa1c750eb7f0818820286551bc450b5b0d
Deleted: 8927bb4878535574411efe47e5006049662fffa3f8984288b00ea49436fe5caf
Deleted: a055b38089a89db6f97c4bef2de139ebe06fd56976a87ef442ce6a9f5047497d
Deleted: 1057eb355528fc473af4bb6e9f529fdd70d7b8b02b764bf873166d7650341bd0
Deleted: 7bfe65031a48db2cc6206d6b4af9e52063a7d538a8e3d13b2f6e4f5d888e0f08
Deleted: cec2959569e4d51aee4bcc0409cebfc4a0a46b9d42142e4611c0fe6294824a8b
Deleted: ed5b1f07a6c393d55598770da45ec197be4682bfedabdf26bbab0208d5b7061a
Deleted: 2103b00b3fdf1d26a86aded36ae73c1c425def0f779a6e69073b3b77377df348
Deleted: 4faa69f72743ce3a18508e840ff84598952fc05bd1de5fd54c6bc0f8ca835884
Deleted: 76b658ecb5644a4aca23b35de695803ad2e223da087d4f8015016021bd970169
Deleted: f0dde87450ec8236a64aebd3e8b499fe2772fca5e837ecbfa97bd8ae380c605e
Deleted: 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158

Moby Docker, o monstro mítico dos mares das nuvens

Depois dessa rápida introdução ao Docker e containers, fica a pergunta: cadê a tal vantagem? Pois precisei fazer uso dela recentemente por causa do LSB, Linux Standard Base.

Quando ouvi falar de LSB, achei que era algo como padronização de diretórios como “/opt” e “/usr/local”, além de localização de arquivos de inicialização em “/etc/init.d”. É, mas não é só isso. LSB cria uma base comum pra se compilar um binário em uma distro e rodar em outra. Isso evita precisar ter ambientes diferentes com distros diferentes e versões dessas distros diferentes. É uma facilidade. Mas… Debian e, consequentemente Ubuntu, não seguem mais a LSB. Primeiro, porque é algo complicado, pois envolve verificação de compatibilidade de ABI; segundo, porque se não tem um interesse econômico – leia-se alguém pra pagar por isso, então não vale a pena manter.

Como na empresa desenvolvemos binários pra RedHat e Suse, meu laptop se tornou um local inóspito pra compilar os binários que usamos. São de OpenSAF, um projeto de software livre, mas é complicado manter um ambiente de compilação pra cada sistema. E caro. A solução inicial que adotamos foi instalar servidores com as versões de RedHat e Suse pra podermos compilar e verificar.

Daí me lembrei do Docker 🙂

Bastou criar um container com os pacotes de compilação necessários como gcc, g++ e rpmbuild. Mas o repositório está no laptop, que roda Ubuntu. Como compilar? Como acessar os dados?

Primeiramente, criei um usuário no container Docker com mesmo UID e GID que o meu, pra não criar tudo como root. Em seguida, chamei o Docker com parâmetros pra usar meu filesystem:

helio@laptop:~$ docker run -it -v /home/helio/OpenSAF:/opensaf --user=helio -w /opensaf susebuilder4 ./configure

e pronto!  Binários compilados num ambiente que suporta LSB. Docker mapeia meu diretório local “/home/helio/OpenSAF” como “/opensaf” no container. Inicia como usuário “helio” dentro do diretório “/opensaf” e roda o comando “./configure”. E pronto. Quando termina o comando, o container desaparece.

Sim, saem lágrimas dos olhos de tão lindo.

Docker permite isso. Imagine então rodar um ambiente virtual com servidor web ou qualquer outra aplicação. Uma vez terminada, some o container. Quer aumentar capacidade? Só criar outro container. Eu não comentei muito, mas é possível mapear portas locais pra portas internas do container, além de rodar o próprio como daemon.

Docker é um monstro de tão bom. Não é uma baleia, mas um Moby Docker! Vale testar.