Initial commit

This commit is contained in:
Ria Bhatia
2017-12-04 13:32:57 -06:00
committed by Erik St. Martin
commit 0075e5b0f3
9056 changed files with 2523100 additions and 0 deletions

View File

@@ -0,0 +1,554 @@
<!--[metadata]>
+++
aliases = ["/engine/userguide/dockerimages/"]
title = "Build your own images"
description = "How to work with Docker images."
keywords = ["documentation, docs, the docker guide, docker guide, docker, docker platform, docker.io, Docker images, Docker image, image management, Docker repos, Docker repositories, docker, docker tag, docker tags, Docker Hub, collaboration"]
[menu.main]
parent = "engine_learn"
weight = -4
+++
<![end-metadata]-->
# Build your own images
Docker images are the basis of containers. Each time you've used `docker run`
you told it which image you wanted. In the previous sections of the guide you
used Docker images that already exist, for example the `ubuntu` image and the
`training/webapp` image.
You 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 Registry](https://registry.hub.docker.com).
In this section you'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 Hub Registry](https://registry.hub.docker.com).
## Listing images on the host
Let's start with listing the images you have locally on our host. You can
do this using the `docker images` command like so:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 1d073211c498 3 days ago 187.9 MB
busybox latest 2c5ac3f849df 5 days ago 1.113 MB
training/webapp latest 54bb4e8718e8 5 months ago 348.7 MB
You can see the images you've previously used in the user guide.
Each has been downloaded from [Docker Hub](https://hub.docker.com) when you
launched a container using that image. When you list images, you get three crucial pieces of information 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.
> **Tip:**
> You can use [a third-party dockviz tool](https://github.com/justone/dockviz)
> or the [Image layers site](https://imagelayers.io/) to display
> visualizations of image data.
A repository potentially holds multiple variants of an image. In the case of
our `ubuntu` image you 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 you run a container you refer to a tagged image like so:
$ docker run -t -i ubuntu:14.04 /bin/bash
If instead you wanted to run an Ubuntu 12.04 image you'd use:
$ 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 `ubuntu:latest` image.
> **Tip:**
> You should always specify an image tag, for example `ubuntu:14.04`.
> That way, you always know exactly what variant of an image you are using.
> This is useful for troubleshooting and debugging.
## Getting a new image
So how do you get new images? Well Docker will automatically download any image
you use that isn't already present on the Docker host. But this can potentially
add some time to the launch of a container. If you want to pre-load an image you
can download it using the `docker pull` command. Suppose you'd like to
download the `centos` image.
$ docker pull centos
Pulling repository centos
b7de3133ff98: Pulling dependent layers
5cc9e91966f7: Pulling fs layer
511136ea3c5a: Download complete
ef52fb1fe610: Download complete
. . .
Status: Downloaded newer image for centos
You can see that each layer of the image has been pulled down and now you
can run a container from this image and you won't have to wait to
download the image.
$ 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 Hub](https://hub.docker.com). You can search these images on the
[Docker Hub](https://hub.docker.com) website.
![indexsearch](search.png)
You can also search for images on the command line using the `docker search`
command. Suppose your team wants an image with Ruby and Sinatra installed on
which to do our web application development. You can search for a suitable image
by using the `docker search` command to find all the images that contain the
term `sinatra`.
$ 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
. . .
You can see the command returns a lot of images that use the term `sinatra`.
You've received 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](https://docs.docker.com/docker-hub/official_repos) are a carefully
curated set of Docker repositories supported by Docker, Inc. Automated
repositories are [Automated Builds](dockerrepos.md#automated-builds) that allow
you to validate the source and content of an image.
You've reviewed the images available to use and you decided to use the
`training/sinatra` image. So far you'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.
You've also seen user images, for example the `training/sinatra` image you'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
You've identified a suitable image, `training/sinatra`, and now you can download it using the `docker pull` command.
$ docker pull training/sinatra
The team can now use this image by running their own containers.
$ 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 you need to make some changes to it. There are two ways you
can update and create images.
1. You can update a container created from an image and commit the results to an image.
2. You can use a `Dockerfile` to specify instructions to create an image.
### Updating and committing an image
To update an image you first need to create a container from the image
you'd like to update.
$ docker run -t -i training/sinatra /bin/bash
root@0b2616b0e5a8:/#
> **Note:**
> Take note of the container ID that has been created, `0b2616b0e5a8`, as you'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 you have a container with the change you want to make. You can then
commit a copy of this container to an image using the `docker commit`
command.
$ docker commit -m "Added json gem" -a "Kate Smith" \
0b2616b0e5a8 ouruser/sinatra:v2
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
Here you've used the `docker commit` command. You'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.
You've also specified the container you want to create this new image from,
`0b2616b0e5a8` (the ID you recorded earlier) and you've specified a target for
the image:
ouruser/sinatra:v2
Break this target down. It consists of a new user, `ouruser`, that you're
writing this image to. You've also specified the name of the image, here you're
keeping the original image name `sinatra`. Finally you're specifying a tag for
the image: `v2`.
You can then look at our new `ouruser/sinatra` image using the `docker images`
command.
$ docker images
REPOSITORY TAG IMAGE ID CREATED 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 you can then:
$ 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 you can use a new command, `docker build`, to
build new images from scratch.
To do this you create a `Dockerfile` that contains a set of instructions that
tell Docker how to build our image.
First, create a directory and a `Dockerfile`.
$ mkdir sinatra
$ cd sinatra
$ touch Dockerfile
If you are using Docker Machine on Windows, you may access your host
directory by `cd` to `/c/Users/your_user_name`.
Each instruction creates a new layer of the image. Try a simple example now for
building your own Sinatra image for your fictitious development team.
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get update && apt-get install -y ruby ruby-dev
RUN gem install sinatra
Examine what your `Dockerfile` does. Each instruction prefixes a statement and
is capitalized.
INSTRUCTION statement
> **Note:** You use `#` to indicate a comment
The first instruction `FROM` tells Docker what the source of our image is, in
this case you're basing our new image on an Ubuntu 14.04 image. The instruction uses the `MAINTAINER` instruction to specify who maintains the new image.
Lastly, you've specified two `RUN` instructions. A `RUN` instruction executes
a command inside the image, for example installing a package. Here you're
updating our APT cache, installing Ruby and RubyGems and then installing the
Sinatra gem.
Now let's take our `Dockerfile` and use the `docker build` command to build an image.
$ docker build -t ouruser/sinatra:v2 .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 1 : FROM ubuntu:14.04
---> e54ca5efa2e9
Step 2 : MAINTAINER Kate Smith <ksmith@example.com>
---> Using cache
---> 851baf55332b
Step 3 : RUN apt-get update && apt-get install -y ruby ruby-dev
---> Running in 3a2558904e9b
Selecting previously unselected package libasan0:amd64.
(Reading database ... 11518 files and directories currently installed.)
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libasan0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libatomic1:amd64.
Preparing to unpack .../libatomic1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libatomic1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libgmp10:amd64.
Preparing to unpack .../libgmp10_2%3a5.1.3+dfsg-1ubuntu1_amd64.deb ...
Unpacking libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...
Selecting previously unselected package libisl10:amd64.
Preparing to unpack .../libisl10_0.12.2-1_amd64.deb ...
Unpacking libisl10:amd64 (0.12.2-1) ...
Selecting previously unselected package libcloog-isl4:amd64.
Preparing to unpack .../libcloog-isl4_0.18.2-1_amd64.deb ...
Unpacking libcloog-isl4:amd64 (0.18.2-1) ...
Selecting previously unselected package libgomp1:amd64.
Preparing to unpack .../libgomp1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libgomp1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libitm1:amd64.
Preparing to unpack .../libitm1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libitm1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libmpfr4:amd64.
Preparing to unpack .../libmpfr4_3.1.2-1_amd64.deb ...
Unpacking libmpfr4:amd64 (3.1.2-1) ...
Selecting previously unselected package libquadmath0:amd64.
Preparing to unpack .../libquadmath0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libquadmath0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libtsan0:amd64.
Preparing to unpack .../libtsan0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libtsan0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libyaml-0-2:amd64.
Preparing to unpack .../libyaml-0-2_0.1.4-3ubuntu3_amd64.deb ...
Unpacking libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...
Selecting previously unselected package libmpc3:amd64.
Preparing to unpack .../libmpc3_1.0.1-1ubuntu1_amd64.deb ...
Unpacking libmpc3:amd64 (1.0.1-1ubuntu1) ...
Selecting previously unselected package openssl.
Preparing to unpack .../openssl_1.0.1f-1ubuntu2.4_amd64.deb ...
Unpacking openssl (1.0.1f-1ubuntu2.4) ...
Selecting previously unselected package ca-certificates.
Preparing to unpack .../ca-certificates_20130906ubuntu2_all.deb ...
Unpacking ca-certificates (20130906ubuntu2) ...
Selecting previously unselected package manpages.
Preparing to unpack .../manpages_3.54-1ubuntu1_all.deb ...
Unpacking manpages (3.54-1ubuntu1) ...
Selecting previously unselected package binutils.
Preparing to unpack .../binutils_2.24-5ubuntu3_amd64.deb ...
Unpacking binutils (2.24-5ubuntu3) ...
Selecting previously unselected package cpp-4.8.
Preparing to unpack .../cpp-4.8_4.8.2-19ubuntu1_amd64.deb ...
Unpacking cpp-4.8 (4.8.2-19ubuntu1) ...
Selecting previously unselected package cpp.
Preparing to unpack .../cpp_4%3a4.8.2-1ubuntu6_amd64.deb ...
Unpacking cpp (4:4.8.2-1ubuntu6) ...
Selecting previously unselected package libgcc-4.8-dev:amd64.
Preparing to unpack .../libgcc-4.8-dev_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package gcc-4.8.
Preparing to unpack .../gcc-4.8_4.8.2-19ubuntu1_amd64.deb ...
Unpacking gcc-4.8 (4.8.2-19ubuntu1) ...
Selecting previously unselected package gcc.
Preparing to unpack .../gcc_4%3a4.8.2-1ubuntu6_amd64.deb ...
Unpacking gcc (4:4.8.2-1ubuntu6) ...
Selecting previously unselected package libc-dev-bin.
Preparing to unpack .../libc-dev-bin_2.19-0ubuntu6_amd64.deb ...
Unpacking libc-dev-bin (2.19-0ubuntu6) ...
Selecting previously unselected package linux-libc-dev:amd64.
Preparing to unpack .../linux-libc-dev_3.13.0-30.55_amd64.deb ...
Unpacking linux-libc-dev:amd64 (3.13.0-30.55) ...
Selecting previously unselected package libc6-dev:amd64.
Preparing to unpack .../libc6-dev_2.19-0ubuntu6_amd64.deb ...
Unpacking libc6-dev:amd64 (2.19-0ubuntu6) ...
Selecting previously unselected package ruby.
Preparing to unpack .../ruby_1%3a1.9.3.4_all.deb ...
Unpacking ruby (1:1.9.3.4) ...
Selecting previously unselected package ruby1.9.1.
Preparing to unpack .../ruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package libruby1.9.1.
Preparing to unpack .../libruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking libruby1.9.1 (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package manpages-dev.
Preparing to unpack .../manpages-dev_3.54-1ubuntu1_all.deb ...
Unpacking manpages-dev (3.54-1ubuntu1) ...
Selecting previously unselected package ruby1.9.1-dev.
Preparing to unpack .../ruby1.9.1-dev_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package ruby-dev.
Preparing to unpack .../ruby-dev_1%3a1.9.3.4_all.deb ...
Unpacking ruby-dev (1:1.9.3.4) ...
Setting up libasan0:amd64 (4.8.2-19ubuntu1) ...
Setting up libatomic1:amd64 (4.8.2-19ubuntu1) ...
Setting up libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...
Setting up libisl10:amd64 (0.12.2-1) ...
Setting up libcloog-isl4:amd64 (0.18.2-1) ...
Setting up libgomp1:amd64 (4.8.2-19ubuntu1) ...
Setting up libitm1:amd64 (4.8.2-19ubuntu1) ...
Setting up libmpfr4:amd64 (3.1.2-1) ...
Setting up libquadmath0:amd64 (4.8.2-19ubuntu1) ...
Setting up libtsan0:amd64 (4.8.2-19ubuntu1) ...
Setting up libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...
Setting up libmpc3:amd64 (1.0.1-1ubuntu1) ...
Setting up openssl (1.0.1f-1ubuntu2.4) ...
Setting up ca-certificates (20130906ubuntu2) ...
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
Setting up manpages (3.54-1ubuntu1) ...
Setting up binutils (2.24-5ubuntu3) ...
Setting up cpp-4.8 (4.8.2-19ubuntu1) ...
Setting up cpp (4:4.8.2-1ubuntu6) ...
Setting up libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...
Setting up gcc-4.8 (4.8.2-19ubuntu1) ...
Setting up gcc (4:4.8.2-1ubuntu6) ...
Setting up libc-dev-bin (2.19-0ubuntu6) ...
Setting up linux-libc-dev:amd64 (3.13.0-30.55) ...
Setting up libc6-dev:amd64 (2.19-0ubuntu6) ...
Setting up manpages-dev (3.54-1ubuntu1) ...
Setting up libruby1.9.1 (1.9.3.484-2ubuntu1) ...
Setting up ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...
Setting up ruby-dev (1:1.9.3.4) ...
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) ...
Processing triggers for ca-certificates (20130906ubuntu2) ...
Updating certificates in /etc/ssl/certs... 164 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
---> c55c31703134
Removing intermediate container 3a2558904e9b
Step 4 : RUN gem install sinatra
---> Running in 6b81cb6313e5
unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping
unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping
Successfully installed rack-1.5.2
Successfully installed tilt-1.4.1
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.5
4 gems installed
Installing ri documentation for rack-1.5.2...
Installing ri documentation for tilt-1.4.1...
Installing ri documentation for rack-protection-1.5.3...
Installing ri documentation for sinatra-1.4.5...
Installing RDoc documentation for rack-1.5.2...
Installing RDoc documentation for tilt-1.4.1...
Installing RDoc documentation for rack-protection-1.5.3...
Installing RDoc documentation for sinatra-1.4.5...
---> 97feabe5d2ed
Removing intermediate container 6b81cb6313e5
Successfully built 97feabe5d2ed
You'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`.
You'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 you 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 you can see each instruction in the `Dockerfile` being executed
step-by-step. You 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 you saw earlier. When all the
instructions have executed you're left with the `97feabe5d2ed` 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.
You can then create a container from our new image.
$ docker run -t -i ouruser/sinatra:v2 /bin/bash
root@8196968dac35:/#
> **Note:**
> This is just a brief 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.md) reference for a
> detailed description and examples of every instruction.
> To help you write a clear, readable, maintainable `Dockerfile`, we've also
> written a [`Dockerfile` Best Practices guide](../eng-image/dockerfile_best-practices.md).
## 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. Now, add a new tag to your
`ouruser/sinatra` image.
$ 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.
Now, see your new tag using the `docker images` command.
$ docker images ouruser/sinatra
REPOSITORY TAG IMAGE ID CREATED 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
## Image Digests
Images that use the v2 or later format have a content-addressable identifier
called a `digest`. As long as the input used to generate the image is
unchanged, the digest value is predictable. To list image digest values, use
the `--digests` flag:
$ docker images --digests | head
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
ouruser/sinatra latest sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf 5db5f8471261 11 hours ago 446.7 MB
When pushing or pulling to a 2.0 registry, the `push` or `pull` command
output includes the image digest. You can `pull` using a digest value.
$ docker pull ouruser/sinatra@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
You can also reference by digest in `create`, `run`, and `rmi` commands, as well as the
`FROM` image reference in a Dockerfile.
## Push an image to Docker Hub
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/).
$ 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](usingdocker.md) using the `docker rmi` command.
Delete the `training/sinatra` image as you don't need it anymore.
$ docker rmi training/sinatra
Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0
> **Note:** To remove an image from the host, please make sure
> that there are no containers actively based on it.
# Next steps
Until now you've seen how to build individual applications inside Docker
containers. Now learn how to build whole application stacks with Docker
by networking together multiple Docker containers.
Go to [Network containers](networkingcontainers.md).

View File

@@ -0,0 +1,212 @@
<!--[metadata]>
+++
aliases = ["/engine/userguide/dockerizing/"]
title = "Hello world in a container"
description = "A simple 'Hello world' exercise that introduced you to Docker."
keywords = ["docker guide, docker, docker platform, how to, dockerize, dockerizing apps, dockerizing applications, container, containers"]
[menu.main]
parent="engine_learn"
weight=-6
+++
<![end-metadata]-->
# Hello world in a container
*So what's this Docker thing all about?*
Docker allows you to run applications, worlds you create, inside containers.
Running an application inside a container takes a single command: `docker run`.
>**Note**: Depending on your Docker system configuration, you may be required to
>preface each `docker` command on this page with `sudo`. To avoid this behavior,
>your system administrator can create a Unix group called `docker` and add users
>to it.
## Run a Hello world
Let's try it now.
$ docker run ubuntu /bin/echo 'Hello world'
Hello world
And you just launched your first container!
So what just happened? Let's step through what the `docker run` command
did.
First we specified the `docker` binary and the command we wanted to
execute, `run`. The `docker run` combination *runs* containers.
Next we specified an image: `ubuntu`. This is the source of the container
we ran. Docker calls this an image. In this case we used the Ubuntu
operating system image.
When you specify an image, Docker looks first for the image on your
Docker host. If it can't find it then it downloads the image from the public
image registry: [Docker Hub](https://hub.docker.com).
Next we told Docker what command to run inside our new container:
/bin/echo 'Hello world'
When our container was launched Docker created a new Ubuntu
environment and then executed the `/bin/echo` command inside it. We saw
the result on the command line:
Hello world
So what happened to our container after that? Well Docker containers
only run as long as the command you specify is active. Here, as soon as
`Hello world` was echoed, the container stopped.
## An interactive container
Let's try the `docker run` command again, this time specifying a new
command to run in our container.
$ docker run -t -i ubuntu /bin/bash
root@af8bae53bdd3:/#
Here we've again specified the `docker run` command and launched an
`ubuntu` image. But we've also passed in two flags: `-t` and `-i`.
The `-t` flag assigns a pseudo-tty or terminal inside our new container
and the `-i` flag allows us to make an interactive connection by
grabbing the standard in (`STDIN`) of the container.
We've also specified a new command for our container to run:
`/bin/bash`. This will launch a Bash shell inside our container.
So now when our container is launched we can see that we've got a
command prompt inside it:
root@af8bae53bdd3:/#
Let's try running some commands inside our container:
root@af8bae53bdd3:/# pwd
/
root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
You can see we've run the `pwd` to show our current directory and can
see we're in the `/` root directory. We've also done a directory listing
of the root directory which shows us what looks like a typical Linux
file system.
You can play around inside this container and when you're done you can
use the `exit` command or enter Ctrl-D to finish.
root@af8bae53bdd3:/# exit
As with our previous container, once the Bash shell process has
finished, the container is stopped.
## A daemonized Hello world
Now a container that runs a command and then exits has some uses but
it's not overly helpful. Let's create a container that runs as a daemon,
like most of the applications we're probably going to run with Docker.
Again we can do this with the `docker run` command:
$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
Wait, what? Where's our "hello world" output? Let's look at what we've run here.
It should look pretty familiar. We ran `docker run` but this time we
specified a flag: `-d`. The `-d` flag tells Docker to run the container
and put it in the background, to daemonize it.
We also specified the same image: `ubuntu`.
Finally, we specified a command to run:
/bin/sh -c "while true; do echo hello world; sleep 1; done"
This is the (hello) world's silliest daemon: a shell script that echoes
`hello world` forever.
So why aren't we seeing any `hello world`'s? Instead Docker has returned
a really long string:
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
This really long string is called a *container ID*. It uniquely
identifies a container so we can work with it.
> **Note:**
> The container ID is a bit long and unwieldy. A bit later,
> we'll see a shorter ID and ways to name our containers to make
> working with them easier.
We can use this container ID to see what's happening with our `hello world` daemon.
Firstly let's make sure our container is running. We can
do that with the `docker ps` command. The `docker ps` command queries
the Docker daemon for information about all the containers it knows
about.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1e5535038e28 ubuntu /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage
Here we can see our daemonized container. The `docker ps` has returned some useful
information about it, starting with a shorter variant of its container ID:
`1e5535038e28`.
We can also see the image we used to build it, `ubuntu`, the command it
is running, its status and an automatically assigned name,
`insane_babbage`.
> **Note:**
> Docker automatically generates names for any containers started.
> We'll see how to specify your own names a bit later.
Okay, so we now know it's running. But is it doing what we asked it to do? To
see this we're going to look inside the container using the `docker logs`
command. Let's use the container name Docker assigned.
$ docker logs insane_babbage
hello world
hello world
hello world
. . .
The `docker logs` command looks inside the container and returns its standard
output: in this case the output of our command `hello world`.
Awesome! Our daemon is working and we've just created our first
Dockerized application!
Now we've established we can create our own containers let's tidy up
after ourselves and stop our detached container. To do this we use the
`docker stop` command.
$ docker stop insane_babbage
insane_babbage
The `docker stop` command tells Docker to politely stop the running
container. If it succeeds it will return the name of the container it
has just stopped.
Let's check it worked with the `docker ps` command.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Excellent. Our container has been stopped.
# Next steps
So far, you launched your first containers using the `docker run` command. You
ran an *interactive container* that ran in the foreground. You also ran a
*detached container* that ran in the background. In the process you learned
about several Docker commands:
* `docker ps` - Lists containers.
* `docker logs` - Shows us the standard output of a container.
* `docker stop` - Stops running containers.
Now, you have the basis learn more about Docker and how to do some more advanced
tasks. Go to ["*Run a simple application*"](usingdocker.md) to actually build a
web application with the Docker client.

View File

@@ -0,0 +1,187 @@
<!--[metadata]>
+++
aliases = ["/engine/userguide/dockerrepos/"]
title = "Store images on Docker Hub"
description = "Learn how to use the Docker Hub to manage Docker images and work flow"
keywords = ["repo, Docker Hub, Docker Hub, registry, index, repositories, usage, pull image, push image, image, documentation"]
[menu.main]
parent = "engine_learn"
+++
<![end-metadata]-->
# Store images on Docker Hub
So far you've learned how to use the command line to run Docker on your local
host. You've learned how to [pull down images](usingdocker.md) to build
containers from existing images and you've learned how to [create your own
images](dockerimages.md).
Next, you're going to learn how to use the [Docker Hub](https://hub.docker.com)
to simplify and enhance your Docker workflows.
The [Docker Hub](https://hub.docker.com) is a public registry maintained by
Docker, Inc. It contains images you can download and use to build
containers. It also provides authentication, work group structure, workflow
tools like webhooks and build triggers, and privacy tools like private
repositories for storing images you don't want to share publicly.
## Docker commands and Docker Hub
Docker itself provides access to Docker Hub services via the `docker search`,
`pull`, `login`, and `push` commands. This page will show you how these commands work.
### Account creation and login
Typically, you'll want to start by creating an account on Docker Hub (if you haven't
already) and logging in. You can create your account directly on
[Docker Hub](https://hub.docker.com/account/signup/), or by running:
$ docker login
This will prompt you for a user name, which will become the public namespace for your
public repositories.
If your user name is available, Docker will prompt you to enter a password and your
e-mail address. It will then automatically log you in. You can now commit and
push your own images up to your repos on Docker Hub.
> **Note:**
> Your authentication credentials will be stored in the `~/.docker/config.json`
> authentication file in your home directory.
## Searching for images
You can search the [Docker Hub](https://hub.docker.com) registry via its search
interface or by using the command line interface. Searching can find images by image
name, user name, or description:
$ docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS 1223 [OK]
tianon/centos CentOS 5 and 6, created using rinse instea... 33
...
There you can see two example results: `centos` and `tianon/centos`. The second
result shows that it comes from the public repository of a user, named
`tianon/`, while the first result, `centos`, doesn't explicitly list a
repository which means that it comes from the trusted top-level namespace for
[Official Repositories](https://docs.docker.com/docker-hub/official_repos/). The `/` character separates
a user's repository from the image name.
Once you've found the image you want, you can download it with `docker pull <imagename>`:
$ docker pull centos
Using default tag: latest
latest: Pulling from library/centos
f1b10cd84249: Pull complete
c852f6d61e65: Pull complete
7322fbe74aa5: Pull complete
Digest: sha256:90305c9112250c7e3746425477f1c4ef112b03b4abe78c612e092037bfecc3b7
Status: Downloaded newer image for centos:latest
You now have an image from which you can run containers.
### Specific Versions or Latest
Using `docker pull centos` is equivalent to using `docker pull centos:latest`.
To pull an image that is not the default latest image you can be more precise
with the image that you want.
For example, to pull version 5 of `centos` use `docker pull centos:centos5`.
In this example, `centos5` is the tag labeling an image in the `centos`
repository for a version of `centos`.
To find a list of tags pointing to currently available versions of a repository
see the [Docker Hub](https://hub.docker.com) registry.
## Contributing to Docker Hub
Anyone can pull public images from the [Docker Hub](https://hub.docker.com)
registry, but if you would like to share your own images, then you must
[register first](https://docs.docker.com/docker-hub/accounts).
## Pushing a repository to Docker Hub
In order to push a repository to its registry, you need to have named an image
or committed your container to a named image as we saw
[here](dockerimages.md).
Now you can push this repository to the registry designated by its name or tag.
$ docker push yourname/newimage
The image will then be uploaded and available for use by your team-mates and/or the
community.
## Features of Docker Hub
Let's take a closer look at some of the features of Docker Hub. You can find more
information [here](https://docs.docker.com/docker-hub/).
* Private repositories
* Organizations and teams
* Automated Builds
* Webhooks
### Private repositories
Sometimes you have images you don't want to make public and share with
everyone. So Docker Hub allows you to have private repositories. You can
sign up for a plan [here](https://registry.hub.docker.com/plans/).
### Organizations and teams
One of the useful aspects of private repositories is that you can share
them only with members of your organization or team. Docker Hub lets you
create organizations where you can collaborate with your colleagues and
manage private repositories. You can learn how to create and manage an organization
[here](https://registry.hub.docker.com/account/organizations/).
### Automated Builds
Automated Builds automate the building and updating of images from
[GitHub](https://www.github.com) or [Bitbucket](http://bitbucket.com), directly on Docker
Hub. It works by adding a commit hook to your selected GitHub or Bitbucket repository,
triggering a build and update when you push a commit.
#### To setup an Automated Build
1. Create a [Docker Hub account](https://hub.docker.com/) and login.
2. Link your GitHub or Bitbucket account through the ["Link Accounts"](https://registry.hub.docker.com/account/accounts/) menu.
3. [Configure an Automated Build](https://registry.hub.docker.com/builds/add/).
4. Pick a GitHub or Bitbucket project that has a `Dockerfile` that you want to build.
5. Pick the branch you want to build (the default is the `master` branch).
6. Give the Automated Build a name.
7. Assign an optional Docker tag to the Build.
8. Specify where the `Dockerfile` is located. The default is `/`.
Once the Automated Build is configured it will automatically trigger a
build and, in a few minutes, you should see your new Automated Build on the [Docker Hub](https://hub.docker.com)
Registry. It will stay in sync with your GitHub and Bitbucket repository until you
deactivate the Automated Build.
To check the output and status of your Automated Build repositories, click on a repository name within the ["Your Repositories" page](https://registry.hub.docker.com/repos/). Automated Builds are indicated by a check-mark icon next to the repository name. Within the repository details page, you may click on the "Build Details" tab to view the status and output of all builds triggered by the Docker Hub.
Once you've created an Automated Build you can deactivate or delete it. You
cannot, however, push to an Automated Build with the `docker push` command.
You can only manage it by committing code to your GitHub or Bitbucket
repository.
You can create multiple Automated Builds per repository and configure them
to point to specific `Dockerfile`'s or Git branches.
#### Build triggers
Automated Builds can also be triggered via a URL on Docker Hub. This
allows you to rebuild an Automated build image on demand.
### Webhooks
Webhooks are attached to your repositories and allow you to trigger an
event when an image or updated image is pushed to the repository. With
a webhook you can specify a target URL and a JSON payload that will be
delivered when the image is pushed.
See the Docker Hub documentation for [more information on
webhooks](https://docs.docker.com/docker-hub/repos/#webhooks)
## Next steps
Go and use Docker!

View File

@@ -0,0 +1,286 @@
<!--[metadata]>
+++
aliases = ["/engine/userguide/dockervolumes/"]
title = "Manage data in containers"
description = "How to manage data inside your Docker containers."
keywords = ["Examples, Usage, volume, docker, documentation, user guide, data, volumes"]
[menu.main]
parent = "engine_learn"
+++
<![end-metadata]-->
# Manage data in containers
So far we've been introduced to some [basic Docker concepts](../containers/usingdocker.md),
seen how to work with [Docker images](../containers/dockerimages.md) as well as learned about
[networking and links between containers](../networking/default_network/dockerlinks.md). In this section we're
going to discuss how you can manage data inside and between your Docker
containers.
We're going to look at the two primary ways you can manage data in
Docker.
* Data volumes, and
* Data volume containers.
## Data volumes
A *data volume* is a specially-designated directory within one or more
containers that bypasses the [*Union File System*](../../reference/glossary.md#union-file-system). Data volumes provide several useful features for persistent or shared data:
- Volumes are initialized when a container is created. If the container's
base image contains data at the specified mount point, that existing data is
copied into the new volume upon volume initialization. (Note that this does
not apply when [mounting a host directory](#mount-a-host-directory-as-a-data-volume).)
- Data volumes can be shared and reused among containers.
- Changes to a data volume are made directly.
- Changes to a data volume will not be included when you update an image.
- Data volumes persist even if the container itself is deleted.
Data volumes are designed to persist data, independent of the container's life
cycle. Docker therefore *never* automatically deletes volumes when you remove
a container, nor will it "garbage collect" volumes that are no longer
referenced by a container.
### Adding a data volume
You can add a data volume to a container using the `-v` flag with the
`docker create` and `docker run` command. You can use the `-v` multiple times
to mount multiple data volumes. Let's mount a single volume now in our web
application container.
$ docker run -d -P --name web -v /webapp training/webapp python app.py
This will create a new volume inside a container at `/webapp`.
> **Note:**
> You can also use the `VOLUME` instruction in a `Dockerfile` to add one or
> more new volumes to any container created from that image.
### Locating a volume
You can locate the volume on the host by utilizing the `docker inspect` command.
$ docker inspect web
The output will provide details on the container configurations including the
volumes. The output should look something similar to the following:
...
Mounts": [
{
"Name": "fac362...80535",
"Source": "/var/lib/docker/volumes/fac362...80535/_data",
"Destination": "/webapp",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
...
You will notice in the above `Source` is specifying the location on the host and
`Destination` is specifying the volume location inside the container. `RW` shows
if the volume is read/write.
### Mount a host directory as a data volume
In addition to creating a volume using the `-v` flag you can also mount a
directory from your Docker daemon's host into a container.
```
$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
```
This command mounts the host directory, `/src/webapp`, into the container at
`/opt/webapp`. If the path `/opt/webapp` already exists inside the container's
image, the `/src/webapp` mount overlays but does not remove the pre-existing
content. Once the mount is removed, the content is accessible again. This is
consistent with the expected behavior of the `mount` command.
The `container-dir` must always be an absolute path such as `/src/docs`.
The `host-dir` can either be an absolute path or a `name` value. If you
supply an absolute path for the `host-dir`, Docker bind-mounts to the path
you specify. If you supply a `name`, Docker creates a named volume by that `name`.
A `name` value must start with an alphanumeric character,
followed by `a-z0-9`, `_` (underscore), `.` (period) or `-` (hyphen).
An absolute path starts with a `/` (forward slash).
For example, you can specify either `/foo` or `foo` for a `host-dir` value.
If you supply the `/foo` value, Docker creates a bind-mount. If you supply
the `foo` specification, Docker creates a named volume.
If you are using Docker Machine on Mac or Windows, your Docker daemon has only limited access to your OS X or Windows filesystem. Docker Machine tries
to auto-share your `/Users` (OS X) or `C:\Users` (Windows) directory. So,
you can mount files or directories on OS X using.
```
docker run -v /Users/<path>:/<container path> ...
```
On Windows, mount directories using:
```
docker run -v /c/Users/<path>:/<container path> ...`
```
All other paths come from your virtual machine's filesystem. For example, if
you are using VirtualBox some other folder available for sharing, you need to do
additional work. In the case of VirtualBox you need to make the host folder
available as a shared folder in VirtualBox. Then, you can mount it using the
Docker `-v` flag.
Mounting a host directory can be useful for testing. For example, you can mount
source code inside a container. Then, change the source code and see its effect
on the application in real time. The directory on the host must be specified as
an absolute path and if the directory doesn't exist Docker will automatically
create it for you. This auto-creation of the host path has been [*deprecated*](#auto-creating-missing-host-paths-for-bind-mounts).
Docker volumes default to mount in read-write mode, but you can also set it to
be mounted read-only.
```
$ docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py
```
Here we've mounted the same `/src/webapp` directory but we've added the `ro`
option to specify that the mount should be read-only.
Because of [limitations in the `mount`
function](http://lists.linuxfoundation.org/pipermail/containers/2015-April/035788.html),
moving subdirectories within the host's source directory can give
access from the container to the host's file system. This requires a malicious
user with access to host and its mounted directory.
>**Note**: The host directory is, by its nature, host-dependent. For this
>reason, you can't mount a host directory from `Dockerfile` because built images
>should be portable. A host directory wouldn't be available on all potential
>hosts.
### Volume labels
Labeling systems like SELinux require that proper labels are placed on volume
content mounted into a container. Without a label, the security system might
prevent the processes running inside the container from using the content. By
default, Docker does not change the labels set by the OS.
To change a label in the container context, you can add either of two suffixes
`:z` or `:Z` to the volume mount. These suffixes tell Docker to relabel file
objects on the shared volumes. The `z` option tells Docker that two containers
share the volume content. As a result, Docker labels the content with a shared
content label. Shared volume labels allow all containers to read/write content.
The `Z` option tells Docker to label the content with a private unshared label.
Only the current container can use a private volume.
### Mount a host file as a data volume
The `-v` flag can also be used to mount a single file - instead of *just*
directories - from the host machine.
$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash
This will drop you into a bash shell in a new container, you will have your bash
history from the host and when you exit the container, the host will have the
history of the commands typed while in the container.
> **Note:**
> Many tools used to edit files including `vi` and `sed --in-place` may result
> in an inode change. Since Docker v1.1.0, this will produce an error such as
> "*sed: cannot rename ./sedKdJ9Dy: Device or resource busy*". In the case where
> you want to edit the mounted file, it is often easiest to instead mount the
> parent directory.
## Creating and mounting a data volume container
If you have some persistent data that you want to share between
containers, or want to use from non-persistent containers, it's best to
create a named Data Volume Container, and then to mount the data from
it.
Let's create a new named container with a volume to share.
While this container doesn't run an application, it reuses the `training/postgres`
image so that all containers are using layers in common, saving disk space.
$ docker create -v /dbdata --name dbstore training/postgres /bin/true
You can then use the `--volumes-from` flag to mount the `/dbdata` volume in another container.
$ docker run -d --volumes-from dbstore --name db1 training/postgres
And another:
$ docker run -d --volumes-from dbstore --name db2 training/postgres
In this case, if the `postgres` image contained a directory called `/dbdata`
then mounting the volumes from the `dbstore` container hides the
`/dbdata` files from the `postgres` image. The result is only the files
from the `dbstore` container are visible.
You can use multiple `--volumes-from` parameters to combine data volumes from
several containers. To find detailed information about `--volumes-from` see the
[Mount volumes from container](../../reference/commandline/run.md#mount-volumes-from-container-volumes-from)
in the `run` command reference.
You can also extend the chain by mounting the volume that came from the
`dbstore` container in yet another container via the `db1` or `db2` containers.
$ docker run -d --name db3 --volumes-from db1 training/postgres
If you remove containers that mount volumes, including the initial `dbstore`
container, or the subsequent containers `db1` and `db2`, the volumes will not
be deleted. To delete the volume from disk, you must explicitly call
`docker rm -v` against the last container with a reference to the volume. This
allows you to upgrade, or effectively migrate data volumes between containers.
> **Note:** Docker will not warn you when removing a container *without*
> providing the `-v` option to delete its volumes. If you remove containers
> without using the `-v` option, you may end up with "dangling" volumes;
> volumes that are no longer referenced by a container.
> You can use `docker volume ls -f dangling=true` to find dangling volumes,
> and use `docker volume rm <volume name>` to remove a volume that's
> no longer needed.
## Backup, restore, or migrate data volumes
Another useful function we can perform with volumes is use them for
backups, restores or migrations. We do this by using the
`--volumes-from` flag to create a new container that mounts that volume,
like so:
$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
Here we've launched a new container and mounted the volume from the
`dbstore` container. We've then mounted a local host directory as
`/backup`. Finally, we've passed a command that uses `tar` to backup the
contents of the `dbdata` volume to a `backup.tar` file inside our
`/backup` directory. When the command completes and the container stops
we'll be left with a backup of our `dbdata` volume.
You could then restore it to the same container, or another that you've made
elsewhere. Create a new container.
$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
Then un-tar the backup file in the new container's data volume.
$ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
You can use the techniques above to automate backup, migration and
restore testing using your preferred tools.
## Important tips on using shared volumes
Multiple containers can also share one or more data volumes. However, multiple containers writing to a single shared volume can cause data corruption. Make sure your applications are designed to write to shared data stores.
Data volumes are directly accessible from the Docker host. This means you can read and write to them with normal Linux tools. In most cases you should not do this as it can cause data corruption if your containers and applications are unaware of your direct access.
# Next steps
Now we've learned a bit more about how to use Docker we're going to see how to
combine Docker with the services available on
[Docker Hub](https://hub.docker.com) including Automated Builds and private
repositories.
Go to [Working with Docker Hub](../containers/dockerrepos.md).

View File

@@ -0,0 +1,19 @@
<!--[metadata]>
+++
title = "Learn by example"
description = "Explains how to work with containers"
keywords = ["docker, introduction, documentation, about, technology, docker.io, user, guide, user's, manual, platform, framework, home, intro"]
[menu.main]
identifier="engine_learn"
parent = "engine_guide"
+++
<![end-metadata]-->
# Learn by example
* [Hello world in a container](dockerizing.md)
* [Run a simple application](usingdocker.md)
* [Build your own images](dockerimages.md)
* [Network containers](networkingcontainers.md)
* [Manage data in containers](dockervolumes.md)
* [Store images on Docker Hub](dockerrepos.md)

View File

@@ -0,0 +1,247 @@
<!--[metadata]>
+++
aliases = ["/engine/userguide/networkigncontainers/"]
title = "Network containers"
description = "How to network Docker containers."
keywords = ["Examples, Usage, volume, docker, documentation, user guide, data, volumes"]
[menu.main]
parent = "engine_learn"
weight = -3
+++
<![end-metadata]-->
# Network containers
If you are working your way through the user guide, you just built and ran a
simple application. You've also built in your own images. This section teaches
you how to network your containers.
## Name a container
You've already seen that each container you create has an automatically
created name; indeed you've become familiar with our old friend
`nostalgic_morse` during this guide. You can also name containers
yourself. This naming provides two useful functions:
* You can name containers that do specific functions in a way
that makes it easier for you to remember them, for example naming a
container containing a web application `web`.
* Names provide Docker with a reference point that allows it to refer to other
containers. There are several commands that support this and you'll use one in an exercise later.
You name your container by using the `--name` flag, for example launch a new container called web:
$ docker run -d -P --name web training/webapp python app.py
Use the `docker ps` command to see check the name:
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154->5000/tcp web
You can also use `docker inspect` with the container's name.
$ docker inspect web
[
{
"Id": "3ce51710b34f5d6da95e0a340d32aa2e6cf64857fb8cdb2a6c38f7c56f448143",
"Created": "2015-10-25T22:44:17.854367116Z",
"Path": "python",
"Args": [
"app.py"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
...
Container names must be unique. That means you can only call one container
`web`. If you want to re-use a container name you must delete the old container
(with `docker rm`) before you can reuse the name with a new container. Go ahead and stop and remove your old `web` container.
$ docker stop web
web
$ docker rm web
web
## Launch a container on the default network
Docker includes support for networking containers through the use of **network
drivers**. By default, Docker provides two network drivers for you, the
`bridge` and the `overlay` drivers. You can also write a network driver plugin so
that you can create your own drivers but that is an advanced task.
Every installation of the Docker Engine automatically includes three default networks. You can list them:
$ docker network ls
NETWORK ID NAME DRIVER
18a2866682b8 none null
c288470c46f6 host host
7b369448dccb bridge bridge
The network named `bridge` is a special network. Unless you tell it otherwise, Docker always launches your containers in this network. Try this now:
$ docker run -itd --name=networktest ubuntu
74695c9cea6d9810718fddadc01a727a5dd3ce6a69d09752239736c030599741
Inspecting the network is an easy way to find out the container's IP address.
```bash
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {
"3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
"EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
"EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "9001"
}
}
]
```
You can remove a container from a network by disconnecting the container. To do this, you supply both the network name and the container name. You can also use the container id. In this example, though, the name is faster.
$ docker network disconnect bridge networktest
While you can disconnect a container from a network, you cannot remove the builtin `bridge` network named `bridge`. Networks are natural ways to isolate containers from other containers or other networks. So, as you get more experienced with Docker, you'll want to create your own networks.
## Create your own bridge network
Docker Engine natively supports both bridge networks and overlay networks. A bridge network is limited to a single host running Docker Engine. An overlay network can include multiple hosts and is a more advanced topic. For this example, you'll create a bridge network:
$ docker network create -d bridge my-bridge-network
The `-d` flag tells Docker to use the `bridge` driver for the new network. You could have left this flag off as `bridge` is the default value for this flag. Go ahead and list the networks on your machine:
$ docker network ls
NETWORK ID NAME DRIVER
7b369448dccb bridge bridge
615d565d498c my-bridge-network bridge
18a2866682b8 none null
c288470c46f6 host host
If you inspect the network, you'll find that it has nothing in it.
$ docker network inspect my-bridge-network
[
{
"Name": "my-bridge-network",
"Id": "5a8afc6364bccb199540e133e63adb76a557906dd9ff82b94183fc48c40857ac",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1/16"
}
]
},
"Containers": {},
"Options": {}
}
]
## Add containers to a network
To build web applications that act in concert but do so securely, create a
network. Networks, by definition, provide complete isolation for containers. You
can add containers to a network when you first run a container.
Launch a container running a PostgreSQL database and pass it the `--net=my-bridge-network` flag to connect it to your new network:
$ docker run -d --net=my-bridge-network --name db training/postgres
If you inspect your `my-bridge-network` you'll see it has a container attached.
You can also inspect your container to see where it is connected:
$ docker inspect --format='{{json .NetworkSettings.Networks}}' db
{"my-bridge-network":{"NetworkID":"7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.18.0.1","IPAddress":"172.18.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}}
Now, go ahead and start your by now familiar web application. This time leave off the `-P` flag and also don't specify a network.
$ docker run -d --name web training/webapp python app.py
Which network is your `web` application running under? Inspect the application and you'll find it is running in the default `bridge` network.
$ docker inspect --format='{{json .NetworkSettings.Networks}}' web
{"bridge":{"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.17.0.1","IPAddress":"172.17.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}}
Then, get the IP address of your `web`
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
172.17.0.2
Now, open a shell to your running `db` container:
$ docker exec -it db bash
root@a205f0dd33b2:/# ping 172.17.0.2
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
^C
--- 172.17.0.2 ping statistics ---
44 packets transmitted, 0 received, 100% packet loss, time 43185ms
After a bit, use `CTRL-C` to end the `ping` and you'll find the ping failed. That is because the two containers are running on different networks. You can fix that. Then, use the `exit` command to close the container.
Docker networking allows you to attach a container to as many networks as you like. You can also attach an already running container. Go ahead and attach your running `web` app to the `my-bridge-network`.
$ docker network connect my-bridge-network web
Open a shell into the `db` application again and try the ping command. This time just use the container name `web` rather than the IP Address.
$ docker exec -it db bash
root@a205f0dd33b2:/# ping web
PING web (172.18.0.3) 56(84) bytes of data.
64 bytes from web (172.18.0.3): icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from web (172.18.0.3): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from web (172.18.0.3): icmp_seq=3 ttl=64 time=0.066 ms
^C
--- web ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.060/0.073/0.095/0.018 ms
The `ping` shows it is contacting a different IP address, the address on the `my-bridge-network` which is different from its address on the `bridge` network.
## Next steps
Now that you know how to network containers, see [how to manage data in containers](dockervolumes.md).

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,306 @@
<!--[metadata]>
+++
title = "Run a simple application"
description = "Learn how to manage and operate Docker containers."
keywords = ["docker, the docker guide, documentation, docker.io, monitoring containers, docker top, docker inspect, docker port, ports, docker logs, log, Logs"]
[menu.main]
parent="engine_learn"
weight=-5
+++
<![end-metadata]-->
# Run a simple application
In the ["*Hello world in a container*"](dockerizing.md) you launched your
first containers using the `docker run` command. You ran an *interactive container* that ran in the foreground. You also ran a *detached container* that ran in the background. In the process you learned about several Docker commands:
* `docker ps` - Lists containers.
* `docker logs` - Shows us the standard output of a container.
* `docker stop` - Stops running containers.
## Learn about the Docker client
If you didn't realize it yet, you've been using the Docker client each time you
typed `docker` in your Bash terminal. The client is a simple command line client
also known as a command-line interface (CLI). Each action you can take with
the client is a command and each command can take a series of flags and arguments.
# Usage: [sudo] docker [subcommand] [flags] [arguments] ..
# Example:
$ docker run -i -t ubuntu /bin/bash
You can see this in action by using the `docker version` command to return
version information on the currently installed Docker client and daemon.
$ docker version
This command will not only provide you the version of Docker client and
daemon you are using, but also the version of Go (the programming
language powering Docker).
Client:
Version: 1.8.1
API version: 1.20
Go version: go1.4.2
Git commit: d12ea79
Built: Thu Aug 13 02:35:49 UTC 2015
OS/Arch: linux/amd64
Server:
Version: 1.8.1
API version: 1.20
Go version: go1.4.2
Git commit: d12ea79
Built: Thu Aug 13 02:35:49 UTC 2015
OS/Arch: linux/amd64
## Get Docker command help
You can display the help for specific Docker commands. The help details the
options and their usage. To see a list of all the possible commands, use the
following:
$ docker --help
To see usage for a specific command, specify the command with the `--help` flag:
$ docker attach --help
Usage: docker attach [OPTIONS] CONTAINER
Attach to a running container
--help Print usage
--no-stdin Do not attach stdin
--sig-proxy=true Proxy all received signals to the process
> **Note:**
> For further details and examples of each command, see the
> [command reference](../../reference/commandline/cli.md) in this guide.
## Running a web application in Docker
So now you've learned a bit more about the `docker` client you can move onto
the important stuff: running more containers. So far none of the
containers you've run did anything particularly useful, so you can
change that by running an example web application in Docker.
For our web application we're going to run a Python Flask application.
Start with a `docker run` command.
$ docker run -d -P training/webapp python app.py
Review what the command did. You've specified two flags: `-d` and
`-P`. You've already seen the `-d` flag which tells Docker to run the
container in the background. The `-P` flag is new and tells Docker to
map any required network ports inside our container to our host. This
lets us view our web application.
You've specified an image: `training/webapp`. This image is a
pre-built image you've created that contains a simple Python Flask web
application.
Lastly, you've specified a command for our container to run: `python app.py`. This launches our web application.
> **Note:**
> You can see more detail on the `docker run` command in the [command
> reference](../../reference/commandline/run.md) and the [Docker Run
> Reference](../../reference/run.md).
## Viewing our web application container
Now you can see your running container using the `docker ps` command.
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse
You can see you've specified a new flag, `-l`, for the `docker ps`
command. This tells the `docker ps` command to return the details of the
*last* container started.
> **Note:**
> By default, the `docker ps` command only shows information about running
> containers. If you want to see stopped containers too use the `-a` flag.
We can see the same details we saw [when we first Dockerized a
container](dockerizing.md) with one important addition in the `PORTS`
column.
PORTS
0.0.0.0:49155->5000/tcp
When we passed the `-P` flag to the `docker run` command Docker mapped any
ports exposed in our image to our host.
> **Note:**
> We'll learn more about how to expose ports in Docker images when
> [we learn how to build images](dockerimages.md).
In this case Docker has exposed port 5000 (the default Python Flask
port) on port 49155.
Network port bindings are very configurable in Docker. In our last example the
`-P` flag is a shortcut for `-p 5000` that maps port 5000 inside the container
to a high port (from *ephemeral port range* which typically ranges from 32768
to 61000) on the local Docker host. We can also bind Docker containers to
specific ports using the `-p` flag, for example:
$ docker run -d -p 80:5000 training/webapp python app.py
This would map port 5000 inside our container to port 80 on our local
host. You might be asking about now: why wouldn't we just want to always
use 1:1 port mappings in Docker containers rather than mapping to high
ports? Well 1:1 mappings have the constraint of only being able to map
one of each port on your local host.
Suppose you want to test two Python applications: both bound to port 5000 inside
their own containers. Without Docker's port mapping you could only access one at
a time on the Docker host.
So you can now browse to port 49155 in a web browser to
see the application.
![Viewing the web application](webapp1.png).
Our Python application is live!
> **Note:**
> If you have been using a virtual machine on OS X, Windows or Linux,
> you'll need to get the IP of the virtual host instead of using localhost.
> You can do this by running the `docker-machine ip your_vm_name` from your command line or terminal application, for example:
>
> $ docker-machine ip my-docker-vm
> 192.168.99.100
>
> In this case you'd browse to `http://192.168.99.100:49155` for the above example.
## A network port shortcut
Using the `docker ps` command to return the mapped port is a bit clumsy so
Docker has a useful shortcut we can use: `docker port`. To use `docker port` we
specify the ID or name of our container and then the port for which we need the
corresponding public-facing port.
$ docker port nostalgic_morse 5000
0.0.0.0:49155
In this case you've looked up what port is mapped externally to port 5000 inside
the container.
## Viewing the web application's logs
You can also find out a bit more about what's happening with our application and
use another of the commands you've learned, `docker logs`.
$ docker logs -f nostalgic_morse
* Running on http://0.0.0.0:5000/
10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -
This time though you've added a new flag, `-f`. This causes the `docker
logs` command to act like the `tail -f` command and watch the
container's standard out. We can see here the logs from Flask showing
the application running on port 5000 and the access log entries for it.
## Looking at our web application container's processes
In addition to the container's logs we can also examine the processes
running inside it using the `docker top` command.
$ docker top nostalgic_morse
PID USER COMMAND
854 root python app.py
Here we can see our `python app.py` command is the only process running inside
the container.
## Inspecting our web application container
Lastly, we can take a low-level dive into our Docker container using the
`docker inspect` command. It returns a JSON document containing useful
configuration and status information for the specified container.
$ docker inspect nostalgic_morse
You can see a sample of that JSON output.
[{
"ID": "bc533791f3f500b280a9626688bc79e342e3ea0d528efe3a86a51ecb28ea20",
"Created": "2014-05-26T05:52:40.808952951Z",
"Path": "python",
"Args": [
"app.py"
],
"Config": {
"Hostname": "bc533791f3f5",
"Domainname": "",
"User": "",
. . .
We can also narrow down the information we want to return by requesting a
specific element, for example to return the container's IP address we would:
$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nostalgic_morse
172.17.0.5
## Stopping our web application container
Okay you've seen web application working. Now you can stop it using the
`docker stop` command and the name of our container: `nostalgic_morse`.
$ docker stop nostalgic_morse
nostalgic_morse
We can now use the `docker ps` command to check if the container has
been stopped.
$ docker ps -l
## Restarting our web application container
Oops! Just after you stopped the container you get a call to say another
developer needs the container back. From here you have two choices: you
can create a new container or restart the old one. Look at
starting your previous container back up.
$ docker start nostalgic_morse
nostalgic_morse
Now quickly run `docker ps -l` again to see the running container is
back up or browse to the container's URL to see if the application
responds.
> **Note:**
> Also available is the `docker restart` command that runs a stop and
> then start on the container.
## Removing our web application container
Your colleague has let you know that they've now finished with the container
and won't need it again. Now, you can remove it using the `docker rm` command.
$ docker rm nostalgic_morse
Error: Impossible to remove a running container, please stop it first or use -f
2014/05/24 08:12:56 Error: failed to remove one or more containers
What happened? We can't actually remove a running container. This protects
you from accidentally removing a running container you might need. You can try
this again by stopping the container first.
$ docker stop nostalgic_morse
nostalgic_morse
$ docker rm nostalgic_morse
nostalgic_morse
And now our container is stopped and deleted.
> **Note:**
> Always remember that removing a container is final!
# Next steps
Until now you've only used images that you've downloaded from Docker Hub. Next,
you can get introduced to building and sharing our own images.
Go to [Working with Docker Images](dockerimages.md).

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB