Desarrolle con Docker: use múltiples etapas para crear imágenes

La compilación en varias etapas es una característica nueva y requiere un demonio y un cliente Docker 17.05 o superior. Para aquellos que luchan por optimizar Dockerfiles y hacerlos fáciles de leer y mantener, las compilaciones de múltiples etapas son muy útiles.

Antes de la construcción de múltiples etapas

Una de las cosas más desafiantes al crear una imagen es reducir el tamaño de la imagen. Cada instrucción en el Dockerfile agregará una capa a la imagen. Antes de pasar a la siguiente capa, debe recordar eliminar todos los artefactos innecesarios. Para escribir un Dockerfile verdaderamente eficiente, tradicionalmente necesita usar técnicas de shell y otra lógica para mantener las capas lo más pequeñas posible y asegurarse de que cada capa tenga los artefactos que necesita de la capa anterior, y nada más.

De hecho, es muy común tener un Dockerfile para el entorno de desarrollo (contiene todo lo necesario para construir la aplicación) y un Dockerfile optimizado para el entorno de producción (contiene solo la aplicación y el contenido necesario para ejecutar la aplicación). A esto se le llama "modo de constructor". Mantener dos Dockerfiles no es ideal.

Aquí hay un Dockerfile.buildarchivo de ejemplo y los constructores cumplen con los modos anteriores Dockerfile:

Dockerfile.build

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go .
RUN go get -d -v golang.org/x/net/html \
  && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

Tenga en cuenta que este ejemplo también utiliza el operador Bash &&dos RUNcomprimidos artificiales juntos para evitar crear capas adicionales en el espejo. Esto es propenso a fallar y difícil de mantener. Por ejemplo, es fácil insertar otro comando y olvidarse de usar el \carácter para continuar la línea.

Dockerfile

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]  

build.sh

#!/bin/sh
echo Building alexellis2/href-counter:build

docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \  
    -t alexellis2/href-counter:build . -f Dockerfile.build

docker container create --name extract alexellis2/href-counter:build  
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app  
docker container rm -f extract

echo Building alexellis2/href-counter:latest

docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app

Cuando ejecuta el build.shscript, necesita construir la primera imagen, crear un contenedor desde el cual copiar el trabajo y luego construir un segundo espejo. Los dos espejos ocupan espacio en su sistema y aún están allí en la apppieza de trabajo del disco local .

¡La construcción de varias etapas simplifica enormemente esta situación!

Usar compilación de varias etapas

Para la compilación de varias etapas, puede usar varios Dockerfile en la FROMdeclaración. Cada FROMinstrucción puede usar un grupo diferente de espejos y están comenzando a construir una nueva etapa. Puede copiar de forma selectiva artefactos de una etapa a otra, descartando todo lo que no desee en la imagen final. Para ilustrar cómo funciona esto, ajustemos el Dockerfile en la sección anterior usando una compilación de múltiples etapas.

Dockerfile

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

Solo necesitas un Dockerfile. Tampoco necesita un script de compilación por separado. Solo corre docker build.

$ docker build -t alexellis2/href-counter:latest .

El resultado final es el mismo espejo de producción diminuto que antes y una complejidad significativamente reducida. No es necesario crear espejos intermedios y no es necesario extraer ningún artefacto en el sistema local.

¿Como funciona? La segunda FROMinstrucción se utiliza alpine:latestel espejo como base para comenzar una nueva fase de construcción. COPY --from=0Solo los artefactos de construcción de la etapa anterior se copian en esta nueva etapa. El SDK de Go y los artefactos intermedios se dejarán atrás y no se guardarán en la imagen final.

Nombra la fase de construcción

Por defecto, las fases no tienen nombre y pueden ser referenciadas por sus números enteros. FROMEl primer número entero de la instrucción comienza desde 0. Sin embargo, puede agregar uno AS <NAME>a la FROMdirectiva denominada etapa. Los siguientes ejemplos y nombrando etapa COPYutilizando un ejemplo mejorado del nombre de la instrucción anterior. Esto significa que incluso si las instrucciones del Dockerfile se reordenan más tarde, COPYno se romperán.

FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

Deténgase en una etapa de construcción específica

Al compilar la imagen, no es necesario compilar el Dockerfile completo, incluida cada etapa. Puede especificar la fase de construcción de destino. El siguiente comando asume que está usando antes Dockerfile, pero se llama builderfase de parada:

$ docker build --target builder -t alexellis2/href-counter:latest .

Algunos escenarios en los que esto puede ser muy poderoso son:

  • Depurar una fase de compilación específica
  • Todos usan una herramienta o una 调试(debug)fase habilitada de depuración de símbolos y una 生产(production)fase ajustada
  • Utilice una 测试(testing)etapa en la que su aplicación se llene con datos de prueba, pero cuando cree un producto, use una etapa diferente que utilice datos reales.

docker-multi-etapa

Utilice espejos externos como "escenarios"

Al usar una compilación de múltiples etapas, no está restringido a copiar de etapas creadas previamente en el Dockerfile. Puede utilizar las COPY --frominstrucciones de una copia separada de la imagen que se pueden utilizar están disponibles en el nombre de la imagen local, el registro local o la etiqueta o ID de Docker. El cliente de Docker extrae la imagen y copia los artefactos de ella cuando es necesario. La sintaxis es:

COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

Trate la etapa anterior como la nueva etapa

En las FROMinstrucciones de uso , puede consultar el contenido de la etapa anterior. P.ej:

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

Autor:
Traductor oficial del sitio web de Docker : Technical Zemin
Editor: Technical Verses
enlaces: texto en inglés

Número público: Estación de traducción técnica

Supongo que te gusta

Origin blog.csdn.net/weixin_47498376/article/details/107140149
Recomendado
Clasificación