Qual è il punto di WORKDIR su Dockerfile?


105

Sto imparando Docker. Per molte volte ho visto che Dockerfileha il WORKDIRcomando:

FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app
EXPOSE 3000
CMD [ “npm”, “start” ] 

Non posso semplicemente omettere WORKDIRe Copyavere il mio Dockerfilealla radice del mio progetto? Quali sono gli svantaggi dell'utilizzo di questo approccio?


Al momento della compilazione si cambia directory entro ilWORKDIR
Ultraviolet

1
@Ultraviolet potresti spiegare questo. Non ho capito bene
Le garcon

Risposte:


118

Secondo la documentazione :

L'istruzione WORKDIR imposta la directory di lavoro per qualsiasi istruzione RUN, CMD, ENTRYPOINT, COPY e ADD che la segue nel Dockerfile. Se la WORKDIR non esiste, verrà creata anche se non viene utilizzata in nessuna istruzione Dockerfile successiva.

Inoltre, nelle migliori pratiche Docker ti consiglia di usarlo:

... dovresti usare WORKDIR invece di proliferare istruzioni come RUN cd… && do-something, che sono difficili da leggere, risolvere e mantenere.

Suggerirei di tenerlo.

Penso che tu possa rifattorizzare il tuo Dockerfile in qualcosa di simile:

FROM node:latest
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD [ “npm”, “start” ] 

2
@MarioGil Si prega di dare un'occhiata alla documentazione COPY.
juanlumn

1
Quando uso FROM ubuntu as buildere poi uso l'immagine successiva COPY, "sa" che ho usato WORKDIR nell'immagine "builder" o devo presumere di no (e utilizzare un percorso assoluto)?
Alex 75

Secondo la documentazioneWORKDIR del docker direi che mantiene il valore perché è un'istruzione eseguita nel Dockerfile prima di eseguire COPYquello
juanlumn

Il tuo RUN mkdircomando non è necessario; cioè, quella riga potrebbe essere cancellata. Secondo la documentazione "Se la WORKDIR non esiste, verrà creata anche se non viene utilizzata in nessuna istruzione Dockerfile successiva." - docs.docker.com/engine/reference/builder/#workdir
Purplejacket

@Purplejacket che è corretto, aggiornerò la risposta
juanlumn

60

Non devi

RUN mkdir -p /usr/src/app

Questo verrà creato automaticamente quando specifichi il tuo WORKDIR

FROM node:latest
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD [ “npm”, “start” ] 

4
Tuttavia, a volte è necessario RUN mkdir perché WORKDIR non rispetta USER durante la creazione delle directory - github.com/moby/moby/issues/20295
Joe Bowbeer

23
Mi piace il fatto che tu abbia specificato WORKDIR creerà la cartella automaticamente.
GingerBeer

32

Puoi pensare a WORKDIRcome un cdall'interno del contenitore (influisce sui comandi che vengono successivamente nel Dockerfile, come il RUNcomando). Se rimuovessi WORKDIRnel tuo esempio sopra, RUN npm installnon funzionerebbe perché non saresti nella /usr/src/appdirectory all'interno del tuo contenitore.

Non vedo come questo sarebbe correlato a dove metti il ​​tuo Dockerfile (dato che la tua posizione Dockerfile sulla macchina host non ha nulla a che fare con il pwd all'interno del contenitore). Puoi inserire il Dockerfile dove preferisci nel tuo progetto. Tuttavia, il primo argomento di COPYè un percorso relativo, quindi se sposti il ​​Dockerfile potresti dover aggiornare quei COPYcomandi.


3
Se si WORKDIRaggiunge come cd, i due COPYnell'esempio originale non avranno la stessa origine e destinazione?
Jonas Rosenqvist

5
No. WORKDIRinfluisce sulla directory di lavoro all'interno del contenitore . Nell'esempio originale, le prime COPYcopie da package.json sull'host (percorso relativo al Dockerfile) a /usr/src/app/package.json nel contenitore . In effetti, WORKDIRnon ha alcun impatto su quel particolare comando perché la destinazione (all'interno del contenitore) non utilizza un percorso relativo (il percorso inizia con /).
mkasberg

@mkasberg If si WORKDIRcomporta come un file cd. Quindi i 2 frammenti sotto equivalgono? WORKDIR /usr/src/app COPY package.json /usr/src/app/e WORKDIR /usr/src/app COPY package.json . grazie
kcatstack

1
Sì, quelli sono equivalenti.
mkasberg

1

Prima di applicare WORKDIR. Qui il WORKDIR si trova nel posto sbagliato e non viene usato saggiamente.

FROM microsoft/aspnetcore:2
COPY --from=build-env /publish /publish
WORKDIR /publish
ENTRYPOINT ["dotnet", "/publish/api.dll"]

Abbiamo corretto il codice precedente per inserire WORKDIR nella posizione corretta e ottimizzato le seguenti istruzioni rimuovendo /Publish

FROM microsoft/aspnetcore:2
WORKDIR /publish
COPY --from=build-env /publish .
ENTRYPOINT ["dotnet", "/api.dll"]

1
Non dovresti avere la barra di fronte a api.dll in quanto ciò lo indirizzerebbe alla radice del contenitore
Timothy c

1

WORKDIRFare attenzione a usare vars come nome della directory di destinazione per - fare ciò sembra risultare in un errore irreversibile "non è possibile normalizzare nulla". IMO, vale anche la pena sottolineare che WORKDIRsi comporta allo stesso modo, mkdir -p <path>cioè tutti gli elementi del percorso vengono creati se non esistono già.

AGGIORNAMENTO: ho riscontrato il problema relativo alla variabile (menzionato sopra) durante l'esecuzione di una build in più fasi - ora sembra che l'uso di una variabile vada bene - se (la variabile) è "nell'ambito", ad esempio nel seguito, il 2 ° WORKDIRriferimento fallisce ...

FROM <some image>
ENV varname varval
WORKDIR $varname

FROM <some other image>
WORKDIR $varname

mentre ci riesce ...

FROM <some image>
ENV varname varval
WORKDIR $varname

FROM <some other image>
ENV varname varval
WORKDIR $varname

.oO ( Forse è nei documenti e l'ho perso )


0

Fare attenzione a dove si imposta WORKDIRperché può influire sul flusso di integrazione continua. Ad esempio, impostarlo su /home/circleci/projectcauserà un errore come .ssho qualunque cosa stia facendo il circleci remoto al momento dell'installazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.