2014-05-21 21:05:19 +00:00
|
|
|
page_title: Working with Docker Images
|
|
|
|
page_description: How to work with Docker images.
|
2014-06-01 20:48:04 +00:00
|
|
|
page_keywords: documentation, docs, the docker guide, docker guide, docker, docker platform, virtualization framework, docker.io, Docker images, Docker image, image management, Docker repos, Docker repositories, docker, docker tag, docker tags, Docker Hub, collaboration
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
# Working with Docker Images
|
|
|
|
|
|
|
|
In the [introduction](/introduction/) we've discovered that Docker
|
|
|
|
images are the basis of containers. In the
|
|
|
|
[previous](/userguide/dockerizing/) [sections](/userguide/usingdocker/)
|
|
|
|
we've used Docker images that already exist, for example the `ubuntu`
|
|
|
|
image and the `training/webapp` image.
|
|
|
|
|
|
|
|
We've also discovered that Docker stores downloaded images on the Docker
|
|
|
|
host. If an image isn't already present on the host then it'll be
|
|
|
|
downloaded from a registry: by default the
|
2014-06-01 20:48:04 +00:00
|
|
|
[Docker Hub](https://hub.docker.com) public registry.
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
In this section we're going to explore Docker images a bit more
|
|
|
|
including:
|
|
|
|
|
|
|
|
* Managing and working with images locally on your Docker host;
|
|
|
|
* Creating basic images;
|
2014-06-01 20:48:04 +00:00
|
|
|
* Uploading images to [Docker Hub](https://hub.docker.com).
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
## Listing images on the host
|
|
|
|
|
|
|
|
Let's start with listing the images we have locally on our host. You can
|
|
|
|
do this using the `docker images` command like so:
|
|
|
|
|
|
|
|
$ sudo docker images
|
|
|
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
|
|
|
training/webapp latest fc77f57ad303 3 weeks ago 280.5 MB
|
|
|
|
ubuntu 13.10 5e019ab7bf6d 4 weeks ago 180 MB
|
|
|
|
ubuntu saucy 5e019ab7bf6d 4 weeks ago 180 MB
|
|
|
|
ubuntu 12.04 74fe38d11401 4 weeks ago 209.6 MB
|
|
|
|
ubuntu precise 74fe38d11401 4 weeks ago 209.6 MB
|
|
|
|
ubuntu 12.10 a7cf8ae4e998 4 weeks ago 171.3 MB
|
|
|
|
ubuntu quantal a7cf8ae4e998 4 weeks ago 171.3 MB
|
|
|
|
ubuntu 14.04 99ec81b80c55 4 weeks ago 266 MB
|
|
|
|
ubuntu latest 99ec81b80c55 4 weeks ago 266 MB
|
|
|
|
ubuntu trusty 99ec81b80c55 4 weeks ago 266 MB
|
|
|
|
ubuntu 13.04 316b678ddf48 4 weeks ago 169.4 MB
|
|
|
|
ubuntu raring 316b678ddf48 4 weeks ago 169.4 MB
|
|
|
|
ubuntu 10.04 3db9c44f4520 4 weeks ago 183 MB
|
|
|
|
ubuntu lucid 3db9c44f4520 4 weeks ago 183 MB
|
|
|
|
|
|
|
|
We can see the images we've previously used in our [user guide](/userguide/).
|
2014-06-01 20:48:04 +00:00
|
|
|
Each has been downloaded from [Docker Hub](https://hub.docker.com) when we
|
2014-05-21 21:05:19 +00:00
|
|
|
launched a container using that image.
|
|
|
|
|
|
|
|
We can see three crucial pieces of information about our images in the listing.
|
|
|
|
|
|
|
|
* What repository they came from, for example `ubuntu`.
|
|
|
|
* The tags for each image, for example `14.04`.
|
|
|
|
* The image ID of each image.
|
|
|
|
|
|
|
|
A repository potentially holds multiple variants of an image. In the case of
|
|
|
|
our `ubuntu` image we can see multiple variants covering Ubuntu 10.04, 12.04,
|
|
|
|
12.10, 13.04, 13.10 and 14.04. Each variant is identified by a tag and you can
|
|
|
|
refer to a tagged image like so:
|
|
|
|
|
|
|
|
ubuntu:14.04
|
|
|
|
|
|
|
|
So when we run a container we refer to a tagged image like so:
|
|
|
|
|
|
|
|
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
|
|
|
|
|
|
|
|
If instead we wanted to build an Ubuntu 12.04 image we'd use:
|
|
|
|
|
|
|
|
$ sudo docker run -t -i ubuntu:12.04 /bin/bash
|
|
|
|
|
|
|
|
If you don't specify a variant, for example you just use `ubuntu`, then Docker
|
|
|
|
will default to using the `ubunut:latest` image.
|
|
|
|
|
|
|
|
> **Tip:**
|
|
|
|
> We recommend you always use a specific tagged image, for example
|
|
|
|
> `ubuntu:12.04`. That way you always know exactly what variant of an image is
|
|
|
|
> being used.
|
|
|
|
|
|
|
|
## Getting a new image
|
|
|
|
|
|
|
|
So how do we get new images? Well Docker will automatically download any image
|
|
|
|
we use that isn't already present on the Docker host. But this can potentially
|
|
|
|
add some time to the launch of a container. If we want to pre-load an image we
|
|
|
|
can download it using the `docker pull` command. Let's say we'd like to
|
|
|
|
download the `centos` image.
|
|
|
|
|
|
|
|
$ sudo docker pull centos
|
|
|
|
Pulling repository centos
|
|
|
|
b7de3133ff98: Pulling dependent layers
|
|
|
|
5cc9e91966f7: Pulling fs layer
|
|
|
|
511136ea3c5a: Download complete
|
|
|
|
ef52fb1fe610: Download complete
|
|
|
|
. . .
|
|
|
|
|
|
|
|
We can see that each layer of the image has been pulled down and now we
|
|
|
|
can run a container from this image and we won't have to wait to
|
|
|
|
download the image.
|
|
|
|
|
|
|
|
$ sudo docker run -t -i centos /bin/bash
|
|
|
|
bash-4.1#
|
|
|
|
|
|
|
|
## Finding images
|
|
|
|
|
|
|
|
One of the features of Docker is that a lot of people have created Docker
|
|
|
|
images for a variety of purposes. Many of these have been uploaded to
|
2014-06-01 20:48:04 +00:00
|
|
|
[Docker Hub](https://hub.docker.com). We can search these images on the
|
|
|
|
[Docker Hub](https://hub.docker.com) website.
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
![indexsearch](/userguide/search.png)
|
|
|
|
|
|
|
|
We can also search for images on the command line using the `docker search`
|
|
|
|
command. Let's say our team wants an image with Ruby and Sinatra installed on
|
|
|
|
which to do our web application development. We can search for a suitable image
|
|
|
|
by using the `docker search` command to find all the images that contain the
|
|
|
|
term `sinatra`.
|
|
|
|
|
|
|
|
$ sudo docker search sinatra
|
2014-06-02 18:48:58 +00:00
|
|
|
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
2014-05-21 21:05:19 +00:00
|
|
|
training/sinatra Sinatra training image 0 [OK]
|
|
|
|
marceldegraaf/sinatra Sinatra test app 0
|
|
|
|
mattwarren/docker-sinatra-demo 0 [OK]
|
|
|
|
luisbebop/docker-sinatra-hello-world 0 [OK]
|
|
|
|
bmorearty/handson-sinatra handson-ruby + Sinatra for Hands on with D... 0
|
|
|
|
subwiz/sinatra 0
|
|
|
|
bmorearty/sinatra 0
|
|
|
|
. . .
|
|
|
|
|
|
|
|
We can see we've returned a lot of images that use the term `sinatra`. We've
|
|
|
|
returned a list of image names, descriptions, Stars (which measure the social
|
|
|
|
popularity of images - if a user likes an image then they can "star" it), and
|
2014-06-02 18:48:58 +00:00
|
|
|
the Official and Automated build statuses. Official repositories are built and
|
|
|
|
maintained by the [Stackbrew](https://github.com/dotcloud/stackbrew) project,
|
|
|
|
and Automated repositories are [Automated Builds](
|
|
|
|
/userguide/dockerrepos/#automated-builds) that allow you to validate the source
|
|
|
|
and content of an image.
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
We've reviewed the images available to use and we decided to use the
|
|
|
|
`training/sinatra` image. So far we've seen two types of images repositories,
|
|
|
|
images like `ubuntu`, which are called base or root images. These base images
|
|
|
|
are provided by Docker Inc and are built, validated and supported. These can be
|
|
|
|
identified by their single word names.
|
|
|
|
|
|
|
|
We've also seen user images, for example the `training/sinatra` image we've
|
|
|
|
chosen. A user image belongs to a member of the Docker community and is built
|
|
|
|
and maintained by them. You can identify user images as they are always
|
|
|
|
prefixed with the user name, here `training`, of the user that created them.
|
|
|
|
|
|
|
|
## Pulling our image
|
|
|
|
|
|
|
|
We've identified a suitable image, `training/sinatra`, and now we can download it using the `docker pull` command.
|
|
|
|
|
|
|
|
$ sudo docker pull training/sinatra
|
|
|
|
|
|
|
|
The team can now use this image by run their own containers.
|
|
|
|
|
|
|
|
$ sudo docker run -t -i training/sinatra /bin/bash
|
|
|
|
root@a8cb6ce02d85:/#
|
|
|
|
|
|
|
|
## Creating our own images
|
|
|
|
|
|
|
|
The team has found the `training/sinatra` image pretty useful but it's not quite what
|
|
|
|
they need and we need to make some changes to it. There are two ways we can
|
|
|
|
update and create images.
|
|
|
|
|
|
|
|
1. We can update a container created from an image and commit the results to an image.
|
|
|
|
2. We can use a `Dockerfile` to specify instructions to create an image.
|
|
|
|
|
|
|
|
### Updating and committing an image
|
|
|
|
|
|
|
|
To update an image we first need to create a container from the image
|
|
|
|
we'd like to update.
|
|
|
|
|
|
|
|
$ sudo docker run -t -i training/sinatra /bin/bash
|
|
|
|
root@0b2616b0e5a8:/#
|
|
|
|
|
|
|
|
> **Note:**
|
|
|
|
> Take note of the container ID that has been created, `0b2616b0e5a8`, as we'll
|
|
|
|
> need it in a moment.
|
|
|
|
|
|
|
|
Inside our running container let's add the `json` gem.
|
|
|
|
|
|
|
|
root@0b2616b0e5a8:/# gem install json
|
|
|
|
|
|
|
|
Once this has completed let's exit our container using the `exit`
|
|
|
|
command.
|
|
|
|
|
|
|
|
Now we have a container with the change we want to make. We can then
|
|
|
|
commit a copy of this container to an image using the `docker commit`
|
|
|
|
command.
|
|
|
|
|
|
|
|
$ sudo docker commit -m="Added json gem" -a="Kate Smith" \
|
|
|
|
0b2616b0e5a8 ouruser/sinatra:v2
|
|
|
|
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
|
|
|
|
|
|
|
|
Here we've used the `docker commit` command. We've specified two flags: `-m`
|
|
|
|
and `-a`. The `-m` flag allows us to specify a commit message, much like you
|
|
|
|
would with a commit on a version control system. The `-a` flag allows us to
|
|
|
|
specify an author for our update.
|
|
|
|
|
|
|
|
We've also specified the container we want to create this new image from,
|
|
|
|
`0b2616b0e5a8` (the ID we recorded earlier) and we've specified a target for
|
|
|
|
the image:
|
|
|
|
|
|
|
|
ouruser/sinatra:v2
|
|
|
|
|
|
|
|
Let's break this target down. It consists of a new user, `ouruser`, that we're
|
|
|
|
writing this image to. We've also specified the name of the image, here we're
|
|
|
|
keeping the original image name `sinatra`. Finally we're specifying a tag for
|
|
|
|
the image: `v2`.
|
|
|
|
|
|
|
|
We can then look at our new `ouruser/sinatra` image using the `docker images`
|
|
|
|
command.
|
|
|
|
|
|
|
|
$ sudo docker images
|
|
|
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
|
|
|
training/sinatra latest 5bc342fa0b91 10 hours ago 446.7 MB
|
|
|
|
ouruser/sinatra v2 3c59e02ddd1a 10 hours ago 446.7 MB
|
|
|
|
ouruser/sinatra latest 5db5f8471261 10 hours ago 446.7 MB
|
|
|
|
|
|
|
|
To use our new image to create a container we can then:
|
|
|
|
|
|
|
|
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
|
|
|
|
root@78e82f680994:/#
|
|
|
|
|
|
|
|
### Building an image from a `Dockerfile`
|
|
|
|
|
|
|
|
Using the `docker commit` command is a pretty simple way of extending an image
|
|
|
|
but it's a bit cumbersome and it's not easy to share a development process for
|
|
|
|
images amongst a team. Instead we can use a new command, `docker build`, to
|
|
|
|
build new images from scratch.
|
|
|
|
|
|
|
|
To do this we create a `Dockerfile` that contains a set of instructions that
|
|
|
|
tell Docker how to build our image.
|
|
|
|
|
|
|
|
Let's create a directory and a `Dockerfile` first.
|
|
|
|
|
|
|
|
$ mkdir sinatra
|
|
|
|
$ cd sinatra
|
|
|
|
$ touch Dockerfile
|
|
|
|
|
|
|
|
Each instructions creates a new layer of the image. Let's look at a simple
|
|
|
|
example now for building our own Sinatra image for our development team.
|
|
|
|
|
|
|
|
# This is a comment
|
|
|
|
FROM ubuntu:14.04
|
|
|
|
MAINTAINER Kate Smith <ksmith@example.com>
|
|
|
|
RUN apt-get -qq update
|
|
|
|
RUN apt-get -qqy install ruby ruby-dev
|
|
|
|
RUN gem install sinatra
|
|
|
|
|
|
|
|
Let's look at what our `Dockerfile` does. Each instruction prefixes a statement and is capitalized.
|
|
|
|
|
|
|
|
INSTRUCTION statement
|
|
|
|
|
|
|
|
> **Note:**
|
|
|
|
> We use `#` to indicate a comment
|
|
|
|
|
|
|
|
The first instruction `FROM` tells Docker what the source of our image is, in
|
|
|
|
this case we're basing our new image on an Ubuntu 14.04 image.
|
|
|
|
|
|
|
|
Next we use the `MAINTAINER` instruction to specify who maintains our new image.
|
|
|
|
|
|
|
|
Lastly, we've specified three `RUN` instructions. A `RUN` instruction executes
|
|
|
|
a command inside the image, for example installing a package. Here we're
|
|
|
|
updating our APT cache, installing Ruby and RubyGems and then installing the
|
|
|
|
Sinatra gem.
|
|
|
|
|
|
|
|
> **Note:**
|
|
|
|
> There are [a lot more instructions available to us in a Dockerfile](/reference/builder).
|
|
|
|
|
|
|
|
Now let's take our `Dockerfile` and use the `docker build` command to build an image.
|
|
|
|
|
|
|
|
$ sudo docker build -t="ouruser/sinatra:v2" .
|
|
|
|
Uploading context 2.56 kB
|
|
|
|
Uploading context
|
|
|
|
Step 0 : FROM ubuntu:14.04
|
|
|
|
---> 99ec81b80c55
|
|
|
|
Step 1 : MAINTAINER Kate Smith <ksmith@example.com>
|
|
|
|
---> Running in 7c5664a8a0c1
|
|
|
|
---> 2fa8ca4e2a13
|
|
|
|
Removing intermediate container 7c5664a8a0c1
|
|
|
|
Step 2 : RUN apt-get -qq update
|
|
|
|
---> Running in b07cc3fb4256
|
|
|
|
---> 50d21070ec0c
|
|
|
|
Removing intermediate container b07cc3fb4256
|
|
|
|
Step 3 : RUN apt-get -qqy install ruby ruby-dev
|
|
|
|
---> Running in a5b038dd127e
|
|
|
|
Selecting previously unselected package libasan0:amd64.
|
|
|
|
(Reading database ... 11518 files and directories currently installed.)
|
|
|
|
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
|
|
|
|
. . .
|
|
|
|
Setting up ruby (1:1.9.3.4) ...
|
|
|
|
Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...
|
|
|
|
Processing triggers for libc-bin (2.19-0ubuntu6) ...
|
|
|
|
---> 2acb20f17878
|
|
|
|
Removing intermediate container a5b038dd127e
|
|
|
|
Step 4 : RUN gem install sinatra
|
|
|
|
---> Running in 5e9d0065c1f7
|
|
|
|
. . .
|
|
|
|
Successfully installed rack-protection-1.5.3
|
|
|
|
Successfully installed sinatra-1.4.5
|
|
|
|
4 gems installed
|
|
|
|
---> 324104cde6ad
|
|
|
|
Removing intermediate container 5e9d0065c1f7
|
|
|
|
Successfully built 324104cde6ad
|
|
|
|
|
|
|
|
We've specified our `docker build` command and used the `-t` flag to identify
|
|
|
|
our new image as belonging to the user `ouruser`, the repository name `sinatra`
|
|
|
|
and given it the tag `v2`.
|
|
|
|
|
|
|
|
We've also specified the location of our `Dockerfile` using the `.` to
|
|
|
|
indicate a `Dockerfile` in the current directory.
|
|
|
|
|
|
|
|
> **Note::**
|
|
|
|
> You can also specify a path to a `Dockerfile`.
|
|
|
|
|
|
|
|
Now we can see the build process at work. The first thing Docker does is
|
|
|
|
upload the build context: basically the contents of the directory you're
|
|
|
|
building in. This is done because the Docker daemon does the actual
|
|
|
|
build of the image and it needs the local context to do it.
|
|
|
|
|
|
|
|
Next we can see each instruction in the `Dockerfile` being executed
|
|
|
|
step-by-step. We can see that each step creates a new container, runs
|
|
|
|
the instruction inside that container and then commits that change -
|
|
|
|
just like the `docker commit` work flow we saw earlier. When all the
|
|
|
|
instructions have executed we're left with the `324104cde6ad` image
|
|
|
|
(also helpfully tagged as `ouruser/sinatra:v2`) and all intermediate
|
|
|
|
containers will get removed to clean things up.
|
|
|
|
|
|
|
|
We can then create a container from our new image.
|
|
|
|
|
|
|
|
$ sudo docker run -t -i ouruser/sinatra /bin/bash
|
|
|
|
root@8196968dac35:/#
|
|
|
|
|
|
|
|
> **Note:**
|
|
|
|
> This is just the briefest introduction to creating images. We've
|
|
|
|
> skipped a whole bunch of other instructions that you can use. We'll see more of
|
|
|
|
> those instructions in later sections of the Guide or you can refer to the
|
|
|
|
> [`Dockerfile`](/reference/builder/) reference for a
|
|
|
|
> detailed description and examples of every instruction.
|
|
|
|
|
|
|
|
## Setting tags on an image
|
|
|
|
|
|
|
|
You can also add a tag to an existing image after you commit or build it. We
|
|
|
|
can do this using the `docker tag` command. Let's add a new tag to our
|
|
|
|
`ouruser/sinatra` image.
|
|
|
|
|
|
|
|
$ sudo docker tag 5db5f8471261 ouruser/sinatra:devel
|
|
|
|
|
|
|
|
The `docker tag` command takes the ID of the image, here `5db5f8471261`, and our
|
|
|
|
user name, the repository name and the new tag.
|
|
|
|
|
|
|
|
Let's see our new tag using the `docker images` command.
|
|
|
|
|
|
|
|
$ sudo docker images ouruser/sinatra
|
|
|
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
|
|
|
ouruser/sinatra latest 5db5f8471261 11 hours ago 446.7 MB
|
|
|
|
ouruser/sinatra devel 5db5f8471261 11 hours ago 446.7 MB
|
|
|
|
ouruser/sinatra v2 5db5f8471261 11 hours ago 446.7 MB
|
|
|
|
|
2014-06-01 20:48:04 +00:00
|
|
|
## Push an image to Docker Hub
|
2014-05-21 21:05:19 +00:00
|
|
|
|
2014-06-01 20:48:04 +00:00
|
|
|
Once you've built or created a new image you can push it to [Docker
|
|
|
|
Hub](https://hub.docker.com) using the `docker push` command. This
|
|
|
|
allows you to share it with others, either publicly, or push it into [a
|
|
|
|
private repository](https://registry.hub.docker.com/plans/).
|
2014-05-21 21:05:19 +00:00
|
|
|
|
|
|
|
$ sudo docker push ouruser/sinatra
|
|
|
|
The push refers to a repository [ouruser/sinatra] (len: 1)
|
|
|
|
Sending image list
|
|
|
|
Pushing repository ouruser/sinatra (3 tags)
|
|
|
|
. . .
|
|
|
|
|
|
|
|
## Remove an image from the host
|
|
|
|
|
|
|
|
You can also remove images on your Docker host in a way [similar to
|
|
|
|
containers](
|
|
|
|
/userguide/usingdocker) using the `docker rmi` command.
|
|
|
|
|
|
|
|
Let's delete the `training/sinatra` image as we don't need it anymore.
|
|
|
|
|
|
|
|
$ docker rmi training/sinatra
|
|
|
|
Untagged: training/sinatra:latest
|
|
|
|
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
|
|
|
|
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
|
|
|
|
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0
|
|
|
|
|
|
|
|
> **Note:** In order to remove an image from the host, please make sure
|
|
|
|
> that there are no containers actively based on it.
|
|
|
|
|
|
|
|
# Next steps
|
|
|
|
|
|
|
|
Until now we've seen how to build individual applications inside Docker
|
|
|
|
containers. Now learn how to build whole application stacks with Docker
|
|
|
|
by linking together multiple Docker containers.
|
|
|
|
|
|
|
|
Go to [Linking Containers Together](/userguide/dockerlinks).
|
|
|
|
|