diff --git a/api_test.go b/api_test.go index 0827c9b5a4..700d2c4b2c 100644 --- a/api_test.go +++ b/api_test.go @@ -679,10 +679,82 @@ func TestPostImagesCreate(t *testing.T) { // }) } -// func TestPostImagesInsert(t *testing.T) { -// //FIXME: Implement this test (or remove this endpoint) -// t.Log("Test not implemented") -// } +func TestPostImagesInsert(t *testing.T) { + // runtime, err := newTestRuntime() + // if err != nil { + // t.Fatal(err) + // } + // defer nuke(runtime) + + // srv := &Server{runtime: runtime} + + // stdin, stdinPipe := io.Pipe() + // stdout, stdoutPipe := io.Pipe() + + // // Attach to it + // c1 := make(chan struct{}) + // go func() { + // defer close(c1) + // r := &hijackTester{ + // ResponseRecorder: httptest.NewRecorder(), + // in: stdin, + // out: stdoutPipe, + // } + + // req, err := http.NewRequest("POST", "/images/"+unitTestImageName+"/insert?path=%2Ftest&url=https%3A%2F%2Fraw.github.com%2Fdotcloud%2Fdocker%2Fmaster%2FREADME.md", bytes.NewReader([]byte{})) + // if err != nil { + // t.Fatal(err) + // } + // if err := postContainersCreate(srv, r, req, nil); err != nil { + // t.Fatal(err) + // } + // }() + + // // Acknowledge hijack + // setTimeout(t, "hijack acknowledge timed out", 5*time.Second, func() { + // stdout.Read([]byte{}) + // stdout.Read(make([]byte, 4096)) + // }) + + // id := "" + // setTimeout(t, "Waiting for imagesInsert output", 10*time.Second, func() { + // for { + // reader := bufio.NewReader(stdout) + // id, err = reader.ReadString('\n') + // if err != nil { + // t.Fatal(err) + // } + // } + // }) + + // // Close pipes (client disconnects) + // if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { + // t.Fatal(err) + // } + + // // Wait for attach to finish, the client disconnected, therefore, Attach finished his job + // setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() { + // <-c1 + // }) + + // img, err := srv.runtime.repositories.LookupImage(id) + // if err != nil { + // t.Fatalf("New image %s expected but not found", id) + // } + + // layer, err := img.layer() + // if err != nil { + // t.Fatal(err) + // } + + // if _, err := os.Stat(path.Join(layer, "test")); err != nil { + // t.Fatalf("The test file has not been found") + // } + + // if err := srv.runtime.graph.Delete(img.Id); err != nil { + // t.Fatal(err) + // } +} func TestPostImagesPush(t *testing.T) { //FIXME: Use staging in order to perform tests diff --git a/commands.go b/commands.go index 4567370d3e..e4aa768d68 100644 --- a/commands.go +++ b/commands.go @@ -104,7 +104,7 @@ func (cli *DockerCli) CmdInsert(args ...string) error { v.Set("url", cmd.Arg(1)) v.Set("path", cmd.Arg(2)) - err := cli.stream("POST", "/images/"+cmd.Arg(0)+"?"+v.Encode(), nil, os.Stdout) + err := cli.stream("POST", "/images/"+cmd.Arg(0)+"/insert?"+v.Encode(), nil, os.Stdout) if err != nil { return err } diff --git a/docs/Makefile b/docs/Makefile index 47ecd9ca89..26168b6f38 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -59,18 +59,13 @@ site: connect: @echo connecting dotcloud to www.docker.io website, make sure to use user 1 @cd _build/website/ ; \ - dotcloud list ; \ - dotcloud connect dockerwebsite + dotcloud connect dockerwebsite ; + dotcloud list push: @cd _build/website/ ; \ dotcloud push -github-deploy: docs - rm -fr github-deploy - git clone ssh://git@github.com/dotcloud/docker github-deploy - cd github-deploy && git checkout -f gh-pages && git rm -r * && rsync -avH ../_build/html/ ./ && touch .nojekyll && echo "docker.io" > CNAME && git add * && git commit -m "Updating docs" - $(VERSIONS): @echo "Hello world" diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index 03f1d4b9cf..1dee086d0d 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -9,7 +9,7 @@ Docker Remote API - The Remote API is replacing rcli - Default port in the docker deamon is 4243 -- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection in hijacked to transport stdout stdin and stderr +- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr 2. Endpoints ============ diff --git a/docs/sources/api/registry_api.rst b/docs/sources/api/registry_api.rst index 35e1971213..e299584e17 100644 --- a/docs/sources/api/registry_api.rst +++ b/docs/sources/api/registry_api.rst @@ -85,7 +85,7 @@ On top of being a runtime for LXC, Docker is the Registry client. It supports: 5. Index returns true/false lettings registry know if it should proceed or error out 6. Get the payload for all layers -It’s possible to run docker pull https:///repositories/samalba/busybox. In this case, docker bypasses the Index. However the security is not guaranteed (in case Registry A is corrupted) because there won’t be any checksum checks. +It’s possible to run docker pull \https:///repositories/samalba/busybox. In this case, docker bypasses the Index. However the security is not guaranteed (in case Registry A is corrupted) because there won’t be any checksum checks. Currently registry redirects to s3 urls for downloads, going forward all downloads need to be streamed through the registry. The Registry will then abstract the calls to S3 by a top-level class which implements sub-classes for S3 and local storage. @@ -245,8 +245,8 @@ API (pushing repos foo/bar): The Index has two main purposes (along with its fancy social features): - Resolve short names (to avoid passing absolute URLs all the time) - - username/projectname -> https://registry.docker.io/users//repositories// - - team/projectname -> https://registry.docker.io/team//repositories// + - username/projectname -> \https://registry.docker.io/users//repositories// + - team/projectname -> \https://registry.docker.io/team//repositories// - Authenticate a user as a repos owner (for a central referenced repository) 3.1 Without an Index diff --git a/docs/sources/examples/python_web_app.rst b/docs/sources/examples/python_web_app.rst index 33caa52c1e..992a09dc42 100644 --- a/docs/sources/examples/python_web_app.rst +++ b/docs/sources/examples/python_web_app.rst @@ -58,7 +58,7 @@ Use the new image we just created and create a new container with network port 5 .. code-block:: bash docker logs $WEB_WORKER - * Running on http://0.0.0.0:5000/ + * Running on \http://0.0.0.0:5000/ view the logs for the new container using the WEB_WORKER variable, and if everything worked as planned you should see the line "Running on http://0.0.0.0:5000/" in the log output. @@ -70,7 +70,7 @@ lookup the public-facing port which is NAT-ed store the private port used by the .. code-block:: bash - curl http://`hostname`:$WEB_PORT + curl \http://`hostname`:$WEB_PORT Hello world! access the web app using curl. If everything worked as planned you should see the line "Hello world!" inside of your console. diff --git a/docs/sources/faq.rst b/docs/sources/faq.rst index 51fc00b306..b96ed06437 100644 --- a/docs/sources/faq.rst +++ b/docs/sources/faq.rst @@ -15,7 +15,7 @@ Most frequently asked questions. 3. **Does Docker run on Mac OS X or Windows?** - Not at this time, Docker currently only runs on Linux, but you can use VirtualBox to run Docker in a virtual machine on your box, and get the best of both worlds. Check out the MacOSX_ and Windows_ intallation guides. + Not at this time, Docker currently only runs on Linux, but you can use VirtualBox to run Docker in a virtual machine on your box, and get the best of both worlds. Check out the MacOSX_ and Windows_ installation guides. 4. **How do containers compare to virtual machines?** @@ -35,8 +35,8 @@ Most frequently asked questions. * `Ask questions on Stackoverflow`_ * `Join the conversation on Twitter`_ - .. _Windows: ../documentation/installation/windows.html - .. _MacOSX: ../documentation/installation/macos.html + .. _Windows: ../installation/windows/ + .. _MacOSX: ../installation/vagrant/ .. _the repo: http://www.github.com/dotcloud/docker .. _IRC\: docker on freenode: irc://chat.freenode.net#docker .. _Github: http://www.github.com/dotcloud/docker diff --git a/docs/sources/installation/index.rst b/docs/sources/installation/index.rst index 698d7f8ff1..1976f30ba0 100644 --- a/docs/sources/installation/index.rst +++ b/docs/sources/installation/index.rst @@ -20,3 +20,4 @@ Contents: rackspace archlinux upgrading + kernel diff --git a/docs/sources/installation/kernel.rst b/docs/sources/installation/kernel.rst new file mode 100644 index 0000000000..2ec5940a7f --- /dev/null +++ b/docs/sources/installation/kernel.rst @@ -0,0 +1,149 @@ +.. _kernel: + +Kernel Requirements +=================== + + The officially supported kernel is the one recommended by the + :ref:`ubuntu_linux` installation path. It is the one that most developers + will use, and the one that receives the most attention from the core + contributors. If you decide to go with a different kernel and hit a bug, + please try to reproduce it with the official kernels first. + +If for some reason you cannot or do not want to use the "official" kernels, +here is some technical background about the features (both optional and +mandatory) that docker needs to run successfully. + +In short, you need kernel version 3.8 (or above), compiled to include +`AUFS support `_. Of course, you need to +enable cgroups and namespaces. + + +Namespaces and Cgroups +---------------------- + +You need to enable namespaces and cgroups, to the extend of what is needed +to run LXC containers. Technically, while namespaces have been introduced +in the early 2.6 kernels, we do not advise to try any kernel before 2.6.32 +to run LXC containers. Note that 2.6.32 has some documented issues regarding +network namespace setup and teardown; those issues are not a risk if you +run containers in a private environment, but can lead to denial-of-service +attacks if you want to run untrusted code in your containers. For more details, +see `[LP#720095 `_. + +Kernels 2.6.38, and every version since 3.2, have been deployed successfully +to run containerized production workloads. Feature-wise, there is no huge +improvement between 2.6.38 and up to 3.6 (as far as docker is concerned!). + +Starting with version 3.7, the kernel has basic support for +`Checkpoint/Restore In Userspace `_, which is not used by +docker at this point, but allows to suspend the state of a container to +disk and resume it later. + +Version 3.8 provides improvements in stability, which are deemed necessary +for the operation of docker. Versions 3.2 to 3.5 have been shown to +exhibit a reproducible bug (for more details, see issue +`#407 `_). + +Version 3.8 also brings better support for the +`setns() syscall `_ -- but this should not +be a concern since docker does not leverage on this feature for now. + +If you want a technical overview about those concepts, you might +want to check those articles on dotCloud's blog: +`about namespaces `_ +and `about cgroups `_. + + +Important Note About Pre-3.8 Kernels +------------------------------------ + +As mentioned above, kernels before 3.8 are not stable when used with docker. +In some circumstances, you will experience kernel "oopses", or even crashes. +The symptoms include: + +- a container being killed in the middle of an operation (e.g. an ``apt-get`` + command doesn't complete); +- kernel messages including mentioning calls to ``mntput`` or + ``d_hash_and_lookup``; +- kernel crash causing the machine to freeze for a few minutes, or even + completely. + +While it is still possible to use older kernels for development, it is +really not advised to do so. + +Docker checks the kernel version when it starts, and emits a warning if it +detects something older than 3.8. + +See issue `#407 `_ for details. + + +Extra Cgroup Controllers +------------------------ + +Most control groups can be enabled or disabled individually. For instance, +you can decide that you do not want to compile support for the CPU or memory +controller. In some cases, the feature can be enabled or disabled at boot +time. It is worth mentioning that some distributions (like Debian) disable +"expensive" features, like the memory controller, because they can have +a significant performance impact. + +In the specific case of the memory cgroup, docker will detect if the cgroup +is available or not. If it's not, it will print a warning, and it won't +use the feature. If you want to enable that feature -- read on! + + +Memory and Swap Accounting on Debian/Ubuntu +------------------------------------------- + +If you use Debian or Ubuntu kernels, and want to enable memory and swap +accounting, you must add the following command-line parameters to your kernel:: + + cgroup_enable=memory swapaccount + +On Debian or Ubuntu systems, if you use the default GRUB bootloader, you can +add those parameters by editing ``/etc/default/grub`` and extending +``GRUB_CMDLINE_LINUX``. Look for the following line:: + + GRUB_CMDLINE_LINUX="" + +And replace it by the following one:: + + GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount" + +Then run ``update-grub``, and reboot. + + +AUFS +---- + +Docker currently relies on AUFS, an unioning filesystem. +While AUFS is included in the kernels built by the Debian and Ubuntu +distributions, is not part of the standard kernel. This means that if +you decide to roll your own kernel, you will have to patch your +kernel tree to add AUFS. The process is documented on +`AUFS webpage `_. + +Note: the AUFS patch is fairly intrusive, but for the record, people have +successfully applied GRSEC and AUFS together, to obtain hardened production +kernels. + +If you want more information about that topic, there is an +`article about AUFS on dotCloud's blog +`_. + + +BTRFS, ZFS, OverlayFS... +------------------------ + +There is ongoing development on docker, to implement support for +`BTRFS `_ +(see github issue `#443 `_). + +People have also showed interest for `ZFS `_ +(using e.g. `ZFS-on-Linux `_) and OverlayFS. +The latter is functionally close to AUFS, and it might end up being included +in the stock kernel; so it's a strong candidate! + +Would you like to `contribute +`_ +support for your favorite filesystem? diff --git a/docs/sources/use/index.rst b/docs/sources/use/index.rst index d3b3a31b18..9939dc7ea8 100644 --- a/docs/sources/use/index.rst +++ b/docs/sources/use/index.rst @@ -15,4 +15,5 @@ Contents: basics workingwithrepository builder + puppet diff --git a/docs/sources/use/puppet.rst b/docs/sources/use/puppet.rst new file mode 100644 index 0000000000..af2d5c8d57 --- /dev/null +++ b/docs/sources/use/puppet.rst @@ -0,0 +1,109 @@ + +.. _install_using_puppet: + +Using Puppet +============= + +.. note:: + + Please note this is a community contributed installation path. The only 'official' installation is using the + :ref:`ubuntu_linux` installation path. This version may sometimes be out of date. + +Requirements +------------ + +To use this guide you'll need a working installation of Puppet from `Puppetlabs `_ . + +The module also currently uses the official PPA so only works with Ubuntu. + +Installation +------------ + +The module is available on the `Puppet Forge `_ +and can be installed using the built-in module tool. + + .. code-block:: bash + + puppet module install garethr/docker + +It can also be found on `GitHub `_ +if you would rather download the source. + +Usage +----- + +The module provides a puppet class for installing docker and two defined types +for managing images and containers. + +Installation +~~~~~~~~~~~~ + + .. code-block:: ruby + + include 'docker' + +Images +~~~~~~ + +The next step is probably to install a docker image, for this we have a +defined type which can be used like so: + + .. code-block:: ruby + + docker::image { 'base': } + +This is equivalent to running: + + .. code-block:: bash + + docker pull base + +Note that it will only if the image of that name does not already exist. +This is downloading a large binary so on first run can take a while. +For that reason this define turns off the default 5 minute timeout +for exec. Note that you can also remove images you no longer need with: + + .. code-block:: ruby + + docker::image { 'base': + ensure => 'absent', + } + +Containers +~~~~~~~~~~ + +Now you have an image you can run commands within a container managed by +docker. + + .. code-block:: ruby + + docker::run { 'helloworld': + image => 'base', + command => '/bin/sh -c "while true; do echo hello world; sleep 1; done"', + } + +This is equivalent to running the following command, but under upstart: + + .. code-block:: bash + + docker run -d base /bin/sh -c "while true; do echo hello world; sleep 1; done" + +Run also contains a number of optional parameters: + + .. code-block:: ruby + + docker::run { 'helloworld': + image => 'base', + command => '/bin/sh -c "while true; do echo hello world; sleep 1; done"', + ports => ['4444', '4555'], + volumes => ['/var/lib/counchdb', '/var/log'], + volumes_from => '6446ea52fbc9', + memory_limit => 10485760, # bytes + username => 'example', + hostname => 'example.com', + env => ['FOO=BAR', 'FOO2=BAR2'], + dns => ['8.8.8.8', '8.8.4.4'], + } + +Note that ports, env, dns and volumes can be set with either a single string +or as above with an array of values. diff --git a/docs/theme/docker/static/img/hiring_graphic.png b/docs/theme/docker/static/img/hiring_graphic.png new file mode 100644 index 0000000000..b3a6b99644 Binary files /dev/null and b/docs/theme/docker/static/img/hiring_graphic.png differ diff --git a/docs/website/index.html b/docs/website/index.html index 777f6b698f..2dad365ce4 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -127,6 +127,22 @@

Repeatability

Because each container is isolated in its own filesystem, they behave the same regardless of where, when, and alongside what they run.

+
+
+
+ +
+
+

Do you think it is cool to hack on docker? Join us!

+
    +
  • Work on open source
  • +
  • Program in Go
  • +
+ read more +
+
+ +
diff --git a/server.go b/server.go index 956a4f8d36..d336248271 100644 --- a/server.go +++ b/server.go @@ -344,13 +344,24 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string) error if err != nil { return err } - for tag, id := range tagsList { - repoData.ImgList[id].Tag = tag + utils.Debugf("Registering tags") + // If not specific tag have been asked, take all + if askedTag == "" { + for tag, id := range tagsList { + repoData.ImgList[id].Tag = tag + } + } else { + // Otherwise, check that the tag exists and use only that one + if id, exists := tagsList[askedTag]; !exists { + return fmt.Errorf("Tag %s not found in repositoy %s", askedTag, remote) + } else { + repoData.ImgList[id].Tag = askedTag + } } for _, img := range repoData.ImgList { - // If we asked for a specific tag, skip all tags expect the wanted one - if askedTag != "" && askedTag != img.Tag { + if askedTag != "" && img.Tag != askedTag { + utils.Debugf("%s does not match %s, skipping", img.Tag, askedTag) continue } fmt.Fprintf(out, "Pulling image %s (%s) from %s\n", img.Id, img.Tag, remote) @@ -371,6 +382,10 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string) error return fmt.Errorf("Could not find repository on any of the indexed registries.") } } + // If we asked for a specific tag, do not register the others + if askedTag != "" { + return nil + } for tag, id := range tagsList { if err := srv.runtime.repositories.Set(remote, tag, id, true); err != nil { return err