This document is meant to serve as a quick reference for common Docker commands and concepts. It is not meant to be an exhaustive guide to Docker, but rather a concise collection of commands and tips to help you get started with Docker.
Most of these commands can be run in one way or another through the Docker Desktop UI as well, but it's useful to get familiar with the options.
docker build -t my-app .This is the most common command used to build a Docker image. It takes a Dockerfile in the current directory and builds an image tagged with the name my-app. The -t flag is used to specify the tag or name of the image. The . at the end of the command specifies the path to the current directory, which must contain the Dockerfile.
docker build -t my-app:latest -f Dockerfile.prod --build-arg BACKEND_URL=http://backend:8000 backendThis command represents a more complex build scenario. It builds an image tagged with my-app:latest using the Dockerfile.prod file in the backend directory. It also passes a build argument BACKEND_URL with the value http://backend:8000 to the build process. This can be useful for passing environment-specific values to the build process.
Let's break it down step by step:
docker build- Command to build a Docker image.-t my-app:latest- Tag the image with the namemy-appand the taglatest. You can use different tags for different builds that still share the same base image name. For example, you might havemy-app:productionandmy-app:developmentlive side by side for different purposes.-f Dockerfile.prod- Use theDockerfile.prodfile for the build process. Without this flag, Docker looks for a file namedDockerfilein the current directory, so use it to specify a different file.--build-arg BACKEND_URL=http://backend:8000- Pass a build argumentBACKEND_URLwith the valuehttp://backend:8000to the build process. This variable can be used in theDockerfileduring the build process. This variable is not available in the final image or the running container.backend- The path to the directory containing theDockerfile.prodfile. This is the context for the build process, and Docker will look for theDockerfile.prodfile in this directory. If you have a.dockerignorefile in this directory, Docker will use it to exclude files and directories from the build context.
docker run -p 4000:5000 my-app
# OR
docker run -p 4000:5000 my-app:latestThis command runs a Docker container based on the my-app image. It maps port 4000 on the host machine to port 5000 in the container. This allows you to access the application running inside the container on port 5000 by navigating to http://localhost:4000 in your web browser.
Usually, not specifying a tag (my-app) is the same as specifying the "latest" tag, and it will use the latest image you have (my-app:latest).
If the my-app image does not exist on your local machine, docker will automatically search for an image by that exact name on DockerHub and will pull it to your machine if it exists.
docker run -it --rm my-appThis is often useful when you want to test something out. You terminal will be "attached" to the running container, so your commands (Ctrl-C for example) are executed directly there. You can also combine it with most other flags if needed (for example, -p 4000:5000)
docker run -d --name my-running-app my-appThis has the same effect of running the my-app image as above, but this time, your terminal is "detached" (-d or --detach) from it, which means it will keep running in the background. You can always see the terminal later if needed with docker logs [container-name] which is why it's useful to give it a custom name like we did with --name my-running-app. Without --name docker chooses a random name for you.
You can also stop the container (which doesn't delete it) with
docker stop my-running-appAnd start it back up later with
docker start my-running-appOr remove it completely with
docker rm my-running-appWhich removes the running container and it's files (but does not delete the static image that was used for this container).
docker run -e API_KEY=abcde -v ./my-data:/container-data -p 4000:5000 --env-file=production.env --name my-running-app my-app:productionThis are just a few of the flags we can use when running a container, but they are the most important / useful ones. Let's break it down:
docker run- The basic command for running docker containers-e API_KEY=abcde- We can pass environment variables that will be accessible to any running process within the container. Can be used multiple times to specify more variables (for example:-e API_KEY=abcde -e ANOTHER_SECRET=12345)-v ./my-data:/container-dataor--volume ./my-data:/container-data- maps a real folder on our local host computer (./my-data) to a folder that exists only inside the container (/container-data). Can be specified multiple times to map multiple folders. While it's possible to use to map specific files instead of folders, it can be more complex for various reasons, so prefer folders for this use when you can.-p 4000:5000or--port 4000:5000- Maps a real port (4000) from out local host computer, to a port that is used by the container (5000). The app running in the container must be listening on that port for this flag to have any effect. Without it, the inner container might be listening on that port but we can't (easily) access it. This flag makes that process available to us on http://localhost:5000--env-file=production.env- Load a whole file of environment variables instead of loading multiple variables through-e. Useful for when you have complete sets of variables for different purposes, for exampleproduction.envvs.development.env--name my-running-app- Specify a custom name for the container. Must be unique (no other active container under that same name, or the run command will fail). Usually a good idea so you can use that name later in other commands, unless you know you need to run many similar containers and don't want to name them all.my-app:production- The image name (my-app) and the tag (production) of the image that will be used as a starting point for the container to run. The image (with the correct tag) must be wither previously build by you on the same computer, or pulled from DockerHub. If you don't specify a tag, this is the (usually) same as using the "latest" tag (my-appis the same asmy-app:latest).
Building and running docker containers through the command line has several difficulties:
- Running each container often requires a long and complex command with many flags
- The flags usually repeat themselves for running the same image for the same purpose.
- The
buildstep is usually done just before therunstep, so it'll be simpler if this step could be done in one command. - Running multiple containers for the same app (for example, a
backend, afrontendand adatabase) might mean that we want to repeat some values multiple times, and have them be more manageable and predictable.
To solve that, we have "Docker Compose" - a special command that takes in a docker-compose.yml file in a specific format that contains all of our needs, and gives us the running containers we need.
We don't get into too much details about the file format and all the options (you can read more here) but a docker-compose.yml file might look like this:
services:
frontend:
container_name: frontend
build:
context: ./frontend
args:
- BACKEND_URL=http://api.example.com
ports:
- 8888:80
backend:
container_name: backend
build:
context: ./backend
environment:
- FRONTEND_URL=http://www.example.com
env_file:
- .env
ports:
- 4444:5555
volumes:
- ./data:/dataWhich contains our definitions to both a backend image and frontend image that need to run together. The following commands can now be run in that same folder, which will simplify our workflow:
- Just build both containers, don't run them
docker compose build- Just run the containers - the terminal stays attached to the containers
docker compose up- Run the containers in the background (detach the terminal)
docker compose up -d- Stop all the containers (only the ones specified in the file)
docker compose down- Force a build, run, and detach - in one step
docker compose up -d --build