> [syntax directive](#dockerfile-syntax) on the first line of the file.
> The symbol is only interpreted as a directive if the pattern matches a
> directive and appears at the beginning of the Dockerfile. Otherwise, it's
> treated as a comment.
### Installing dependencies
The second `RUN` instruction installs the `flask` dependency required by the
Python application.
```dockerfile
RUN pip install flask==3.0.*
```
A prerequisite for this instruction is that `pip` is installed into the build
container. The first `RUN` command installs `pip`, which ensures that we can
use the command to install the flask web framework.
### Copying files
The next instruction uses the
[`COPY` instruction](/reference/dockerfile.md#copy) to copy the
`hello.py` file from the local build context into the root directory of our image.
```dockerfile
COPY hello.py /
```
A [build context](./context.md) is the set of files that you can access
in Dockerfile instructions such as `COPY` and `ADD`.
After the `COPY` instruction, the `hello.py` file is added to the filesystem
of the build container.
### Setting environment variables
If your application uses environment variables, you can set environment variables
in your Docker build using the [`ENV` instruction](/reference/dockerfile.md#env).
```dockerfile
ENV FLASK_APP=hello
```
This sets a Linux environment variable we'll need later. Flask, the framework
used in this example, uses this variable to start the application. Without this,
flask wouldn't know where to find our application to be able to run it.
### Exposed ports
The [`EXPOSE` instruction](/reference/dockerfile.md#expose) marks that
our final image has a service listening on port `8000`.
```dockerfile
EXPOSE 8000
```
This instruction isn't required, but it is a good practice and helps tools and
team members understand what this application is doing.
### Starting the application
Finally, [`CMD` instruction](/reference/dockerfile.md#cmd) sets the
command that is run when the user starts a container based on this image.
```dockerfile
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]
```
This command starts the flask development server listening on all addresses
on port `8000`. The example here uses the "exec form" version of `CMD`.
It's also possible to use the "shell form":
```dockerfile
CMD flask run --host 0.0.0.0 --port 8000
```
There are subtle differences between these two versions,
for example in how they trap signals like `SIGTERM` and `SIGKILL`.
For more information about these differences, see
[Shell and exec form](/reference/dockerfile.md#shell-and-exec-form)
## Building
To build a container image using the Dockerfile example from the
[previous section](#example), you use the `docker build` command:
```console
$ docker build -t test:latest .
```
The `-t test:latest` option specifies the name and tag of the image.
The single dot (`.`) at the end of the command sets the
[build context](./context.md) to the current directory. This means that the
build expects to find the Dockerfile and the `hello.py` file in the directory
where the command is invoked. If those files aren't there, the build fails.
After the image has been built, you can run the application as a container with
`docker run`, specifying the image name:
```console
$ docker run -p 127.0.0.1:8000:8000 test:latest
```
This publishes the container's port 8000 to `http://localhost:8000` on the
Docker host.
> [!TIP]
>
> Want a better editing experience for Dockerfiles in VS Code?
> Check out the [Docker VS Code Extension (Beta)](https://marketplace.visualstudio.com/items?itemName=docker.docker) for linting, code navigation, and vulnerability scanning.