Docker is a powerful platform for running containerized applications. It allows developers to easily package, deploy, and run applications in an isolated environment called a container. Containers are more lightweight and portable than virtual machines, making Docker a very useful tool.
In this comprehensive guide, we will cover the most common and useful Docker commands with practical examples to help you get started with Docker.
Finding the Docker Version
To check the version of Docker installed on your system:
This will print out the version number of your Docker installation:
Docker version 20.10.12, build e91ed57
Knowing the Docker version is useful when you need to check compatibility or look up documentation for specific features.
Downloading Docker Images
Docker images contain all the dependencies and configuration required to run an application inside a Docker container. Images are available from public repositories like Docker Hub or private repositories.
To download an image from a repository, use the
docker pull command:
docker pull ubuntu
This will pull the latest version of the
ubuntu image from Docker Hub:
20.04: Pulling from library/ubuntu 8559a31e96f4: Pull complete 51d229c90eb8: Pull complete bac681833d4f: Pull complete Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322 Status: Downloaded newer image for ubuntu:20.04
You can now run containers based on this ubuntu image.
Listing Docker Images
To see all images that are available locally on your Docker host, use the
docker images command:
docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 20.04 cd6d8154f1e1 4 weeks ago 72.9MB nginx latest 82a59828381d 3 months ago 141MB mysql 5.7 b0b168632190 3 months ago 448MB
This lists out all Docker images present on the system along with details like repository name, tag, image ID, created date, and size.
By default, intermediate images used during builds are not displayed. To include those, use the
docker images -a
Running a Docker Container
To start a new Docker container from an image, use the
docker run command:
docker run -it ubuntu bash
This will start a new interactive Ubuntu container and open up a Bash shell inside it.
-it flags tells Docker to allocate a pseudo-TTY connected to the container‘s stdin so we can interact with it.
bash overrides the default command to launch Bash instead.
Once inside the container, you can run Linux commands like:
root@d9b100f2f636:/# cat /etc/os-release NAME="Ubuntu" VERSION="20.04.2 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.2 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal
When done, type
exit to terminate the container.
List Running Containers
To view all running containers, use:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d9b100f2f636 ubuntu "bash" 2 hours Up 2 hour focused_jones
This shows all running containers with details like the container ID, source image, creation time, status, ports, and name.
List All Containers
To view all containers — both running and stopped, use the
-a (all) flag:
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d9b100f2f636 ubuntu "bash" 2 hours ago Up 2 hours focused_jones e2caf7728d5f nginx:latest "nginx" 2 days ago Exited (0) 2 days ago zealous_swartz a4542f719dc9 mysql:5.7 "mysqld" 2 weeks ago Exited (255) 2 weeks ago mysql01
This allows you to view even containers that were run in the past and are now stopped.
Executing Commands in Running Containers
To execute a command inside an already running container, use
docker exec -it focused_jones bash
This will open up a new Bash session attached to the running container with ID
You can similarly run other commands like
cat or check
top from within the container:
root@d9b100f2f636:/# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@d9b100f2f636:/# cat /etc/hostname d9b100f2f636
Stopping a Container
To stop a running container, use the
docker stop command:
docker stop focused_jones
This will send a SIGTERM signal to gracefully stop the container. Once the main process exits, the container stops running.
If you want to forcibly stop a container immediately, use
docker kill focused_jones
This kills the container by sending it a SIGKILL instead.
Removing a Container
To remove a stopped container, use
docker rm focused_jones
This will free up all resources associated with the container. Note that you can only remove stopped containers – not running ones.
To remove a running container, first stop it and then remove it:
docker stop focused_jones docker rm focused_jones
If you want Docker to automatically clean up stopped containers, use
--rm when running the container:
docker run --rm -it ubuntu bash
This container will be removed automatically after it exits.
Committing Changes in a Container
When you start a container from an image, you can make changes inside it, such as writing new files, installing packages, etc. To save these changes as a new Docker image, use
docker commit focused_jones ubuntu-updated
This will create a new image named
ubuntu-updated containing all the changes made in the
You can now run new containers from the updated image.
Pushing Docker Images to a Registry
To share Docker images with others, you can push them to public or private image registries like Docker Hub.
First, log into Docker Hub from the CLI:
docker login --username=your-docker-id
Then, tag your image with the repository name:
docker tag ubuntu-updated your-docker-id/ubuntu-updated
Finally, push it to Docker Hub:
docker push your-docker-id/ubuntu-updated
This uploads your image to your Docker Hub repository.
Pulling Images from a Registry
Other users can now download your image by running:
docker pull your-docker-id/ubuntu-updated
This way, Docker‘s registry system allows easy sharing of images between users.
Private registries work similarly, but require credentials and HTTPS to secure image transfers.
Tagging an Image
Docker images can have multiple tags associated with them. For example,
ubuntu image has tags like
To tag an existing image to a new tag:
docker tag ubuntu:latest ubuntu:jammy
This creates a new tag
jammy that refers to the same
You can also tag images at the time of building – for example:
docker build -t webapp:v1 .
Tags let you version images and refer to them more meaningfully.
Getting Docker Container Logs
To print out logs from a Docker container use:
docker logs focused_jones INFO Started MySQL successfully! INFO Creating database structure...
This shows application logs generated by the processes running inside your container.
You can follow logs in real-time with the
docker logs -f focused_jones INFO Creating user admin123... INFO User admin123 created!
Container logs allow easy debugging of issues inside your containers.
Restarting a Container
Sometimes you may need to restart containers due to application failures or to refresh configuration changes.
docker restart command for this:
docker restart focused_jones
This will send a SIGTERM followed by SIGKILL after a grace period, to restart the main container process.
If you just want to send a SIGTERM, you can use
docker stop and
docker start instead.
Accessing Docker Container Filesystem
The files inside a Docker container are readable/writable via the container‘s filesystem.
To copy a file out of a container onto the host, use
docker cp focused_jones:/var/log/nginx/access.log ./access.log
This will copy
/var/log/nginx/access.log from inside the container onto the host machine‘s current directory as
You can also copy files from host into a container, e.g. to inject configuration files.
By default, containers run on a private virtual network called
bridge which provides internal IPs and container discovery using DNS.
To list out Docker networks:
docker network ls NETWORK ID NAME DRIVER SCOPE c7527e93a56c bridge bridge local b3b2c4d0fc4c host host local 2885e5cc56f2 none null local
Common networks include:
bridge– The default network for containers used for internal communication.
host– Adds containers directly onto the host‘s network stack.
none– Removes all networking including external connectivity.
User defined networks – Create your own networks like
Managing Docker Volumes
Docker volumes provide persistent data storage for containers. Even if a container is deleted, the data stored on volumes persist.
Some common volume commands are:
docker volume create my-vol– Creates a new volume named
docker volume ls– Lists all volumes
docker volume inspect my-vol– Displays details about
docker volume rm my-vol– Removes the volume
When running a container, you can mount a volume inside it using the
docker run -v my-vol:/data ubuntu
This mounts the volume
my-vol onto the
/data directory inside the container. Any data written here is stored on the volume.
Building Docker Images
To build your own Docker image from a Dockerfile, use the
docker build command:
docker build -t myimage:1.0 .
This looks for a Dockerfile in the current directory and builds an image named
myimage:1.0 from it.
Image building best practices include:
Specify a tag like 1.0, 1.1 rather than just
Organize Dockerfiles into separate directories for each application component.
Use small base images like Alpine Linux to keep sizes small.
Leverage Docker‘s build cache by ordering commands from least frequently changed to most.
Don‘t install unnecessary packages or leave behind large build dependencies.
Some key Dockerfile instructions are:
FROM– Sets base image to build upon
COPY– Copy files from host into image
RUN– Execute Linux commands/scripts during build
EXPOSE– Expose ports that the container listens on
ENV– Set environment variables
CMD– Set the default command to run on container start
ENTRYPOINT– Set executable invoked when starting container
USER– Switch to given user upon container start
WORKDIR– Set working directory for
FROM alpine:3.14 RUN apk add --update nodejs COPY . /app WORKDIR /app RUN npm install EXPOSE 3000 ENTRYPOINT ["node", "server.js"]
This builds a container that runs a Node.js application.
Sharing Data Between Containers
There are two main ways to share data between containers:
Volumes: Create a shared volume and mount it onto multiple containers
docker volume create shared-vol docker run -v shared-vol:/volume1 --name container1 ubuntu docker run -v shared-vol:/volume2 --name container2 ubuntu
Any data written to
/volume2 is available to both containers.
Networks: Place containers on the same user-defined bridge network
docker network create app-net docker run -d --network app-net --name mysql mysql docker run -it --network app-net ubuntu
Now both containers can access each other over the
Limiting Container Resources
By default, containers have unrestricted access to the host machine‘s resources.
You can set limits on:
CPU – Limit CPU shares using the
--cpusflag or CPU period/quota.
Memory – Set memory limit via
Restart Policies – Use
--restartto apply a restart policy.
For example, to limit a container to use max 2 CPUs and 1GB RAM:
docker run --cpus=2 --memory=1g nginx
Resource constraints allow limiting the impact of any single container on overall host performance.
Docker Security Best Practices
Some basic security best practices for using Docker include:
Run containers as a non-root user where possible using
Limit container capabilities to the minimum required using
Update Docker and avoid old base images with known vulnerabilities.
Scan images for vulnerabilities using tools like Anchore or Trivy.
-vbinds rather than
--volumes-fromto selectively expose volumes.
Limit communication between containers using custom Docker networks if needed.
Use secrets/configs for sensitive data and Never store secrets in Dockerfiles or source code.
Sign and verify images using Docker Content Trust to prevent tampering.
Use hardware/cloud signing to establish trust for the Docker daemon.
Follow the principle of least privilege throughout – ensure containers have only the permissions truly required.
Docker provides a simple and powerful way to run containerized applications on any infrastructure. Core Docker commands like
build allow you to manage the entire container workflow.
With the examples covered in this guide, you should have a good understanding of the most essential Docker commands for development and testing. To take your skills to the next level, I recommend checking out more advanced Docker features like Swarm, Kubernetes, and security hardening.