In the introduction we've discovered that Docker images are the basis of containers. In the previous sectionswe've
used Docker images that already exist, for example the ubuntu image
and thetraining/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 Docker
Hub public registry.
In this section we're going to explore Docker images a bit more including:
Managing and working with images locally on your Docker host;
We can see three crucial pieces of information about our images in the listing.
在列出信息中,我们可以看到3个字段信息
What repository they came from, for example ubuntu.来自于哪个仓库,比如ubuntu
The tags for each image, for example 14.04.image的标记,比如
14.04
The image ID of each image.它的ID号
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:
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.
提示:我们建议最好指定发行版,只有这样你才可以保证你真正使用的image是那个
Getting a new image
获取一个新的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.
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.
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 Docker
Hub. We can search these images on the Docker Hubwebsite.
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
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
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 the Official and Automated build statuses. Official repositories are built and maintained by the Stackbrew project,
and Automated repositories are Automated Builds that allow you to validate the source and content of
an image.
We've 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.
The team can now use this image by run their own containers.
然后我们就可以使用这个image来启动容器了
$ sudo docker run -t -i training/sinatra /bin/bash
root@a8cb6ce02d85:/#
Creating our own images
创建我们自己的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.
别人的镜像虽然好,但不一定适合我们。我们可以对他们做一些改变,有2中方法:
We can update a container created from an image and commit the results to an image。使用image启动容器,并做更新后提交结果到新的image
We can use a Dockerfile to
specify instructions to create an image. 使用dockerfile 创建新的image
Updating and committing an image
更新并提交一个image
To update an image we first need to create a container from the image we'd like to update.
当我们要更新一个image时,我们先使用它来启动一个容器
$ 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.
注意:记住容器的ID ,稍后我们还会用到
Inside our running container let's add the json gem.
这里我们在容器中添加json gem
root@0b2616b0e5a8:/# gem install json
Once this has completed let's exit our container using the exit command.
当结束后,我们使用exit来退出
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.
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.
-m 来指定提交的信息,跟我们使用的版本控制工具一样。-a 可以指定我们更新的用户信息
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:
指定我们要从哪个容器ID来创建我们的副本,最后指定目标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.
使用docker images来查看我们创建的新image
$ 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:
使用新的image来启动容器
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
root@78e82f680994:/#
Building an image from a Dockerfile
从dockerfile 来创建 image
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.
# 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.
FROM指令告诉docker 使用哪个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.
Now let's take our Dockerfile and
use the docker build command to
build an image.
现在,让我们来使用docker build来通过dockerfile创建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.
使用-t标记来指定新的image的用户信息和命令
We've also specified the location of our Dockerfile using
the . to indicate a Dockerfile in
the current directory.
使用了.来指出dockerfile的位置在当前目录
Note: You can also specify a path to a Dockerfile.
注意:你也可以指定一个dockfile的路径
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.
Note: An image can't have more than 127 layers regardless of the storage driver. This limitation is set globally to encourage optimization of the overall size
of images.
注意:一个image不能
We can then create a container from our new image.
$ sudo docker run -t -i ouruser/sinatra:v2 /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
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
Push an image to Docker Hub
Once you've built or created a new image you can push it to Docker Hub using the docker
pushcommand. This allows you to share it with others, either publicly, or push it into a private repository.
使用docker push上传image
$ 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
从本地移除image
You can also remove images on your Docker host in a way similar to containers using the docker
rmicommand.
dcoker rmi 移除
Let's delete the training/sinatra image
as we don't need it anymore.
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.