Sem delongas, vamos continuar nosso processo da parte 1 e manter um container em pé sem travar nosso Terminal.
A imagem escolhida para utilizarmos é do Ubuntu: git pull ubuntu e, é importante dizer que quando esse comando executa, pega a versão mais recente da imagem do Ubuntu no Docker Hub. Você poderia estipular uma versão específica utilizando essa sintaxe: docker pull ubuntu:21.04
Execute nossa imagem com docker run, mantendo o terminal interativo com a flag -it para executarmos comandos dentro do container e nomeando nosso container como lab utilizando a flag --name: docker run -it --name lab ubuntu
Pronto, se você rodar o comando ls, poderá ver uma estrutura de pastas.
Estamos executando um sistema Linux “enxuto” mas vamos fazer algo mais divertido do que listar diretórios, certo?
apt-get updateapt-get -y install sudoecho $USER e repare que é retornada uma string em brancosudo suecho $USER novamente e veja que a resposta é rootcowsay: sudo apt-get -y install cowsaycowsay MUUUUUUexit quantas vezes forem necessárias até seu Terminal voltar ao normalAgora vamos verificar se o container continua em pé com: docker ps
A resposta é sim, então vamos entrar novamente nele: docker exec -it lab bash
E se quisermos executar o comando cowsay temos somente que trocar nosso usuário com sudo su, pois nossas modificações foram mantidas.
Vamos parar o container com: docker stop lab
E a lista retornada do comando docker ps deve estar vazia.
Se quiser recomeçar o processo, é possível subir o container novamente com docker start lab
E repetir o ciclo com docker exec -it lab bash
Imagine cada pessoa desenvolvedora tendo que aplicar diversos comandos sobre uma imagem base para rodar um projeto. A margem de erro seria enorme e o tempo consumido também. Então eis que surge o Dockerfile.
O Dockerfile é um arquivo que comumente vai na raiz de nosso projeto e permite que construamos nossas próprias imagens e a utilizemos como base para os containers. Abaixo temos um exemplo de configuração:
FROM imagem # Imagem base que estamos utilizando
RUN comando # Comando bash
WORKDIR /app # Diretório "raíz" para os comandos a seguir
COPY . /app # Copia arquivos para dentro do container
VOLUME /app # Volumes exportos para fora do container
EXPOSE 3000 # Portas liberadas para fora do container
CMD ["comando", "parametros", …] # Comando que deve ser executado assim que um container sobe
Vamos reconstruir nossa imagem Ubuntu com suas dependências utilizando Dockerfile.
# imagem base
FROM ubuntu
# dependências
RUN apt-get update && apt-get -y install sudo && sudo apt-get -y install cowsay
# "cowsay" é instalado em /usr/games
ENV PATH $PATH:/usr/games
# as instruções passadas no comando 'docker run' serão executadas com bash
CMD /bin/bash
Agora vamos rodar o comando para criar a imagem: docker build -t lab_image .
Confirmar se a imagem foi criada: docker images | grep lab_image
E rodar a imagem: docker run --rm lab_image cowsay muuuu
O Docker tem um entrypoint padrão, que é: /bin/sh -c mas não tem um comando especificado.
Em outras palavras, o entrypoint especifica o comando que será executado sempre que o container iniciar e o CMD especifica os argumentos que serão passados para o entrypoint e, pelo menos um deles deve estar especificado no Dockerfile.
Quando você utiliza o comando docker run -i -t ubuntu bash, o entrypoint é o padrão, a imagem é a Ubuntu e o comando é bash.
Desse modo, o que realmente é executado é: /bin/sh -c bash.
O comando RUN cria uma camada nova no container (os container são feito de camadas read-only onde a ultima camada é read/write), por isso é bom concatenar o máximo de comando possível pro seu container ficar com menos camadas assim economizando espaço, ganhando performance.