--- title: Writing a Dockerfile keywords: concepts, build, images, container, docker desktop description: This concept page will teach you how to create image using Dockerfile. summary: | Mastering Dockerfile practices is vital for leveraging container technology effectively, enhancing application reliability and supporting DevOps and CI/CD methodologies. In this guide, you’ll learn how to write a Dockerfile, how to define a base image and setup instructions, including software installation and copying necessary files. weight: 2 aliases: - /guides/docker-concepts/building-images/writing-a-dockerfile/ --- {{< youtube-embed Jx8zoIhiP4c >}} ## Explanation A Dockerfile is a text-based document that's used to create a container image. It provides instructions to the image builder on the commands to run, files to copy, startup command, and more. As an example, the following Dockerfile would produce a ready-to-run Python application: ```dockerfile FROM python:3.12 WORKDIR /usr/local/app # Install the application dependencies COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt # Copy in the source code COPY src ./src EXPOSE 5000 # Setup an app user so the container doesn't run as the root user RUN useradd app USER app CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"] ``` ### Common instructions Some of the most common instructions in a `Dockerfile` include: - `FROM ` - this specifies the base image that the build will extend. - `WORKDIR ` - this instruction specifies the "working directory" or the path in the image where files will be copied and commands will be executed. - `COPY ` - this instruction tells the builder to copy files from the host and put them into the container image. - `RUN ` - this instruction tells the builder to run the specified command. - `ENV ` - this instruction sets an environment variable that a running container will use. - `EXPOSE ` - this instruction sets configuration on the image that indicates a port the image would like to expose. - `USER ` - this instruction sets the default user for all subsequent instructions. - `CMD ["", ""]` - this instruction sets the default command a container using this image will run. To read through all of the instructions or go into greater detail, check out the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/). ## Try it out Just as you saw with the previous example, a Dockerfile typically follows these steps: 1. Determine your base image 2. Install application dependencies 3. Copy in any relevant source code and/or binaries 4. Configure the final image In this quick hands-on guide, you'll write a Dockerfile that builds a simple Node.js application. If you're not familiar with JavaScript-based applications, don't worry. It isn't necessary for following along with this guide. ### Set up [Download this ZIP file](https://github.com/docker/getting-started-todo-app/raw/build-image-from-scratch/app.zip) and extract the contents into a directory on your machine. ### Creating the Dockerfile Now that you have the project, you’re ready to create the `Dockerfile`. 1. [Download and install](https://www.docker.com/products/docker-desktop/) Docker Desktop. 2. Create a file named `Dockerfile` in the same folder as the file `package.json`. > **Dockerfile file extensions** > > It's important to note that the `Dockerfile` has _no_ file extension. Some editors > will automatically add an extension to the file (or complain it doesn't have one). 3. In the `Dockerfile`, define your base image by adding the following line: ```dockerfile FROM node:20-alpine ``` 4. Now, define the working directory by using the `WORKDIR` instruction. This will specify where future commands will run and the directory files will be copied inside the container image. ```dockerfile WORKDIR /app ``` 5. Copy all of the files from your project on your machine into the container image by using the `COPY` instruction: ```dockerfile COPY . . ``` 6. Install the app's dependencies by using the `yarn` CLI and package manager. To do so, run a command using the `RUN` instruction: ```dockerfile RUN yarn install --production ``` 7. Finally, specify the default command to run by using the `CMD` instruction: ```dockerfile CMD ["node", "./src/index.js"] ``` And with that, you should have the following Dockerfile: ```dockerfile FROM node:20-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "./src/index.js"] ``` > **This Dockerfile isn't production-ready yet** > > It's important to note that this Dockerfile is _not_ following all > of the best practices yet (by design). It will build the app, but the > builds won't be as fast, or the images as secure, as they could be. > > Keep reading to learn more about how to make the image maximize the > build cache, run as a non-root user, and multi-stage builds. > **Containerize new projects quickly with `docker init`** > > The `docker init` command will analyze your project and quickly create > a Dockerfile, a `compose.yaml`, and a `.dockerignore`, helping you get > up and going. Since you're learning about Dockerfiles specifically here, > you won't use it now. But, [learn more about it here](/engine/reference/commandline/init/). ## Additional resources To learn more about writing a Dockerfile, visit the following resources: * [Dockerfile reference](/reference/dockerfile/) * [Dockerfile best practices](/develop/develop-images/dockerfile_best-practices/) * [Base images](/build/building/base-images/) * [Getting started with Docker Init](/reference/cli/docker/init/) ## Next steps Now that you have created a Dockerfile and learned the basics, it's time to learn about building, tagging, and pushing the images. {{< button text="Build, tag and publish the Image" url="build-tag-and-publish-an-image" >}}