43

In the docker docs getting started tutorial part 2, it has one make a Dockerfile. It instructs to add the following lines:

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

What is /app, and why is this a necessary step?

Intrastellar Explorer
  • 3,005
  • 9
  • 52
  • 119

3 Answers3

104

There are two important directories when building a docker image:

  • the build context directory.
  • the WORKDIR directory.

Build context directory

It's the directory on the host machine where docker will get the files to build the image. It is passed to the docker build command as the last argument. (Instead of a PATH on the host machine it can be a URL). Simple example:

docker build -t myimage .

Here the current dir (.) is the build context dir. In this case, docker build will use Dockerfile located in that dir. All files from that dir will be visible to docker build.

The build context dir is not necessarily where the Dockerfile is located. Dockerfile location defaults to current dir and is otherwise indicated by the -f otpion. Example:

docker build -t myimage -f ./rest-adapter/docker/Dockerfile ./rest-adapter

Here build context dir is ./rest-adapter, a subdirectory of where you call docker build; the Dokerfile location is indicated by -f.

WORKDIR

It's a directory inside your container image that can be set with the WORKDIR instruction in the Dockerfile. It is optional (default is /, but base image might have set it), but considered a good practice. Subsequent instructions in the Dockerfile, such as RUN, CMD and ENTRYPOINT will operate in this dir. As for COPY and ADD, they use both...

COPY and ADD use both dirs

These two commands have <src> and <dest>.

  • <src> is relative to the build context directory.
  • <dest> is relative to the WORKDIR directory.

For example, if your Dockerfile contains...

WORKDIR /myapp
COPY . .

then the contents of your build context directory will be copied to the /myapp dir inside your docker image.

Paulo Merson
  • 13,270
  • 8
  • 79
  • 72
  • 13
    Awesome answer! – Valentyn Stets Jan 30 '20 at 10:25
  • If the app is setting up a web hosting environment via a domain name - then am I correct in believing that to access via a browser there is no need to include the workdir within the URL. for example https://domainname.com:port#/ would be enough? – Martin Sansone - MiOEE Apr 02 '20 at 13:14
  • if `COPY . .` copies from the build context to the WORKDIR then wouldn't the command in the OP's post: `COPY . /app` copy into an 'app' directory inside the WORKDIR? – Toby 1 Kenobi Jun 18 '20 at 14:18
  • 14
    Finally an answer and example that really explains this s#!*. So far all I've seen is "WORKDIR THIS" and "COPY THAT" with no explanation what is being copied to where and what is the magical app folder that everyone seems to have. Thanks. – Wiizl Dec 03 '20 at 16:06
  • 2
    hurray! Dear @Paulo could you add a bit more on how the base image (let's assume alpine) filesystem is seen within the container image and with respect to the WORKDIR, defined above? – andreagalle Jun 03 '21 at 08:52
  • @andreagalle The image you're building sees and shares the same file system of the base image (alpine for example). `WORKDIR` may point to `/myapp` for example, but that's just a shorthand for the Dockerfile commands (`COPY`, `ADD`, `RUN`, `ENTRYPOINT`, `CMD`). When you `docker run` the image, the application (or the shell if you use `-it`) will still see the whole file system from `/`. – Paulo Merson Jun 15 '21 at 10:12
  • 2
    Your comment about base image setting the WORKDIR was super helpful. I wasn't able to figure out how the path was /app from the get go and the docker documentation doesn't state that either. – Govind Rai Jun 16 '21 at 23:03
  • 2
    This thing about the build context and workdir should be part of the getting started guide. – Thakur Karthik Aug 19 '22 at 06:27
  • 2
    this answer explains it better than the one in the docker docs. – alejandro Sep 01 '22 at 15:28
  • 1
    Also important to note is the `--from=` option on commands like `COPY`. These change the "build context" to be the output from the specified stage of the build rather than the native filesystem. – Brian White Feb 05 '23 at 21:00
23

WORKDIR is a good practice because you can set a directory as the main directory, then you can work on it using COPY, ENTRYPOINT, CMD commands, because them will execute pointing to this PATH.

Docker documentation: https://docs.docker.com/engine/reference/builder/

The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.

The WORKDIR instruction can be used multiple times in a Dockerfile. If a relative path is provided, it will be relative to the path of the previous WORKDIR instruction.

Dockerfile Example:

FROM node:alpine
WORKDIR '/app'
COPY ./package.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "start"]

A alpine node.js was created and the workdir is /app, then al files are copied them into /app

Finally npm run start command is running into /app folder inside the container.

You should exec the following command in the case you have sh or bash tty:

docker exec -it <container-id> sh

or

docker exec -it <container-id> bash

After that you can do ls command and you will can see the WORKDIR folder.

I hope it may help you

Hugo Lesta
  • 721
  • 4
  • 14
  • 4
    Okay follow up quesion @Hugo Lesta. Is WORKDIR created within the context of that specific container? In other words, where is that directory created? – Intrastellar Explorer Mar 11 '19 at 19:54
  • 1
    @IntrastellarExplorer you should exec the following command in the case you have sh or bash tty: docker exec -it sh or docker exec -it bash After that you can do ls command and you will can see the WORKDIR folder. – Hugo Lesta Mar 11 '19 at 19:56
  • 1
    Alright I ran the command with bash. @Hugo Lesta the input: `root@c95328d92adf:/app# pwd` and the output: `/app` Does this mean that /app is just a sub-directory of the a root directory in the container? – Intrastellar Explorer Mar 11 '19 at 20:36
  • Hey @IntrastellarExplorer sorry for my delay, that is right! – Hugo Lesta Apr 27 '20 at 13:15
8

You need to declare a working directory and move your code into it, because your code has to live somewhere. Otherwise your code wouldn't be present and your app wouldn't run. Then when commands like RUN, CMD, ENTRYPOINT, COPY, and ADD are used, they are executed in the context of WORKDIR.

/app is an arbitrary choice of working directory. You could use anything you like (foo, bar, or baz), but app is nice since it's self-descriptive and commonly used.

Gavin Miller
  • 43,168
  • 21
  • 122
  • 188