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 FROM
générations à plusieurs étapes, vous utilisez plusieurs instructions dans votre Dockerfile. Chaque FROM
instruction 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' Dockerfile
inclure 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"]
.dockerignore
répète le contenu du .gitignore
fichier (il empêche les répertoires node_modules
résultants dist
du 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_PASSPHRASE
argument vide .
Voilà comment cela fonctionne:
1). Sur la première étape uniquement package.json
, les yarn.lock
fichiers 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 yarn
commande 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 dist
répertoire de la prochaine image intermédiaire nommée production
. Notez que le code source de installé node_modules
est copié à partir de l'image nommée sources
produite 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_modules
répertoire de la première image intermédiaire, non SSH_KEY
et des SSH_KEY_PASSPHRASE
arguments. 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.0
en incluant uniquement le dist
répertoire de la deuxième image intermédiaire nommée production
et 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_KEY
et SSH_KEY_PASSPHRASE
dans l'image finale.