Entendendo contêineres… escrevendo contêineres - Parte final

Igor Franca
Nerdzão/Nerdgirlz
Published in
5 min readDec 5, 2017

Já queria agradecer de antemão a você que acompanhou a matéria! Valeu mesmo e espero que curta esse final da nossa viagem de fim de semana pelo incrível mundo dos contêineres! :D Divirta-se e não se esqueça dos clapzinhos!

Vamos continuar a nossa aventura! Então apague a luz, pegue uma bebida e divirta-se!

…porque um contêiner tem que ser capaz de rodar stand-alone!

Ou seja, se ele depender tão crucialmente do meu sistema de arquivos, e eu rodar esse contêiner em um sistema de arquivos diferente, *boom!* Meu contêiner se torna falho.

Então! Acho que já fritamos neurônios o suficiente por hoje não? hahahaha, até o proximo artigo onde vamos isolar realmente os processos do contêiner dos do meu sistema operacional!

Até a próxima e se curtiu deixa seus clapzinhos pra que possamos compartilhar conhecimento também!

Okay, mas como resolver isso?

Simples! Precisamos dar pra ele um sistema de arquivos dele! Ou no nosso caso, pelo menos uma pasta chamada /proc, pra que ele consiga ver seus processos apenas.

Em contêineres Docker, quem é responsável por fazer isso é a própria engine, mondando uma especie de sanduíche entre a imagem que manipulamos realmente e o sistema hospedeiro, mais ou menos assim:

Créditos da Red Hat pela imagem 😃 (https://access.redhat.com/documentation/pt-br/red_hat_enterprise_linux/7/html-single/7.1_release_notes/#chap-Red_Hat_Enterprise_Linux-7.1_Release_Notes-Linux_Containers_with_Docker_Format)

O que são na verdade essas camadas?

Bom, são etapas de construção de um contêiner usável para nós devs na outra ponta. Na verdade, quando pedimos pra Docker Engine criar um contêiner novo para nós, seguindo X Dockerfile, ele primeiro cria um namespace, depois, cria uma mini imagem de um UNIX, (por padrão o Debian/BusyBox) para exatamente conceder um sistema de arquivos do contêiner, e depois adicionar novas layers que você pedir, como por exemplo o MySQL, ou para a Golang, e depois adiciona uma camada onde podemos “escrever” realmente, que é onde acessamos o interior do contêiner.

Portanto….

Se continuarmos a estudar a fundo, chegamos em camadas muito pesadas de um contêiner, por ele ser realmente uma lightweight virtual machine como muitos chamam. Então para entregarmos um sistema de arquivos inteiro pro nosso contêiner precisamos apenas dar um cpna raiz do nosso sistema e jogar dentro de uma pasta que escolhemos, isso pode demorar um pouco então se já terminou seu chá/bebida de acompanhamento, pegue mais haha :)

Para copiarmos de maneira eficiente, precisamos da permissão de sudorodando o comando sudo -s, esse comando vai permitir que nosso terminal use sempre as permissões de super user .

Agora podemos simplesmente criar uma pasta dentro da minha home, que vou chamar de rootfs, que seria correspondente a layer que disse do Debian em um Docker, e la dentro, apontar o destino do comando cp, assim temos o comando cp -ax / /home/rootfs, porém isso vai copiar tudo, inclusive permissões e links então pode demorar muito hahahahaha, porém depois que terminar teremos um contêiner com sistema de arquivos próprio!

inclusive permissões e links, portanto demora bastante, mas quando terminar nosso contêiner vai estar pronto para rodar, então se seu chá/bebida para acompanhar já terminou, é um bom tempo para pegar mais :),

Calma hahahaha

Depois de um tempo…

Pruentoo!

Pronto! Agora temos todas as pastas necessárias, então modificamos nosso código pra que ele use essa pasta em vez da comum do meu sistema!

Assim, nossa função child agora usa aquela pasta para o contêiner, e se novamente subirmos uma bash, e tentarmos listar os processos:

Agora alguma coisa definitivamente mudou! Agora realmente colocamos uma layer própria do contêiner, e ele vai utilizar tudo como se fose algo dele, e então temos apenas os processos dele, podendo assim realmente ver como um contêiner é construido!

Isso é o que a Docker Engine vai fazer com o ambiente de execução do seu programa, e acima disso ainda são adicionadas mais e mais camadas de segurança, porém, agora você sabe o que elas são realmente, na verdade são apenas syscall‘s que o contêiner impede seu programa de chamar! Não existe magia na Docker Engine, só existe um aglomerado de conhecimento de como os programas se comportam, para que possamos rodar ele em qualquer lugar!

Agradecimentos (Finalmente! hahaha 😃)

Open source é mais do que apenas código, é sobre pessoas.

Assim como Solomon Hykes disse na talk na OSCON de 2016, devemos sempre pensar em iniciativas open-source como iniciativas não só de código, mas de propósito, e mesmo a própria Docker Inc. ter seus segredos corporativos com a Docker engine, existe o Moby Project que pode ser uma grande fonte de pesquisa se você gosta da Golang, e se você gosta mais ainda de contêineres. Ele está cheio de ótimas pessoas, e grandes nomes na questão de infraestrutura, então usá-lo como fonte de pesquisa foi essencial. Então, pensando sobre como os contêineres do Docker, sua unidade principal inclusive, foram escritos, eu aprendi muito mais de como eles funcionam, e acreditem, namespaces já salvaram vocês que colocaram contêineres em produção muitas vezes!. Caso queira estudar mais sobre syscall‘s e coisas relacionadas a biblioteca de seccomp em Go, (a original é em C e C++, mas eles fizeram uma interface em Go só pra nós hehehehehe 😃) seguem alguns links de referência, e caso queiram ver na prática é só pedir nos comentários que eu faço uma explicação mais legal como um post aqui no Medium.

libseccomp em Go e C/C++:

Referencia de syscall‘s em sistemas Linux: (desculpa galera do Windows 😢):

Então, é só pegar uma xícara de chá/café/qualquer líquido agradável, e embarcar nessa aventura no incrível mundo de kernel 😆.

Queria também agradecer a você manooo! Muito obrigado mesmo e espero que tenha curtido nossa viagem por esse mundo maluco :D

--

--

Igor Franca
Nerdzão/Nerdgirlz

Node.js Witch Doctor and at the free time playing with security stuff :D