Docker is useful for containerizing and managing processes. It is a great tool for developers and devops teams. Docker is good for creating reproducible environments. It is easy to customize images and document how an environment should be configured. We will look at how to:
- Install Docker
- Manage images, containers, and volumes
- Create custom images
- Pushing images to DockerHub and running custom registry
- and more!
Download and install Docker from the official Docker website. After installing, you may need to restart your computer. After installation, the docker command should be available in the shell.
Debian based distributions
.deb package from
Find the files inside the
Download and install in order:
sudo apt install runc # A dependency sudo dpkg -i containerd.io_1.2.5-1_amd64.deb sudo dpkg -i docker-ce-cli_18.09.4~3-0~ubuntu-bionic_amd64.deb sudo dpkg -i docker-ce_18.09.4~3-0~ubuntu-bionic_amd64.deb
Add the necessary users to the docker group and then reboot:
sudo gpasswd -a someuser docker sudo reboot
Pull an image
Find an image on Docker Hub. Alpine is the first image I would recommend getting. It's a tiny \~5MB Linux base with BusyBox shell. It's good for basic docker testing and can be extended to create your own custom images. You can get the image by running:
docker pull alpine # Some other examples docker pull ubuntu docker pull python:3.7.0 docker pull openjdk:11-jre docker pull openjdk:11-jdk
Here is a list of some other popular images:
nginx, busybox, redis, httpd, mongo, ubuntu, postgres, node, mysql, memcached, registry, hello world, golang, docker, centos, mariadb, drupal, cassandra, vault, jetty, redmine, pypy, django, gcc, rails, swift, rust, irssi
After you have an image installed you can list them with the following commands:
docker images docker image ls
Remove an image
To permanently delete a base image.
-f flag if you need to kill running containers currently runnng that image.
# Delete an image, docker rmi -f alpine
Save and load images to files
To export and import images as files you can use
This is useful for transferring and sharing images without a registry.
docker save ubuntu > ubuntu-all.tar docker save ubuntu:latest > ubuntu-latest.tar docker load < ubuntu-latest.tar
Push an image to a registry
You can use DockerHub or a custom registry server.
Push to DockerHub public registry
docker tag xxxidxxx myusername/my_image:1.0.0 docker login --username=myusername [email protected] docker push username/my_image
Push to a custom registry
You can push and pull to a custom registry using similar commands.
For example, if you have a custom registry on
docker tag image_name localhost.local:9999/myimage docker push localhost.local:9999/myimage docker pull localhost.local:9999/myimage
Run a custom registry
# Boot custom registry docker run -d -p 5000:5000 registry
Create a custom image
You can create a custom image a couple ways:
- Build an image using instructions in a Dockerfile
- Take a snapshot from an existing container
You can build custom images from scratch or build on top of base images like Alpine.
You can find the Dockerfiles that are used to create the images on DockerHub.
You can use those Dockerfiles as references.
To create an image, you need to define a Dockerfile first which acts as the template
which is then built using
docker build to create the image which can then be pushed
to DockerHub, or used to create containers.
Create image from a Dockerfile
Any image can serve as a base image.
Some recommended base images are
Docker also provide a base image named
scratch that allows you to build
totally custom images. The
scratch image is good if you only want to
drop in one single executable. You can read more about creating
base images from
Official Docker Base Images Documentation.
Simplest Dockerfile possible
This example won't do anything but create an useless image.
FROM scratch MAINTAINER Your Name <[email protected]>
Here is a practical minimal example that will at least add an executable
FROM scratch ADD my_executable / CMD ["/my_executable"] # Default command run with `docker run image_name`
Here is an example that includes some common operations:
FROM ubuntu:latest MAINTAINER NanoDano <[email protected]> # Set environment variables ENV PATH=$PATH:/new/bin # Copy file from local system in to image COPY /src /dest # Similar to copy, also supports remote URLs & auto-unpacks zips ADD /src /dest # Expose ports. Must be published at runtime `docker run -P -d my_image` EXPOSE 80/tcp 443/tcp # Mount points VOLUME ["/etc/confdir", "/var/lib/datadir"] # Equivalent to `cd`. Changes dir for subsequent commands. WORKDIR /new/working/dir # Moves to /new/working/dir/subdir WORKDIR subdir # Run command when building image (e.g. RUN apt install git) RUN apt-get update RUN apt-get install -y git # Command to run when `docker run` invoked directly. # Any args passed get passed to the entrypoint executable ENTRYPOINT ["/bin/bash", "-c"] # Default args for entrypoint if none are provided to `docker run`. # The CMD is executed directly if no ENTRYPOINT present. CMD ["env"]
Then build and run the image:
docker build /path/to/Dockerfile --tag myimage docker run myimage # Will run `/bin/bash -c env` by default docker run myimage git --version
Read more about Docker best practices.
Build image from Dockerfile
From the directory containing the
Build will look for a
Dockerfile in the directory.
docker build --tag my_image:latest .
Docker can also take input from STDIN, a direct filepath, or a URL.
# Take input from STDIN (three options) docker build - docker build - < Dockerfile cat Dockerfile | docker build - # Direct file path docker build /path/to/Dockerfile # Remote URL docker build https://raw.githubusercontent.com/nodejs/docker-node/master/10/alpine/Dockerfile
Create image from container snapshot
Instead of building a image from a
you can create new images from existing containers by using
docker run docker commit container_id # Generates unnamed hash (Image ID) docker tag <commit_hash> new_image_name # Tag an unnamed hash # Commit and tag in a single step docker commit container_id new_image_name:latest
Containers are basically running images. Containers are run from image templates. Containers can be started and stopped and images cannot. Many containers can be started from the same image.
Run a container
There are several ways to invoke and run a container. You can have the docker image run a single command and output the results or have it detach and run in the background as a service.
You can run with a container with all the defaults by just running it by name with no arguments. Alpine doesn't do anything by default so it will just exit.
docker run alpine
Run interactive terminal
To run an interactive (
-i) and psuedo-tty(
-t) to get a shell, use
-it like this:
docker run -it alpine docker run -it alpine /bin/sh
Specify restart options
You can have a container automatically restart by specifying the
docker run --restart=always image_name
Run a single command
You can run single commands and view the output directly using this format:
docker run <image_name> <command>.
docker run alpine echo Hello, world docker run openjdk:jre java -version docker run python:3.7.0 python --version # Will run forever, until stopped or sigint received docker run alpine watch date
Running in detached mode
You can run a docker image in the background similar to adding
& to the end of a command.
Just add the
-d flag to detach after running.
docker -d run alpine watch date # Name the container docker run -d --name watcher alpine watch date
Automatically delete image after running
If you don't need an image to persist after a single run, you can flag it to delete itself after running.
docker run --rm alpine echo Hello
To open ("publish") ports that are exposed inside the container, use the
in the format of
docker run -p <host_port>:<container_port>. Use
-P to publish
all exposed ports in container.
For example, to allow 80 and 443 from an nginx container:
# Make localhost:9999 on host viewable docker run -d -p 9999:80 nginx # Publish ALL exposed ports defined in container docker run -d -P nginx
View ports that are listening with:
docker ps netstat -lt # sudo apt install net-tools
If a docker container needs to read or write a directory outside of itself, you need to mount a volume. You can mount it directly to a directory or to a proper "Docker volume".
It is easier to simply mount a directory, but it is better to create a Docker volume to better share it between multiple containers, manage it using Docker CLI, can easily be encrypted, stored remotely, shared between Windows and Linux, and other benefits. Volumes will be covered more below.
There is a
--mount and a
-v option. The simpler and recommended one to use is
docker run -v /path/on/host:/path/inside/container my_image docker run -v my_volume:/mnt/path my_image docker run --mount source=/path/on/host,target=/path/inside/container my_image docker run --mount source=my_volume,target=/path/inside/container my_image
There are many more options available like
Refer to the Official Docker Volume.
To see what containers are active and how long they've been up, use the ps command. This will provide the ID and the name of the containers, both of which you can use to call stop.
# List running containers docker ps # List all containers, including stopped ones docker ps -a
Get usage statistics of running containers
# Memory, CPU, disk, network usage, process count # Like `top` for docker docker stats
Pause, stop and restart a container
You can shutdown a container by calling stop and passing it the name or the ID of the container, which you can get with the ps command.
Instead of shutting down or restarting a container, there are times when pausing a container is useful. This could help if a container performs heavy computation and you want to pause it for a while without shutting down. It can also be useful in certain debugging situations. You can use the pause and unpause commands.
# Shutdown a container by name or id `docker ps` docker stop wonky_wombat # Restart a container, works on running and stopped containers docker restart tall_tiffany # Pause all processes, but keeps container running docker pause captain_carl docker unpause captain_carl
Delete a container
When a container is stopped, it is not completely gone.
To delete a container use the
docker rm command.
You can list all containers with
docker ps -a.
You can't delete a running container without including the
# Delete a stopped container docker rm some_container # Delete a running container docker rm -f some_container
Copy files to/from a container
docker cp command works similar to
scp but the remote host name
is the container id.
docker cp /host/path container_name:/path/in/container docker cp container_name:/path/in/container /host/path
Volumes are for persistent file storage. You could tie a running image to a directory on the host system, but it is better to create a volume that is managed by docker. Containers can even be backed up to and restored from volumes.
Create a volume
docker volume create my_volume
docker volume ls
Get volume details
docker volume inspect my_volume
Delete a volume
docker volume rm my_volume # Delete all unused volumes docker volume prune
As always, refer to the official documentation for the most thorough and up-to-date information. You can also get direct help from the docker application itself using the following commands:
# Help info docker --help # Examples of sub-help options docker ps -h docker container -h docker image -h
Explore public images on Docker Hub.
You should now understand the very basics of Docker, how to find and pull existing images, build your own custom images, and run the containers. Check out the official Docker site for more information.