Entendendo contêineres… escrevendo contêineres - Parte 1
Todos os dias em novas (ou não!) equipes de desenvolvimento batemos no conceito de contêineres, porém, o que realmente você está fazendo com seu projeto ao “contêineriza-lo”?.
Essa é uma série de três artigos! Nesse primeiro vamos escutar argumentos da linha de comando, e construir algo para isolar o processo que nosso contêiner deve executar! :D
Porém o que realmente é um contêiner?
Será essa caixa azul de metal super famosa em filmes de ação o mesmo contêiner que estamos falando aqui? Não literalmente, porém se analisarmos sua estrutura, podemos ver que ele consiste basicamente em paredes que isolam o meio interno do externo e fazendo com que o único meio de comunicação seja suas portas. Traçando um paralelo, suas portas são exatamente essas ligações tanto com portas de acesso via protocolo TCP/IP, (a maneira mais comum de usarmos, expondo portas lógicas do contêiner para uma porta física, como a 8080.) e também temos os namespaces responsáveis exatamente por isolar a execução do seu programa do que chamamos de rootOs ou sistema hospedeiro, que na prática é quem realmente “roda” o Docker e sua engine para controlar os contêineres. E assim nos aproximamos da definição da própria Docker, Inc.
A container image is a lightweight, stand-alone, executable package of a piece of software that includes everything needed to run it: code, runtime, system tools, system libraries, settings.
Fonte: https://www.docker.com/what-container
Então..
Parte desse trabalho como as bibliotecas do sistema, sistema de arquivos (ou rootfs) e outras funcionalidades, são servidas pelo sistema hospedeiro, portanto, para rodar esse tutorial, você precisa de uma VM ou sistema operacional Mint (adquira uma no https://linuxmint.com/download.php), no meu caso, Linux Mint versão 18.02, com arquitetura x64 de um I7.
E sobre a versão do Go estou usando a versão 1.9.2 da linguagem adquirida no site da Golang.
Após essa “breve” (sqn) introdução, vamos sujar as mãos…
Vou partir do principio que o tutorial do site da Golang te ajudou a setar seu ambiente, e já está pronto para rodar qualquer código Go sem problemas, porém se tiver duvidas você pode seguir o tutorial do site do Go! -> https://golang.org/doc/install 😃 ou deixar sua duvida no artigo!
Em um diretório vazio, inicie um arquivo novo, chamado main.go, e dentro só declare o pacote main, e a função, como abaixo:
Então até aqui temos apenas como começar um programa em Go, portanto, vamos importar algumas libs, só para deixar nossos editores afiados:D.
Então ficamos com:
O primeiro pacote, fmt, é apenas para interação e impressão de strings no console. O segundo, o os
, é para interagirmos com os comandos passados via terminal para o programa, assim poderemos escutar comandos como argumentos. De dentro do pacote os, importamos exec para executarmos comandos direto pro kernel, podendo acionar processos filhos e/ou gerenciar processos filhos que criamos. O ultimo pacote o syscall
é responsável por deixar a gente acessar o kernel direto com syscall’s para podermos usar alguns recursos legais.
Assim, vamos escutar o primeiro argumento depois do comando comum de iniciarmos um programa em Go, que seria go run main.go
e nossos argumentos, que vamos adicionando depois.
Depois de obtermos o primeiro argumento vamos definir a funçãorun
que vai imprimir o comando que mandamos e rodar em um processo separado.
Também definimos uma função simples pra não precisar repetir o mesmo código diversas vezes, para que caso aconteça algo, possamos receber a exception no console.
Só tem um problema no nosso código, mesmo rodando comando simples, como um echo no nosso “contêiner”, ele ainda pode escrever no sistema hospedeiro, ou seja, se eu sobrescrever o hostname, por exemplo, mesmo fora do contêiner, eu terei alterado.
Como podemos ver, quando eu rodei o comando que iniciaria uma bash no meu Linux, eu iniciei ela dentro do nosso “contêiner”, porém, de dentro do contêiner o processo não pode de jeito nenhum alterar nada no sistema hospedeiro, pois ele tem que ser isolável o suficiente para que possamos rodar processos “agressivos” dentro de um contêiner sem que ele altere nada na minha máquina.
Assim, com literalmente esse código, temos o básico de um contêiner, para rodar qualquer coisa.
Porém para que ele não altere nada no sistema hospedeiro, se tornando assim realmente stand-alone, podemos usar algumas flags de cópia.
Mas deixaremos isso pro próximo artigo!
Muito obrigado e deixa seus clapzinhos se curtiu! :D