Merge branch 'master' of https://github.com/dotcloud/docker
142
api.go
|
|
@ -72,9 +72,18 @@ func httpError(w http.ResponseWriter, err error) {
|
||||||
http.Error(w, err.Error(), statusCode)
|
http.Error(w, err.Error(), statusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeJSON(w http.ResponseWriter, b []byte) {
|
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(code)
|
||||||
w.Write(b)
|
w.Write(b)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBoolParam(value string) (bool, error) {
|
func getBoolParam(value string) (bool, error) {
|
||||||
|
|
@ -107,25 +116,14 @@ func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reque
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if status != "" {
|
if status != "" {
|
||||||
b, err := json.Marshal(&APIAuth{Status: status})
|
return writeJSON(w, http.StatusOK, &APIAuth{Status: status})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
m := srv.DockerVersion()
|
return writeJSON(w, http.StatusOK, srv.DockerVersion())
|
||||||
b, err := json.Marshal(m)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -168,12 +166,8 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, outs)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -184,13 +178,7 @@ func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.R
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
out := srv.DockerInfo()
|
return writeJSON(w, http.StatusOK, srv.DockerInfo())
|
||||||
b, err := json.Marshal(out)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -259,12 +247,8 @@ func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *ht
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, outs)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -276,12 +260,8 @@ func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(changesStr)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, changesStr)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -300,12 +280,8 @@ func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *ht
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(procsStr)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, procsStr)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -327,23 +303,18 @@ func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *h
|
||||||
n = -1
|
n = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
var b []byte
|
|
||||||
outs := srv.Containers(all, size, n, since, before)
|
outs := srv.Containers(all, size, n, since, before)
|
||||||
|
|
||||||
if version < 1.5 {
|
if version < 1.5 {
|
||||||
outs2 := []APIContainersOld{}
|
outs2 := []APIContainersOld{}
|
||||||
for _, ctnr := range outs {
|
for _, ctnr := range outs {
|
||||||
outs2 = append(outs2, ctnr.ToLegacy())
|
outs2 = append(outs2, ctnr.ToLegacy())
|
||||||
}
|
}
|
||||||
b, err = json.Marshal(outs2)
|
|
||||||
} else {
|
|
||||||
b, err = json.Marshal(outs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, outs2)
|
||||||
return err
|
} else {
|
||||||
|
return writeJSON(w, http.StatusOK, outs)
|
||||||
}
|
}
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -385,13 +356,8 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(&APIID{id})
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusCreated, &APIID{id})
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an image from Pull or from Import
|
// Creates an image from Pull or from Import
|
||||||
|
|
@ -455,12 +421,8 @@ func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *htt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, outs)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -485,12 +447,8 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(&APIID{ID: imgID})
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, &APIID{ID: imgID})
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -577,13 +535,7 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r
|
||||||
out.Warnings = append(out.Warnings, "IPv4 forwarding is disabled.")
|
out.Warnings = append(out.Warnings, "IPv4 forwarding is disabled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := json.Marshal(out)
|
return writeJSON(w, http.StatusCreated, out)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -639,11 +591,7 @@ func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.R
|
||||||
}
|
}
|
||||||
if imgs != nil {
|
if imgs != nil {
|
||||||
if len(imgs) != 0 {
|
if len(imgs) != 0 {
|
||||||
b, err := json.Marshal(imgs)
|
return writeJSON(w, http.StatusOK, imgs)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Conflict, %s wasn't deleted", name)
|
return fmt.Errorf("Conflict, %s wasn't deleted", name)
|
||||||
}
|
}
|
||||||
|
|
@ -706,12 +654,8 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(&APIWait{StatusCode: status})
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, &APIWait{StatusCode: status})
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -858,12 +802,8 @@ func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return fmt.Errorf("Conflict between containers and images")
|
return fmt.Errorf("Conflict between containers and images")
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(container)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, container)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
@ -881,12 +821,8 @@ func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *htt
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return fmt.Errorf("Conflict between containers and images")
|
return fmt.Errorf("Conflict between containers and images")
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(image)
|
|
||||||
if err != nil {
|
return writeJSON(w, http.StatusOK, image)
|
||||||
return err
|
|
||||||
}
|
|
||||||
writeJSON(w, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
|
||||||
|
|
@ -445,7 +445,7 @@ func TestGetContainersChanges(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainersTop(t *testing.T) {
|
func TestGetContainersTop(t *testing.T) {
|
||||||
t.Skip("Fixme. Skipping test for now. Reported error when testing using dind: 'api_test.go:527: Expected 2 processes, found 0.'")
|
t.Skip("Fixme. Skipping test for now. Reported error when testing using dind: 'api_test.go:527: Expected 2 processes, found 0.'")
|
||||||
runtime, err := newTestRuntime()
|
runtime, err := newTestRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
26
buildfile.go
|
|
@ -1,7 +1,6 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
|
|
@ -458,6 +457,9 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Long lines can be split with a backslash
|
||||||
|
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
|
||||||
|
|
||||||
func (b *buildFile) Build(context io.Reader) (string, error) {
|
func (b *buildFile) Build(context io.Reader) (string, error) {
|
||||||
// FIXME: @creack any reason for using /tmp instead of ""?
|
// FIXME: @creack any reason for using /tmp instead of ""?
|
||||||
// FIXME: @creack "name" is a terrible variable name
|
// FIXME: @creack "name" is a terrible variable name
|
||||||
|
|
@ -470,22 +472,18 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(name)
|
defer os.RemoveAll(name)
|
||||||
b.context = name
|
b.context = name
|
||||||
dockerfile, err := os.Open(path.Join(name, "Dockerfile"))
|
filename := path.Join(name, "Dockerfile")
|
||||||
if err != nil {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return "", fmt.Errorf("Can't build a directory with no Dockerfile")
|
return "", fmt.Errorf("Can't build a directory with no Dockerfile")
|
||||||
}
|
}
|
||||||
// FIXME: "file" is also a terrible variable name ;)
|
fileBytes, err := ioutil.ReadFile(filename)
|
||||||
file := bufio.NewReader(dockerfile)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
dockerfile := string(fileBytes)
|
||||||
|
dockerfile = lineContinuation.ReplaceAllString(dockerfile, " ")
|
||||||
stepN := 0
|
stepN := 0
|
||||||
for {
|
for _, line := range strings.Split(dockerfile, "\n") {
|
||||||
line, err := file.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF && line == "" {
|
|
||||||
break
|
|
||||||
} else if err != io.EOF {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n")
|
line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n")
|
||||||
// Skip comments and empty line
|
// Skip comments and empty line
|
||||||
if len(line) == 0 || line[0] == '#' {
|
if len(line) == 0 || line[0] == '#' {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,34 @@ run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Exactly the same as above, except uses a line split with a \ to test
|
||||||
|
// multiline support.
|
||||||
|
{
|
||||||
|
`
|
||||||
|
from {IMAGE}
|
||||||
|
run sh -c 'echo root:testpass \
|
||||||
|
> /tmp/passwd'
|
||||||
|
run mkdir -p /var/run/sshd
|
||||||
|
run [ "$(cat /tmp/passwd)" = "root:testpass" ]
|
||||||
|
run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
|
||||||
|
`,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Line containing literal "\n"
|
||||||
|
{
|
||||||
|
`
|
||||||
|
from {IMAGE}
|
||||||
|
run sh -c 'echo root:testpass > /tmp/passwd'
|
||||||
|
run echo "foo \n bar"; echo "baz"
|
||||||
|
run mkdir -p /var/run/sshd
|
||||||
|
run [ "$(cat /tmp/passwd)" = "root:testpass" ]
|
||||||
|
run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
|
||||||
|
`,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
`
|
`
|
||||||
from {IMAGE}
|
from {IMAGE}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,28 @@
|
||||||
:description: A simple hello world example with Docker
|
:description: A simple hello world example with Docker
|
||||||
:keywords: docker, example, hello world
|
:keywords: docker, example, hello world
|
||||||
|
|
||||||
|
.. _running_examples:
|
||||||
|
|
||||||
|
Running the Examples
|
||||||
|
====================
|
||||||
|
|
||||||
|
All the examples assume your machine is running the docker daemon. To
|
||||||
|
run the docker daemon in the background, simply type:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker -d &
|
||||||
|
|
||||||
|
Now you can run docker in client mode: by defalt all commands will be
|
||||||
|
forwarded to the ``docker`` daemon via a protected Unix socket, so you
|
||||||
|
must run as root.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker help
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _hello_world:
|
.. _hello_world:
|
||||||
|
|
||||||
Hello World
|
Hello World
|
||||||
|
|
@ -49,4 +71,108 @@ See the example in action
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
Continue to the :ref:`hello_world_daemon` example.
|
----
|
||||||
|
|
||||||
|
.. _hello_world_daemon:
|
||||||
|
|
||||||
|
Hello World Daemon
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. include:: example_header.inc
|
||||||
|
|
||||||
|
And now for the most boring daemon ever written!
|
||||||
|
|
||||||
|
This example assumes you have Docker installed and the Ubuntu
|
||||||
|
image already imported with ``docker pull ubuntu``. We will use the Ubuntu
|
||||||
|
image to run a simple hello world daemon that will just print hello
|
||||||
|
world to standard out every second. It will continue to do this until
|
||||||
|
we stop it.
|
||||||
|
|
||||||
|
**Steps:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
CONTAINER_ID=$(sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done")
|
||||||
|
|
||||||
|
We are going to run a simple hello world daemon in a new container
|
||||||
|
made from the *ubuntu* image.
|
||||||
|
|
||||||
|
- **"docker run -d "** run a command in a new container. We pass "-d"
|
||||||
|
so it runs as a daemon.
|
||||||
|
- **"ubuntu"** is the image we want to run the command inside of.
|
||||||
|
- **"/bin/sh -c"** is the command we want to run in the container
|
||||||
|
- **"while true; do echo hello world; sleep 1; done"** is the mini
|
||||||
|
script we want to run, that will just print hello world once a
|
||||||
|
second until we stop it.
|
||||||
|
- **$CONTAINER_ID** the output of the run command will return a
|
||||||
|
container id, we can use in future commands to see what is going on
|
||||||
|
with this process.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker logs $CONTAINER_ID
|
||||||
|
|
||||||
|
Check the logs make sure it is working correctly.
|
||||||
|
|
||||||
|
- **"docker logs**" This will return the logs for a container
|
||||||
|
- **$CONTAINER_ID** The Id of the container we want the logs for.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker attach $CONTAINER_ID
|
||||||
|
|
||||||
|
Attach to the container to see the results in realtime.
|
||||||
|
|
||||||
|
- **"docker attach**" This will allow us to attach to a background
|
||||||
|
process to see what is going on.
|
||||||
|
- **$CONTAINER_ID** The Id of the container we want to attach too.
|
||||||
|
|
||||||
|
Exit from the container attachment by pressing Control-C.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker ps
|
||||||
|
|
||||||
|
Check the process list to make sure it is running.
|
||||||
|
|
||||||
|
- **"docker ps"** this shows all running process managed by docker
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker stop $CONTAINER_ID
|
||||||
|
|
||||||
|
Stop the container, since we don't need it anymore.
|
||||||
|
|
||||||
|
- **"docker stop"** This stops a container
|
||||||
|
- **$CONTAINER_ID** The Id of the container we want to stop.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker ps
|
||||||
|
|
||||||
|
Make sure it is really stopped.
|
||||||
|
|
||||||
|
|
||||||
|
**Video:**
|
||||||
|
|
||||||
|
See the example in action
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<div style="margin-top:10px;">
|
||||||
|
<iframe width="560" height="350" src="http://ascii.io/a/2562/raw" frameborder="0"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The next example in the series is a :ref:`python_web_app` example, or
|
||||||
|
you could skip to any of the other examples:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
python_web_app
|
||||||
|
nodejs_web_app
|
||||||
|
running_redis_service
|
||||||
|
running_ssh_service
|
||||||
|
couchdb_data_volumes
|
||||||
|
postgresql_service
|
||||||
|
mongodb
|
||||||
|
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
:title: Hello world daemon example
|
|
||||||
:description: A simple hello world daemon example with Docker
|
|
||||||
:keywords: docker, example, hello world, daemon
|
|
||||||
|
|
||||||
.. _hello_world_daemon:
|
|
||||||
|
|
||||||
Hello World Daemon
|
|
||||||
==================
|
|
||||||
|
|
||||||
.. include:: example_header.inc
|
|
||||||
|
|
||||||
The most boring daemon ever written.
|
|
||||||
|
|
||||||
This example assumes you have Docker installed and the Ubuntu
|
|
||||||
image already imported with ``docker pull ubuntu``. We will use the Ubuntu
|
|
||||||
image to run a simple hello world daemon that will just print hello
|
|
||||||
world to standard out every second. It will continue to do this until
|
|
||||||
we stop it.
|
|
||||||
|
|
||||||
**Steps:**
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
CONTAINER_ID=$(sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done")
|
|
||||||
|
|
||||||
We are going to run a simple hello world daemon in a new container
|
|
||||||
made from the *ubuntu* image.
|
|
||||||
|
|
||||||
- **"docker run -d "** run a command in a new container. We pass "-d"
|
|
||||||
so it runs as a daemon.
|
|
||||||
- **"ubuntu"** is the image we want to run the command inside of.
|
|
||||||
- **"/bin/sh -c"** is the command we want to run in the container
|
|
||||||
- **"while true; do echo hello world; sleep 1; done"** is the mini
|
|
||||||
script we want to run, that will just print hello world once a
|
|
||||||
second until we stop it.
|
|
||||||
- **$CONTAINER_ID** the output of the run command will return a
|
|
||||||
container id, we can use in future commands to see what is going on
|
|
||||||
with this process.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker logs $CONTAINER_ID
|
|
||||||
|
|
||||||
Check the logs make sure it is working correctly.
|
|
||||||
|
|
||||||
- **"docker logs**" This will return the logs for a container
|
|
||||||
- **$CONTAINER_ID** The Id of the container we want the logs for.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker attach $CONTAINER_ID
|
|
||||||
|
|
||||||
Attach to the container to see the results in realtime.
|
|
||||||
|
|
||||||
- **"docker attach**" This will allow us to attach to a background
|
|
||||||
process to see what is going on.
|
|
||||||
- **$CONTAINER_ID** The Id of the container we want to attach too.
|
|
||||||
|
|
||||||
Exit from the container attachment by pressing Control-C.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker ps
|
|
||||||
|
|
||||||
Check the process list to make sure it is running.
|
|
||||||
|
|
||||||
- **"docker ps"** this shows all running process managed by docker
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker stop $CONTAINER_ID
|
|
||||||
|
|
||||||
Stop the container, since we don't need it anymore.
|
|
||||||
|
|
||||||
- **"docker stop"** This stops a container
|
|
||||||
- **$CONTAINER_ID** The Id of the container we want to stop.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker ps
|
|
||||||
|
|
||||||
Make sure it is really stopped.
|
|
||||||
|
|
||||||
|
|
||||||
**Video:**
|
|
||||||
|
|
||||||
See the example in action
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div style="margin-top:10px;">
|
|
||||||
<iframe width="560" height="350" src="http://ascii.io/a/2562/raw" frameborder="0"></iframe>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Continue to the :ref:`python_web_app` example.
|
|
||||||
|
|
@ -5,16 +5,16 @@
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
============
|
========
|
||||||
|
|
||||||
Contents:
|
Here are some examples of how to use Docker to create running
|
||||||
|
processes, starting from a very simple *Hello World* and progressing
|
||||||
|
to more substantial services like you might find in production.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
running_examples
|
|
||||||
hello_world
|
hello_world
|
||||||
hello_world_daemon
|
|
||||||
python_web_app
|
python_web_app
|
||||||
nodejs_web_app
|
nodejs_web_app
|
||||||
running_redis_service
|
running_redis_service
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
:title: Running the Examples
|
|
||||||
:description: An overview on how to run the docker examples
|
|
||||||
:keywords: docker, examples, how to
|
|
||||||
|
|
||||||
.. _running_examples:
|
|
||||||
|
|
||||||
Running the Examples
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
All the examples assume your machine is running the docker daemon. To
|
|
||||||
run the docker daemon in the background, simply type:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker -d &
|
|
||||||
|
|
||||||
Now you can run docker in client mode: by defalt all commands will be
|
|
||||||
forwarded to the ``docker`` daemon via a protected Unix socket, so you
|
|
||||||
must run as root.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo docker help
|
|
||||||
|
|
@ -1,24 +1,77 @@
|
||||||
:title: Installation on Amazon EC2
|
:title: Installation on Amazon EC2
|
||||||
:description: Docker installation on Amazon EC2 with a single vagrant command. Vagrant 1.1 or higher is required.
|
:description: Docker installation on Amazon EC2
|
||||||
:keywords: amazon ec2, virtualization, cloud, docker, documentation, installation
|
:keywords: amazon ec2, virtualization, cloud, docker, documentation, installation
|
||||||
|
|
||||||
Using Vagrant (Amazon EC2)
|
Amazon EC2
|
||||||
==========================
|
==========
|
||||||
|
|
||||||
This page explains how to setup and run an Amazon EC2 instance from
|
|
||||||
your local machine. **Vagrant is not necessary to run Docker on
|
|
||||||
EC2.** You can follow the :ref:`ubuntu_linux` instructions installing
|
|
||||||
Docker on any EC2 instance running Ubuntu.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. include:: install_header.inc
|
.. include:: install_header.inc
|
||||||
|
|
||||||
|
There are several ways to install Docker on AWS EC2:
|
||||||
|
|
||||||
|
* :ref:`amazonquickstart` or
|
||||||
|
* :ref:`amazonstandard` or
|
||||||
|
* :ref:`amazonvagrant`
|
||||||
|
|
||||||
|
**You'll need an** `AWS account <http://aws.amazon.com/>`_ **first, of course.**
|
||||||
|
|
||||||
|
.. _amazonquickstart:
|
||||||
|
|
||||||
|
Amazon QuickStart
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
1. **Choose an image:**
|
||||||
|
|
||||||
|
* Open http://cloud-images.ubuntu.com/locator/ec2/
|
||||||
|
* Enter ``amd64 precise`` in the search field (it will search as you
|
||||||
|
type)
|
||||||
|
* Pick an image by clicking on the image name. *An EBS-enabled
|
||||||
|
image will let you t1.micro instance.* Clicking on the image name
|
||||||
|
will take you to your AWS Console.
|
||||||
|
|
||||||
|
2. **Tell CloudInit to install Docker:**
|
||||||
|
|
||||||
|
* Enter ``#include https://get.docker.io`` into the instance *User
|
||||||
|
Data*. `CloudInit <https://help.ubuntu.com/community/CloudInit>`_
|
||||||
|
is part of the Ubuntu image you chose and it bootstraps from this
|
||||||
|
*User Data*.
|
||||||
|
|
||||||
|
3. After a few more standard choices where defaults are probably ok, your
|
||||||
|
AWS Ubuntu instance with Docker should be running!
|
||||||
|
|
||||||
|
**If this is your first AWS instance, you may need to set up your
|
||||||
|
Security Group to allow SSH.** By default all incoming ports to your
|
||||||
|
new instance will be blocked by the AWS Security Group, so you might
|
||||||
|
just get timeouts when you try to connect.
|
||||||
|
|
||||||
|
Installing with ``get.docker.io`` (as above) will create a service
|
||||||
|
named ``dockerd``. You may want to set up a :ref:`docker group
|
||||||
|
<dockergroup>` and add the *ubuntu* user to it so that you don't have
|
||||||
|
to use ``sudo`` for every Docker command.
|
||||||
|
|
||||||
|
Once you've got Docker installed, you're ready to try it out -- head
|
||||||
|
on over to the :doc:`../use/basics` or :doc:`../examples/index` section.
|
||||||
|
|
||||||
|
.. _amazonstandard:
|
||||||
|
|
||||||
|
Standard Ubuntu Installation
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
If you want a more hands-on installation, then you can follow the
|
||||||
|
:ref:`ubuntu_linux` instructions installing Docker on any EC2 instance
|
||||||
|
running Ubuntu. Just follow Step 1 from :ref:`amazonquickstart` to
|
||||||
|
pick an image (or use one of your own) and skip the step with the
|
||||||
|
*User Data*. Then continue with the :ref:`ubuntu_linux` instructions.
|
||||||
|
|
||||||
|
.. _amazonvagrant:
|
||||||
|
|
||||||
|
Use Vagrant
|
||||||
|
-----------
|
||||||
|
|
||||||
.. include:: install_unofficial.inc
|
.. include:: install_unofficial.inc
|
||||||
|
|
||||||
Docker can now be installed on Amazon EC2 with a single vagrant
|
And finally, if you prefer to work through Vagrant, you can install
|
||||||
command. Vagrant 1.1 or higher is required.
|
Docker that way too. Vagrant 1.1 or higher is required.
|
||||||
|
|
||||||
1. Install vagrant from http://www.vagrantup.com/ (or use your package manager)
|
1. Install vagrant from http://www.vagrantup.com/ (or use your package manager)
|
||||||
2. Install the vagrant aws plugin
|
2. Install the vagrant aws plugin
|
||||||
|
|
@ -37,16 +90,17 @@ command. Vagrant 1.1 or higher is required.
|
||||||
|
|
||||||
4. Check your AWS environment.
|
4. Check your AWS environment.
|
||||||
|
|
||||||
Create a keypair specifically for EC2, give it a name and save it to your disk. *I usually store these in my ~/.ssh/ folder*.
|
Create a keypair specifically for EC2, give it a name and save it
|
||||||
|
to your disk. *I usually store these in my ~/.ssh/ folder*.
|
||||||
Check that your default security group has an inbound rule to accept SSH (port 22) connections.
|
|
||||||
|
|
||||||
|
|
||||||
|
Check that your default security group has an inbound rule to
|
||||||
|
accept SSH (port 22) connections.
|
||||||
|
|
||||||
5. Inform Vagrant of your settings
|
5. Inform Vagrant of your settings
|
||||||
|
|
||||||
Vagrant will read your access credentials from your environment, so we need to set them there first. Make sure
|
Vagrant will read your access credentials from your environment, so
|
||||||
you have everything on amazon aws setup so you can (manually) deploy a new image to EC2.
|
we need to set them there first. Make sure you have everything on
|
||||||
|
amazon aws setup so you can (manually) deploy a new image to EC2.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -60,7 +114,8 @@ command. Vagrant 1.1 or higher is required.
|
||||||
* ``AWS_ACCESS_KEY_ID`` - The API key used to make requests to AWS
|
* ``AWS_ACCESS_KEY_ID`` - The API key used to make requests to AWS
|
||||||
* ``AWS_SECRET_ACCESS_KEY`` - The secret key to make AWS API requests
|
* ``AWS_SECRET_ACCESS_KEY`` - The secret key to make AWS API requests
|
||||||
* ``AWS_KEYPAIR_NAME`` - The name of the keypair used for this EC2 instance
|
* ``AWS_KEYPAIR_NAME`` - The name of the keypair used for this EC2 instance
|
||||||
* ``AWS_SSH_PRIVKEY`` - The path to the private key for the named keypair, for example ``~/.ssh/docker.pem``
|
* ``AWS_SSH_PRIVKEY`` - The path to the private key for the named
|
||||||
|
keypair, for example ``~/.ssh/docker.pem``
|
||||||
|
|
||||||
You can check if they are set correctly by doing something like
|
You can check if they are set correctly by doing something like
|
||||||
|
|
||||||
|
|
@ -75,10 +130,12 @@ command. Vagrant 1.1 or higher is required.
|
||||||
vagrant up --provider=aws
|
vagrant up --provider=aws
|
||||||
|
|
||||||
|
|
||||||
If it stalls indefinitely on ``[default] Waiting for SSH to become available...``, Double check your default security
|
If it stalls indefinitely on ``[default] Waiting for SSH to become
|
||||||
zone on AWS includes rights to SSH (port 22) to your container.
|
available...``, Double check your default security zone on AWS
|
||||||
|
includes rights to SSH (port 22) to your container.
|
||||||
|
|
||||||
If you have an advanced AWS setup, you might want to have a look at https://github.com/mitchellh/vagrant-aws
|
If you have an advanced AWS setup, you might want to have a look at
|
||||||
|
https://github.com/mitchellh/vagrant-aws
|
||||||
|
|
||||||
7. Connect to your machine
|
7. Connect to your machine
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 275 KiB |
|
|
@ -114,10 +114,6 @@
|
||||||
<form>
|
<form>
|
||||||
<input type="text" id="st-search-input" class="st-search-input span3" style="width:160px;" />
|
<input type="text" id="st-search-input" class="st-search-input span3" style="width:160px;" />
|
||||||
</form>
|
</form>
|
||||||
<a href="http://swiftype.com?ref=pb">
|
|
||||||
<img id="swiftype-img" src="http://swiftype.com/assets/media/swiftype-logo-lightbg-small.png"
|
|
||||||
alt="Search by Swiftype" />
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- body block -->
|
<!-- body block -->
|
||||||
|
|
|
||||||
|
|
@ -772,7 +772,9 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName
|
||||||
} else {
|
} else {
|
||||||
elem.Checksum = checksum
|
elem.Checksum = checksum
|
||||||
}
|
}
|
||||||
return pushTags()
|
if err := pushTags(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,6 @@ func TestParseRelease(t *testing.T) {
|
||||||
assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "19-generic"}, 0)
|
assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "19-generic"}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestDependencyGraphCircular(t *testing.T) {
|
func TestDependencyGraphCircular(t *testing.T) {
|
||||||
g1 := NewDependencyGraph()
|
g1 := NewDependencyGraph()
|
||||||
a := g1.NewNode("a")
|
a := g1.NewNode("a")
|
||||||
|
|
@ -421,4 +420,4 @@ func TestDependencyGraph(t *testing.T) {
|
||||||
if len(res[2]) != 1 || res[2][0] != "d" {
|
if len(res[2]) != 1 || res[2][0] != "d" {
|
||||||
t.Fatalf("Expected [d], found %v instead", res[2])
|
t.Fatalf("Expected [d], found %v instead", res[2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||