Publicando uma imagem com docker compose.

namespace/repositório.
docker compose push usa a sessão do Docker Desktop (ou docker login) para autenticar.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.
$ 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] ...
$ 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

tag
services:
meucafezinho:
build: .
image: newtonsbm/cafecompao_aula:pcd2024
ports:
- "8000:8000"
A tag é opcional — quando omitida, o padrão é latest.

docker pull.Imagens menores, separando build de execução.
golang e deploy no alpine.
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.
Dockerfile.compose.yaml.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
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.
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.

dev: 290.91 MB (Python + Git + dependências) → prod: 46.42 MB (só o site estático + nginx) — mais de 6× menor.