DEV Community

Cover image for Abrindo mares: Dockerfile, o que precisamos saber!
Rafael Pazini
Rafael Pazini

Posted on

Abrindo mares: Dockerfile, o que precisamos saber!

Para pensar sobre o que são os Dockerfiles e o que fazemos com eles é bom ter em mente que sempre estamos lidando com containers. Containers são criados a partir de imagens e imagens são criadas usando os famosos Dockerfiles.

Dockerfiles são arquivos de texto onde colocamos algumas sequências de comandos para gerar nossa imagem da aplicação.

É importante lembrar da palavra SEQUÊNCIA pois é exatamente isso que vamos fazer em um Dockerfile: escrever uma sequência de comandos para serem executados. Podemos até chamar de "receita de bolo" para criar uma imagem de nosso app.

Mas temos que ficar atentos a algumas regras básicas para escrever essa nossa receita.

Formato

A estrutura de um Dockerfile é bem parecida com um yaml mas com algumas particularidades.

Este é um exemplo de formatação de um Dockerfile:

# Comentário
INTRUÇÃO argumento
Enter fullscreen mode Exit fullscreen mode

A convenção para a escrita de Dockerfile é: Escrever as instruções em LETRA MAIÚSCULA para facilitar a separação do que é uma instrução e o que é um argumento.

Segue um exemplo de como é um Dockerfile real, que no caso executa o build de um app Go.

FROM golang:1.20-alpine

COPY go.* ./
RUN go mod download && go mod verify

COPY . ./
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/main.go

EXPOSE 8080

CMD["/app/server"]
Enter fullscreen mode Exit fullscreen mode

Primeiro e com letras maiúsculas vem os comandos para o Docker entender o que queremos fazer. Logo após vem os argumentos que compõe os comandos.

Comandos mais utilizados

FROM

Onde escolhemos a nova Base Image e dizemos para o Docker que estamos iniciando um novo build. Por exemplo, no exemplo acima, estamos usando a golang:1.20-alpine como Base Image pois estamos criando um app Go.

FROM golang:1.20-alpine
Enter fullscreen mode Exit fullscreen mode

“Poxa Rafa, mas onde eu arrumo o nome dessas Base Images? São aleatórios?” E a resposta é sempre não. Podemos encontrar base images no Docker Hub oficiais das linguagens, como Golang, Java, Node e utilizar a convenção para colocar os parâmetros.

A convenção para o FROM é:

FROM <image>[:<tag>]
Enter fullscreen mode Exit fullscreen mode

COPY

O comando COPY copia os arquivos ou pastas do <src>, no caso a pasta onde esta o Dockerfile, e os adiciona para o destino final, que é a imagem que estamos criando.

COPY . ./
Enter fullscreen mode Exit fullscreen mode

O COPY é geralmente utilizado seguindo esta convenção:

COPY <src>... <dest>
Enter fullscreen mode Exit fullscreen mode

Sempre colocamos o que queremos copiar primeiro <src> e logo após para onde queremos copiar <dest>. No exemplo onde usamos o . ./, estamos dizendo que queremos copiar todos os arquivos do nosso diretório atual (onde esta o Dockerfile) para a raiz do diretório de destino.

RUN

Este é o comando que executa qualquer comando. É como se você estivesse dentro de um bashfile dizendo que quer fazer algum comando. Por exemplo, RUN ["/bin/bash", "-c", "echo hello"] é como se rodássemos o comando direto do terminal do container. Dessa forma podemos executar todos os comandos que são necessários.

RUN go mod download && go mod verify
Enter fullscreen mode Exit fullscreen mode

Acima podemos ver o primeiro comando RUN que executamos dentro de nosso Dockerfile.
Ele baixa todas as dependências do projeto e as instala na imagem e, em seguida, verifica se todas as dependências baixadas não foram alteradas para que nossa aplicação rode.

O RUN pode ser executado de duas maneiras com base nessa convenção:

#1
RUN <comando>
#2
RUN ["executável", "parametro1", "parametro2"]
Enter fullscreen mode Exit fullscreen mode

Aqui vimos as duas maneiras, tanto passando o comando logo em seguida do RUN, quanto chamando um executável no caso do comando echo.

EXPOSE

Aqui é onde falamos para o Docker por qual porta o container vai interagir em tempo de execução. Podemos escolher qualquer porta, tanto UDP quanto TCP. Se não especificarmos o protocolo, é assumido por padrão que vamos utilizar TCP.

EXPOSE <port> [<port>/<protocol>...]
Enter fullscreen mode Exit fullscreen mode

Em nosso exemplo utilizamos a 8080 para expor nosso serviço e como não passamos o protocolo, ele assumirá o TCP. Assim quando rodarmos o nosso container e acessarmos a URL http://localhost:8080/ teremos nosso serviço rodando.

CMD

E por último, mas não menos importante, o CMD, que tem uma função parecida com o RUN de executar os comandos, porém é reservado para o contexto de runtime. Ou seja, quando executamos o container é o comando que é executado de imediato.

CMD ["/app/server"]
Enter fullscreen mode Exit fullscreen mode

Esses são os principais comandos que utilizamos no dia-a-dia para criar imagens e buildar projetos 🙂.

A receita, resumo

Se você parar e analisar friamente, os passos para criar uma imagem usando Docker são praticamente os mesmos passos que fazemos para rodar uma aplicação em nosso computador pela primeira vez.

Assim como uma receita de bolo.

Configurar o SDK FROM golang:1.20-alpine
Clonar o projeto COPY . ./
Instalar as dependências RUN go mod download && go mod verify
Fazer o build RUN CGO_ENABLED=0 go build -o /app/server ./cmd/main.go
Executá-lo CMD["/app/server"]

Assim, fica claro de entender o que temos que fazer e quais passos temos que seguir para qualquer aplicação que queremos criar uma imagem, independente da linguagem ou ferramentas que estamos utilizando.

E pra finalizar, como sempre deixo aqui o link da documentação oficial de Dockerfile para vocês se aprofundarem ainda mais em outros comandos.

Top comments (0)