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 FROMdeclaraciones en su Dockerfile. Cada FROMinstrucció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 Dockerfileincluir 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"]
.dockerignorerepite el contenido del .gitignorearchivo (evita node_modulesy distse 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_PASSPHRASEargumento vacío .
Así es como funciona:
1) Solo en la primera etapapackage.json , los yarn.lockarchivos 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 yarncomando 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 distdirectorio de la siguiente imagen intermedia nombrada production. Tenga en cuenta que el código fuente de instaladonode_modules se copia de la imagen nombrada sourcesproducida 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_KEYy SSH_KEY_PASSPHRASEargumentos. 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.0al incluir solodist directorio de la segunda imagen intermedia nombrada productione 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_KEYy SSH_KEY_PASSPHRASEen la imagen final.