When using Docker, we start with a base image. We boot it up, create changes and those changes are saved in layers forming another image.
So eventually I have an image for my PostgreSQL instance and an image for my web application, changes to which keep on being persisted.
So the question is: What is a container?
Simply said, if an image is a class, then a container is an instance of a class is a runtime object.
From my article on Automating Docker Deployments:
Docker Images vs. Containers
In Dockerland, there are images and there are containers. The two are closely related, but distinct. For me, grasping this dichotomy has clarified Docker immensely.
What's an Image?
An image is an inert, immutable, file that's essentially a snapshot of a container. Images are created with the build command, and they'll produce a container when started with run. Images are stored in a Docker registry such as registry.hub.docker.com. Because they can become quite large, images are designed to be composed of layers of other images, allowing a miminal amount of data to be sent when transferring images over the network.
Local images can be listed by running
docker images
:Some things to note:
-t
flag of thedocker build
command, or fromdocker tag
-ing an existing image. You're free to tag images using a nomenclature that makes sense to you, but know that docker will use the tag as the registry location in adocker push
ordocker pull
.[REGISTRYHOST/][USERNAME/]NAME[:TAG]
. Forubuntu
above, REGISTRYHOST is inferred to beregistry.hub.docker.com
. So if you plan on storing your image calledmy-application
in a registry atdocker.example.com
, you should tag that imagedocker.example.com/my-application
.latest
tag is not magical, it's simply the default tag when you don't specify a tag.<none>
TAG and REPOSITORY. It's easy to forget about them.More info on images is available from the Docker docs and glossary.
What's a container?
To use a programming metaphor, if an image is a class, then a container is an instance of a class—a runtime object. Containers are hopefully why you're using Docker; they're lightweight and portable encapsulations of an environment in which to run applications.
View local running containers with
docker ps
:Here I'm running a dockerized version of the docker registry, so that I have a private place to store my images. Again, some things to note:
docker ps
only outputs running containers. You can view all containers (running or stopped) withdocker ps -a
.--name
flag.How to avoid image and container buildup?
One of my early frustrations with Docker was the seemingly constant buildup of untagged images and stopped containers. On a handful of occassions this buildup resulted in maxed out hard drives slowing down my laptop or halting my automated build pipeline. Talk about "containers everywhere"!
We can remove all untagged images by combining
docker rmi
with the recentdangling=true
query:docker images -q --filter "dangling=true" | xargs docker rmi
Docker won't be able to remove images that are behind existing containers, so you may have to remove stopped containers with
docker rm
first:These are known pain points with Docker, and may be addressed in future releases. However, with a clear understanding of images and containers, these situations can be avoided with a couple of practices:
docker rm [CONTAINER_ID]
.docker rmi [IMAGE_ID]
.Dockerfile > (Build) > Image > (Run) > Container.
Dockerfile: contains a set of docker instructions that provisions your operating system the way you like, and installs/configure all your software's.
Image: compiled Dockerfile. Saves you time from rebuilding the Dockerfile every time you need to run a container. And it's a way to hide your provision code.
Container: the virtual operating system itself, you can ssh into it and run any commands you wish, as if it's a real environment. You can run 1000+ containers from the same Image.
A Docker image packs up the application and environment required by the application to run, and a container is a running instance of the image.
Images are the packing part of docker, analogous to "source code" or a "program". Containers are the execution part of docker, analogous to a "process".
In the question, only the "program" part is referred to and that's the image. The "running" part of docker is the container. When a container is run and changes are made, it's as if the process makes a change in it's own source code and saves it as the new image.
As many answers pointed this out: You build Dockerfile to get an image and you run image to get a container.
However, following steps helped me get a better feel for what Docker image and container are:
1) Build Dockerfile:
docker build -t my_image dir_with_dockerfile
2) Save the image to
.tar
filedocker save -o my_file.tar my_image_id
my_file.tar
will store the image. Open it withtar -xvf my_file.tar
, and you will get to see all the layers. If you dive deeper into each layer you can see what changes were added in each layer. (They should be pretty close to commands in the Dockerfile).3) To take a look inside of a container, you can do:
sudo docker run -it my_image bash
and you can see that is very much like an OS.
Workflow
Here is the end-to-end workflow showing the various commands and their associated inputs and outputs. That should clarify the relationship between an image and a container.
To list the images you could run, execute:
To list the containers you could execute commands on: