|
@@ -0,0 +1,397 @@
|
|
|
|
+page_title: Working with Docker Images
|
|
|
|
+page_description: How to work with Docker images.
|
|
|
|
+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.io, collaboration
|
|
|
|
+
|
|
|
|
+# 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
|
|
|
|
+[Docker.io](https://index.docker.io) 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;
|
|
|
|
+* Creating basic images;
|
|
|
|
+* Uploading images to [Docker.io](https://index.docker.io).
|
|
|
|
+
|
|
|
|
+## 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/).
|
|
|
|
+Each has been downloaded from [Docker.io](https://index.docker.io) when we
|
|
|
|
+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
|
|
|
|
+[Docker.io](https://index.docker.io). We can search these images on the
|
|
|
|
+[Docker.io](https://index.docker.io) website.
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+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 TRUSTED
|
|
|
|
+ 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 Trusted statuses. Official repositories are XXX and Trusted
|
|
|
|
+repositories are [Trusted Build](/userguide/dockerrepos/) that allow you to
|
|
|
|
+validate the source and content of an image.
|
|
|
|
+
|
|
|
|
+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
|
|
|
|
+
|
|
|
|
+## Push an image to Docker.io
|
|
|
|
+
|
|
|
|
+Once you've built or created a new image you can push it to [Docker.io](
|
|
|
|
+https://index.docker.io) using the `docker push` command. This allows you to
|
|
|
|
+share it with others, either publicly, or push it into [a private
|
|
|
|
+repository](https://index.docker.io/plans/).
|
|
|
|
+
|
|
|
|
+ $ 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).
|
|
|
|
+
|