Ampliando la respuesta de Peter Grainger Pude usar la construcción en varias etapas disponible desde Docker 17.05. La página oficial dice:
Con compilaciones de varias etapas, utiliza múltiples FROM
declaraciones en su Dockerfile. Cada FROM
instrucción puede usar una base diferente, y cada uno de ellos comienza una nueva etapa de la construcción. Puede copiar selectivamente artefactos de una etapa a otra, dejando todo lo que no desea en la imagen final.
Tener esto en cuenta aquí es mi ejemplo de Dockerfile
incluir tres etapas de construcción. Está destinado a crear una imagen de producción de la aplicación web del cliente.
# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
chmod 0700 /root/.ssh && \
ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
yarn --pure-lockfile --mutex file --network-concurrency 1 && \
rm -rf /root/.ssh/
# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod
# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]
.dockerignore
repite el contenido del .gitignore
archivo (evita node_modules
y dist
se copian los directorios resultantes del proyecto):
.idea
dist
node_modules
*.log
Ejemplo de comando para construir una imagen:
$ docker build -t ezze/geoport:0.6.0 \
--build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
--build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
./
Si su clave SSH privada no tiene una frase de contraseña, especifique un SSH_KEY_PASSPHRASE
argumento vacío .
Así es como funciona:
1) Solo en la primera etapapackage.json
, los yarn.lock
archivos y la clave SSH privada se copian en la primera imagen intermedia nombrada sources
. Para evitar más mensajes de frase clave de SSH, se agrega automáticamente a ssh-agent
. Finalmente, el yarn
comando instala todas las dependencias requeridas de NPM y clona repositorios privados de git de Bitbucket sobre SSH.
2) La segunda etapa construye y minimiza el código fuente de la aplicación web y lo coloca en el dist
directorio de la siguiente imagen intermedia nombrada production
. Tenga en cuenta que el código fuente de instaladonode_modules
se copia de la imagen nombrada sources
producida en la primera etapa por esta línea:
COPY --from=sources /app/ /app/
Probablemente también podría ser la siguiente línea:
COPY --from=sources /app/node_modules/ /app/node_modules/
Sólo tenemos node_modules
directorio de la primera imagen intermedia, no SSH_KEY
y SSH_KEY_PASSPHRASE
argumentos. Todo el resto requerido para la compilación se copia de nuestro directorio de proyectos.
3) En la tercera etapa, reducimos el tamaño de la imagen final que se etiquetará ezze/geoport:0.6.0
al incluir solodist
directorio de la segunda imagen intermedia nombrada production
e instalar Node Express para iniciar un servidor web.
Listado de imágenes da una salida como esta:
REPOSITORY TAG IMAGE ID CREATED SIZE
ezze/geoport 0.6.0 8e8809c4e996 3 hours ago 717MB
<none> <none> 1f6518644324 3 hours ago 1.1GB
<none> <none> fa00f1182917 4 hours ago 1.63GB
node carbon b87c2ad8344d 4 weeks ago 676MB
donde las imágenes no etiquetadas corresponden a la primera y la segunda etapa de construcción intermedia.
Si tu corres
$ docker history ezze/geoport:0.6.0 --no-trunc
no verá ninguna mención de SSH_KEY
y SSH_KEY_PASSPHRASE
en la imagen final.