En développant la réponse de Peter Grainger, j'ai pu utiliser la version multi-étapes disponible depuis Docker 17.05. La page officielle indique:
  Avec les FROMgénérations à plusieurs étapes, vous utilisez plusieurs instructions dans votre Dockerfile. Chaque FROMinstruction peut utiliser une base différente et chacune d'elles commence une nouvelle étape de la construction. Vous pouvez copier de manière sélective des artefacts d'une étape à une autre, laissant derrière vous tout ce que vous ne voulez pas dans l'image finale.
Garder cela à l'esprit ici est mon exemple d' Dockerfileinclure trois étapes de construction. Il est destiné à créer une image de production de l'application Web 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"]
.dockerignorerépète le contenu du .gitignorefichier (il empêche les répertoires node_modulesrésultants distdu projet d'être copiés):
.idea
dist
node_modules
*.log
Exemple de commande pour construire une image:
$ 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 votre clé SSH privée n'a pas de phrase secrète, spécifiez simplement un SSH_KEY_PASSPHRASEargument vide .
Voilà comment cela fonctionne:
1). Sur la première étape uniquement package.json, les yarn.lockfichiers et la clé SSH privée sont copiés dans la première image intermédiaire nommée sources. Afin d'éviter d'autres invites de phrase secrète de clé SSH, il est automatiquement ajouté à ssh-agent. Enfin, la yarncommande installe toutes les dépendances requises de NPM et clone les référentiels git privés de Bitbucket sur SSH.
2). La deuxième étape construit et réduit le code source de l'application Web et le place dans le distrépertoire de la prochaine image intermédiaire nommée production. Notez que le code source de installé node_modulesest copié à partir de l'image nommée sourcesproduite sur la première étape par cette ligne:
COPY --from=sources /app/ /app/
Il pourrait également s'agir de la ligne suivante:
COPY --from=sources /app/node_modules/ /app/node_modules/
Nous n'avons ici que le node_modulesrépertoire de la première image intermédiaire, non SSH_KEYet des SSH_KEY_PASSPHRASEarguments. Tout le reste requis pour la construction est copié à partir de notre répertoire de projet.
3). À la troisième étape, nous réduisons la taille de l'image finale qui sera étiquetée ezze/geoport:0.6.0en incluant uniquement le distrépertoire de la deuxième image intermédiaire nommée productionet en installant Node Express pour démarrer un serveur Web.
La liste des images donne une sortie comme celle-ci:
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
où les images non étiquetées correspondent aux première et deuxième étapes de construction intermédiaires.
Si vous courez
$ docker history ezze/geoport:0.6.0 --no-trunc
vous ne verrez aucune mention de SSH_KEYet SSH_KEY_PASSPHRASEdans l'image finale.