Espandendo la risposta di Peter Grainger Sono stato in grado di utilizzare la build multi-stage disponibile dalla Docker 17.05. La pagina ufficiale afferma:
Con build multi-stage, usi più FROM
istruzioni nel tuo Dockerfile. Ogni FROM
istruzione può usare una base diversa e ognuna di esse inizia una nuova fase della build. Puoi copiare in modo selettivo artefatti da uno stadio all'altro, lasciando tutto ciò che non vuoi nell'immagine finale.
Tenere presente questo è il mio esempio di Dockerfile
includere tre fasi di costruzione. Ha lo scopo di creare un'immagine di produzione dell'applicazione Web client.
# 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
ripete il contenuto del .gitignore
file (impedisce node_modules
che le dist
directory risultanti del progetto vengano copiate):
.idea
dist
node_modules
*.log
Esempio di comando per creare un'immagine:
$ docker build -t ezze/geoport:0.6.0 \
--build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
--build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
./
Se la tua chiave SSH privata non ha una passphrase, specifica semplicemente un SSH_KEY_PASSPHRASE
argomento vuoto .
È così che funziona:
1). Solo nella prima fase package.json
, i yarn.lock
file e la chiave SSH privata vengono copiati nella prima immagine intermedia denominata sources
. Per evitare ulteriori prompt della passphrase della chiave SSH, viene aggiunto automaticamente ssh-agent
. Infine il yarn
comando installa tutte le dipendenze richieste da NPM e clona i repository git privati da Bitbucket su SSH.
2). La seconda fase crea e minimizza il codice sorgente dell'applicazione Web e lo posiziona nella dist
directory della successiva immagine intermedia denominata production
. Si noti che il codice sorgente di installato node_modules
viene copiato dall'immagine denominata sources
prodotta nel primo stadio da questa riga:
COPY --from=sources /app/ /app/
Probabilmente potrebbe anche essere la seguente riga:
COPY --from=sources /app/node_modules/ /app/node_modules/
node_modules
Qui abbiamo solo directory dalla prima immagine intermedia, no SSH_KEY
e SSH_KEY_PASSPHRASE
argomenti. Tutto il resto necessario per la compilazione viene copiato dalla nostra directory di progetto.
3). Nella terza fase riduciamo una dimensione dell'immagine finale che verrà taggata ezze/geoport:0.6.0
includendo solo la dist
directory della seconda immagine intermedia denominata production
e installando Node Express per l'avvio di un web server.
Elencare le immagini fornisce un output come questo:
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
dove le immagini senza tag corrispondono alla prima e alla seconda fase di costruzione intermedia.
Se corri
$ docker history ezze/geoport:0.6.0 --no-trunc
non vedrai alcuna menzione di SSH_KEY
e SSH_KEY_PASSPHRASE
nell'immagine finale.