As imagens do Docker são criadas a partir de um Dockerfile que define uma imagem base e uma série de instruções que adicionam suas próprias camadas de sistema de arquivos. O que acontece se você quiser fazer o seu ter “Imagem de base” embora? Veja como começar do zero e criar um sistema de arquivos contêiner completo do zero.

Publicidade

O que é uma imagem?

As imagens do Docker geralmente usam uma distribuição Linux popular como imagem base. Se você escreveu FROM ubuntu:latest, FROM debian:latest ou FROM alpine:latest, você usou um sistema operacional como base. Você também pode usar uma imagem pré-configurada para uma determinada linguagem de programação ou estrutura, como FROM php:8.0 ou FROM node:16.

Todas essas imagens fornecem um ponto de partida útil para seus aplicativos. Eles vêm com utilitários Unix comuns e pacotes de software importantes. Porém, tudo isso aumenta o tamanho da imagem final. Uma imagem verdadeiramente mínima deve ser construída construindo seu próprio sistema de arquivos a partir dos primeiros princípios.

A imagem “zero”

O Docker fornece uma imagem base especial que indica que você deseja controlar a primeira camada do sistema de arquivos. Esta é a camada mais inferior de sua imagem, geralmente definida pela imagem de base indicada por seu FROM instrução.

Publicidade

Quando você quiser criar uma imagem “do zero”, escreva FROM scratch em seu Dockerfile é a maneira de fazer isso! Isso dá a você um sistema de arquivos que, para começar, é uma folha em branco.

FROM scratch

Você deve então usar o resto do Dockerfile normalmente para preencher o sistema de arquivos do contêiner com os binários e bibliotecas de que precisa.

O que é “zero”?

o scratch “Imagem” se parece com uma imagem Docker normal. É mesmo listado no Docker Hub. scratch não é realmente uma imagem – é uma palavra-chave reservada que denota a camada mais baixa do sistema de arquivos de uma imagem em funcionamento. Todas as imagens do Docker ficam em cima scratch como seu fundamento comum.

Você não pode docker pull scratch e não é possível executar contêineres usando-o. Ele representa uma camada de imagem vazia, então não há nada para o Docker executar. As imagens não podem ser marcadas como scratch quer devido à sua natureza reservada.

Publicidade

O que pode ser adicionado a imagens baseadas em scratch?

Você não precisa de muito para construir uma imagem funcional sobre scratch. Tudo que você precisa adicionar é um binário Linux compilado estaticamente que você pode usar como o comando de sua imagem.

Publicidade

Aqui está uma demonstração funcional que executa um pequeno programa “hello world” compilado de C:

#include <stdio.h>
 
int main() {
    printf("Hello World");
    return 0;
}

Compile seu código C para um binário:

gcc -o helloworld hello.c

Execute seu binário e observe que “hello world” está impresso em seu terminal:

./helloworld

Agora você pode criar um contêiner Docker baseado em scratch que executa seu binário:

FROM scratch
COPY helloworld /
CMD ["helloworld"]

Construa sua imagem:

Publicidade
docker build -t hello:latest .

Inspecionando a imagem com docker inspect mostrará que ele tem uma única camada. O sistema de arquivos desta imagem contém apenas um arquivo, o helloworld binário.

Agora execute um contêiner usando sua imagem:

docker run hello:latest

Você verá “hello world” em seu terminal enquanto seu binário compilado é executado. Sua imagem baseada em scratch contém apenas seu binário, então ele terá apenas alguns KBs de tamanho. Usar qualquer imagem de base do sistema operacional aumentaria isso para vários megabytes, mesmo com uma distribuição mínima como o Alpine.

Praticamente todas as imagens terão algumas dependências além de um binário estático simples. Você precisará adicioná-los à sua imagem como parte do Dockerfile. Lembre-se de que nenhuma das ferramentas que você considera certas nas distribuições padrão do Linux estará disponível até que você as adicione manualmente ao sistema de arquivos da imagem.

Quando usar o Scratch?

A decisão de começar scratch deve se basear nas dependências de seu aplicativo e em seus objetivos em relação à portabilidade de imagem. Imagens construídas a partir de scratch são mais adequados para hospedar binários compilados estaticamente onde o tamanho da imagem e os tempos de construção são importantes.

Publicidade

scratch fornece uma lousa limpa para trabalhar, portanto, requer algum investimento inicial para escrever corretamente seu Dockerfile e mantê-lo ao longo do tempo. Alguns comandos do Docker como attach não funcionará por padrão, pois não haverá shell dentro do seu contêiner, a menos que você adicione um.

Usando scratch pode ser mais problemático do que vale quando você usa linguagens interpretadas com dependências ambientais pesadas. Você precisará atualizar continuamente sua imagem de base para fazer referência às versões mais recentes desses pacotes. Geralmente é mais conveniente e de fácil manutenção usar um sabor mínimo de uma imagem base do Docker Hub existente.

Resumo

FROM scratch em um Dockerfile indica que você deseja iniciar a partir de um sistema de arquivos vazio onde você está no controle de cada camada adicionada. Ele facilita imagens altamente simplificadas, eliminadas de tudo, exceto das dependências de que seu aplicativo precisa.

A maioria dos desenvolvedores provavelmente não usará scratch diretamente, pois não é adequado para a maioria dos casos de uso de contêiner. Você pode escolher usá-lo se quiser colocar em contêiner binários estáticos autocontidos com poucos requisitos ambientais.

scratch também funciona como um indicador claro da diferença entre “contêineres” e VMs. Uma imagem contendo apenas um arquivo executável é um contêiner do Docker utilizável, pois o processo é executado no kernel do seu host. Uma VM regular precisa ser inicializada independentemente de seu host, portanto, deve incluir um kernel completo do sistema operacional em sua imagem.

Publicidade