Programação Concorrente e Distribuída

Docker Hub e Boas Práticas

Aula 06 — Publicando imagens e construindo com múltiplos estágios
Prof. Newton S. B. Miyoshi
newton.miyoshi@baraodemaua.br
Centro Universitário Barão de Mauá — Ribeirão Preto
Parte 1

Docker Hub

Publicando uma imagem com docker compose.

Enviando com Docker Compose — criar o repositório

Tela do Docker Hub para criar um novo repositório, com namespace e nome preenchidos
No Docker Hub, crie o repositório que vai receber a imagem — namespace/repositório.

Esteja logado no Docker Desktop

Docker Desktop com o menu de conta aberto, mostrando o usuário logado
O docker compose push usa a sessão do Docker Desktop (ou docker login) para autenticar.

Enviando com Docker Compose — propriedade image


services:
  meucafezinho:
    build: .
    image: newtonsbm/cafecompao_aula
    ports:
      - "8000:8000"
    command: /bin/sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
        

No serviço que será enviado, image segue o padrão nome_usuario/repositorio referente ao Docker Hub.

Garanta que a imagem foi buildada


$ docker compose build
[+] Building 12.5s (8/10)
 => [meucafezinho 1/5] FROM docker.io/library/python:3-alpine
 => [meucafezinho 2/5] COPY . /app
 => [meucafezinho 3/5] WORKDIR /app
 => [meucafezinho 4/5] RUN pip install -r requirements.txt
 => [meucafezinho 5/5] ...
        

Envie para o Docker Hub


$ docker compose push meucafezinho
[+] Pushing 9/9
 - Pushing newtonsbm/cafecompao_aula: 2f44f485586a Pushed
 - Pushing newtonsbm/cafecompao_aula: 699a8ba52c91 Pushed
 - Pushing newtonsbm/cafecompao_aula: 5f70bf18a086 Mounted from newtonsbm/cafecompao_exemplo
        

Verifique no Docker Hub

Página do Docker Hub mostrando as camadas (layers) da imagem enviada
A imagem enviada aparece no repositório, com suas camadas (layers) e tamanho.

Opcional: tag


services:
  meucafezinho:
    build: .
    image: newtonsbm/cafecompao_aula:pcd2024
    ports:
      - "8000:8000"
        

A tag é opcional — quando omitida, o padrão é latest.

Tags no Docker Hub

Aba Tags do Docker Hub, mostrando as tags pcd2024 e latest com o comando docker pull de cada uma
Cada tag é uma versão independente da imagem, com seu próprio docker pull.
Parte 2

Boas Práticas — Multi-stage builds

Imagens menores, separando build de execução.

Use builds de múltiplos estágios

  • Muitas vezes precisamos de mais de uma imagem para uma aplicação.
  • Uma imagem para fazer o build, outra para fazer o deploy
    • ex.: Maven para Java, Tomcat para deploy.
  • Vamos ver um exemplo: aplicação em Go, com build no golang e deploy no alpine.

Usando um estágio anterior para construir outro


FROM alpine:latest as builder
RUN apk --no-cache add build-base

FROM builder as build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp

FROM builder as build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp
        

Os estágios build1 e build2 reaproveitam o estágio builder — sem repetir a instalação das dependências.

Exemplo prático

Passo a passo — Pelican SSG

  • Criar Dockerfile.
  • Criar compose.yaml.
  • Gerar o projeto Pelican.
  • Configurar.

Gerando o projeto — pelican-quickstart


$ docker compose run -it cafeblog pelican-quickstart
Welcome to pelican-quickstart v4.9.1.

> Where do you want to create your new web site? [.]
> What will be the title of this web site? Cafezando
> Who will be the author of this web site? Newton Miyoshi
> Do you want to specify a URL prefix? (Y/n) y
  blog.cafecompao.com.br
Done. Your new project is available at /app
        

Docker Multi Stage — Pelican: Dockerfile (single / dev)


FROM python:3-slim
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN apt-get update
RUN apt-get install -y git
RUN pip install pelican[markdown] git+https://github.com/arulrajnet/attila.git@master
        

Uma única imagem: Python + Git + todas as dependências de build, também usada para servir o site em desenvolvimento.

Docker Multi Stage — Pelican: DockerfileProd (multi / prod)


FROM python:3-slim AS builder
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN apt-get update
RUN apt-get install -y git
RUN pip install pelican[markdown] git+https://github.com/arulrajnet/attila.git@master
RUN pelican content -o output -s publishconf.py

FROM nginx:1-alpine
COPY --from=builder /app/output/ /usr/share/nginx/html
        

O estágio builder gera o site estático; só o resultado (output/) vai para a imagem final do nginx — Python e Git ficam de fora.

compose.yaml — dev (single-stage)


services:
  cafeblog:
    build: .
    image: cafecompao_blog:dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    command: pelican --autoreload --listen --bind 0.0.0.0 --port 3000
        

compose.prod.yaml — prod (multi-stage)


services:
  cafeblog:
    image: cafecompao_blog:prod
    build:
      context: .
      dockerfile: DockerfileProd
    ports:
      - "8080:80"
        

docker compose -f compose.prod.yaml up usa outro arquivo e outro dockerfile — o nginx passa a servir na porta 80.

Comparação

Docker Desktop listando as imagens cafecompao_blog:prod com 46.42 MB e cafecompao_blog:dev com 290.91 MB
dev: 290.91 MB (Python + Git + dependências) → prod: 46.42 MB (só o site estático + nginx) — mais de 6× menor.

Referências bibliográficas