Browse code

added search

Victor Vieux authored on 2013/05/08 03:37:35
Showing 15 changed files
... ...
@@ -365,6 +365,28 @@ func ListenAndServe(addr string, srv *Server) error {
365 365
 		}
366 366
 	})
367 367
 
368
+	r.Path("/images/search").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
369
+		log.Println(r.Method, r.RequestURI)
370
+		if err := r.ParseForm(); err != nil {
371
+                        http.Error(w, err.Error(), http.StatusInternalServerError)
372
+                        return
373
+                }
374
+
375
+		term := r.Form.Get("term")
376
+		outs, err := srv.ImagesSearch(term)
377
+		if err != nil {
378
+			httpError(w, err)
379
+			return
380
+		}
381
+		b, err := json.Marshal(outs)
382
+                if err != nil {
383
+                        http.Error(w, err.Error(), http.StatusInternalServerError)
384
+                } else {
385
+                        w.Header().Set("Content-Type", "application/json")
386
+                        w.Write(b)
387
+                }
388
+	})
389
+
368 390
 	r.Path("/images/{name:*.}/insert").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
369 391
 		log.Println(r.Method, r.RequestURI)
370 392
 		if err := r.ParseForm(); err != nil {
... ...
@@ -31,6 +31,11 @@ type ApiContainers struct {
31 31
 	Ports   string `json:",omitempty"`
32 32
 }
33 33
 
34
+type ApiSearch struct {
35
+	Name string
36
+	Description string
37
+}
38
+
34 39
 type ApiId struct {
35 40
 	Id string
36 41
 }
... ...
@@ -53,6 +53,7 @@ func ParseCommands(args ...string) error {
53 53
 
54 54
 	cmds := map[string]func(args ...string) error{
55 55
 		"attach":  CmdAttach,
56
+		"build": CmdBuild,
56 57
 		"commit":  CmdCommit,
57 58
 		"diff":    CmdDiff,
58 59
 		"export":  CmdExport,
... ...
@@ -74,6 +75,7 @@ func ParseCommands(args ...string) error {
74 74
 		"rmi":     CmdRmi,
75 75
 		"run":     CmdRun,
76 76
 		"tag":     CmdTag,
77
+		"search":	CmdSearch,
77 78
 		"start":   CmdStart,
78 79
 		"stop":    CmdStop,
79 80
 		"version": CmdVersion,
... ...
@@ -116,6 +118,7 @@ func cmdHelp(args ...string) error {
116 116
 		{"rm", "Remove a container"},
117 117
 		{"rmi", "Remove an image"},
118 118
 		{"run", "Run a command in a new container"},
119
+		{"search", "Search for an image in the docker index"},
119 120
 		{"start", "Start a stopped container"},
120 121
 		{"stop", "Stop a running container"},
121 122
 		{"tag", "Tag an image into a repository"},
... ...
@@ -948,6 +951,41 @@ func CmdAttach(args ...string) error {
948 948
 	return nil
949 949
 }
950 950
 
951
+func CmdSearch(args ...string) error {
952
+	cmd := Subcmd("search", "NAME", "Search the docker index for images")
953
+	if err := cmd.Parse(args); err != nil {
954
+		return nil
955
+	}
956
+	if cmd.NArg() != 1 {
957
+		cmd.Usage()
958
+		return nil
959
+	}
960
+	
961
+	v := url.Values{}
962
+        v.Set("term", cmd.Arg(0))
963
+	body, _, err := call("GET", "/images/search?"+v.Encode(), nil)
964
+        if err != nil {
965
+                return err
966
+        }
967
+
968
+        var outs []ApiSearch
969
+        err = json.Unmarshal(body, &outs)
970
+        if err != nil {
971
+                return err
972
+        }
973
+	fmt.Printf("Found %d results matching your query (\"%s\")\n", len(outs), cmd.Arg(0))
974
+	w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
975
+	fmt.Fprintf(w, "NAME\tDESCRIPTION\n")
976
+	for _, out := range outs {
977
+		fmt.Fprintf(w, "%s\t%s\n", out.Name, out.Description)
978
+	}
979
+	w.Flush()
980
+	return nil
981
+}
982
+
983
+// Ports type - Used to parse multiple -p flags
984
+type ports []int
985
+
951 986
 // ListOpts type
952 987
 type ListOpts []string
953 988
 
... ...
@@ -15,6 +15,7 @@ Installation
15 15
 
16 16
 * Work in your own fork of the code, we accept pull requests.
17 17
 * Install sphinx: ``pip install sphinx``
18
+* Install sphinx httpdomain contrib package ``sphinxcontrib-httpdomain``
18 19
 * If pip is not available you can probably install it using your favorite package manager as **python-pip**
19 20
 
20 21
 Usage
... ...
@@ -47,6 +47,7 @@ Available Commands
47 47
    command/rm
48 48
    command/rmi
49 49
    command/run
50
+   command/search
50 51
    command/start
51 52
    command/stop
52 53
    command/tag
53 54
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+===================================================================
1
+``search`` -- Search for an image in the docker index
2
+===================================================================
3
+
4
+::
5
+
6
+    Usage: docker search TERM
7
+
8
+    Searches for the TERM parameter on the Docker index and prints out a list of repositories
9
+    that match.
... ...
@@ -2,9 +2,9 @@
2 2
 :description: Sharing data between 2 couchdb databases
3 3
 :keywords: docker, example, package installation, networking, couchdb, data volumes
4 4
 
5
-.. _running_redis_service:
5
+.. _running_couchdb_service:
6 6
 
7
-Create a redis service
7
+Create a CouchDB service
8 8
 ======================
9 9
 
10 10
 .. include:: example_header.inc
... ...
@@ -7,6 +7,7 @@
7 7
 <head>
8 8
     <meta charset="utf-8">
9 9
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10
+    <meta name="google-site-verification" content="UxV66EKuPe87dgnH1sbrldrx6VsoWMrx5NjwkgUFxXI" />
10 11
     <title>Docker - the Linux container engine</title>
11 12
 
12 13
     <meta name="description" content="Docker encapsulates heterogeneous payloads in standard containers">
... ...
@@ -23,6 +24,29 @@
23 23
     <script src="_static/js/vendor/jquery-1.9.1.min.js" type="text/javascript" ></script>
24 24
     <script src="_static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js" type="text/javascript" ></script>
25 25
 
26
+    <style>
27
+        .indexlabel {
28
+            float: left;
29
+            width: 150px;
30
+            display: block;
31
+            padding: 10px 20px 10px;
32
+            font-size: 20px;
33
+            font-weight: 200;
34
+            background-color: #a30000;
35
+            color: white;
36
+            height: 22px;
37
+        }
38
+        .searchbutton {
39
+            font-size: 20px;
40
+            height: 40px;
41
+        }
42
+
43
+        .debug {
44
+            border: 1px red dotted;
45
+        }
46
+
47
+    </style>
48
+
26 49
 </head>
27 50
 
28 51
 
... ...
@@ -49,59 +73,40 @@
49 49
 </div>
50 50
 
51 51
 
52
-<div class="container">
53
-    <div class="row">
54
-        <div class="text-center">
55
-            <img src="_static/img/docker-letters-logo.gif">
56
-        </div>
57
-    </div>
58
-</div>
59
-
60
-<div class="container">
52
+<div class="container" style="margin-top: 30px;">
61 53
     <div class="row">
62 54
 
63 55
         <div class="span12">
64 56
             <section class="contentblock header">
65 57
 
66
-                <div class="span6" style="margin:10px 0px 0px 30px; float: right; ">
67
-                    <div class="js-video" >
68
-                        <iframe width="640" height="360" src="http://www.youtube.com/embed/wW9CAH9nSLs?feature=player_detailpage&rel=0&modestbranding=1&start=11" frameborder="0" allowfullscreen></iframe>
58
+                <div class="span5" style="margin-bottom: 15px;">
59
+                    <div style="text-align: center;" >
60
+                        <img src="_static/img/docker_letters_500px.png">
61
+
62
+                        <h2>The Linux container engine</h2>
69 63
                     </div>
70
-                </div>
71 64
 
72
-                <div style="text-align: center; padding: 50px 30px 50px 30px;">
73
-		    <h1>Docker</h1>
74
-		    <h2>The Linux container engine</h2>
75
-                </div>
65
+                    <div style="display: block; text-align: center; margin-top: 20px;">
76 66
 
77
-                <div style="display: block; text-align: center; padding: 10px 30px 50px 30px;">
67
+                        <h5>
68
+                            Docker is an open-source engine which automates the deployment of applications as highly portable, self-sufficient containers which are independent of hardware, language, framework, packaging system and hosting provider.
69
+                        </h5>
78 70
 
79
-		<p>
80
-		Docker is an open-source engine which automates the deployment of applications as highly portable, self-sufficient containers.
81
-		</p>
71
+                    </div>
82 72
 
83
-		<p>
84
-		Docker containers are both <string>hardware-agnostic</strong> and <strong>platform-agnostic</strong>. This means that they can run anywhere, from your
85
-		laptop to the largest EC2 compute instance and everything in between - and they don't require that you use a particular
86
-		language, framework or packaging system. That makes them great building blocks for deploying and scaling web apps, databases
87
-		and backend services without depending on a particular stack or provider.
88
-		</p>
89 73
 
90
-		<p>
91
-		Docker is an open-source implementation of the deployment engine which powers <a href="http://dotcloud.com">dotCloud</a>, a popular Platform-as-a-Service.
92
-		It benefits directly from the experience accumulated over several years of large-scale operation and support of hundreds of thousands
93
-		of applications and databases.
94
-		</p>
74
+                    <div style="display: block; text-align: center; margin-top: 30px;">
75
+                        <a class="btn btn-custom btn-large" href="gettingstarted/">Let's get started</a>
76
+                    </div>
95 77
 
96 78
                 </div>
97 79
 
98
-
99
-                <div style="display: block; text-align: center;">
100
-                    <a class="btn btn-custom btn-large" href="gettingstarted/">Let's get started</a>
80
+                <div class="span6" >
81
+                    <div class="js-video" >
82
+                        <iframe width="600" height="360" src="http://www.youtube.com/embed/wW9CAH9nSLs?feature=player_detailpage&rel=0&modestbranding=1&start=11" frameborder="0" allowfullscreen></iframe>
83
+                    </div>
101 84
                 </div>
102 85
 
103
-
104
-
105 86
                 <br style="clear: both"/>
106 87
             </section>
107 88
         </div>
... ...
@@ -111,31 +116,56 @@
111 111
 <div class="container">
112 112
     <div class="row">
113 113
 
114
-        <div class="span3">
114
+        <div class="span6">
115 115
             <section class="contentblock">
116 116
                 <h4>Heterogeneous payloads</h4>
117 117
                 <p>Any combination of binaries, libraries, configuration files, scripts, virtualenvs, jars, gems, tarballs, you name it. No more juggling between domain-specific tools. Docker can deploy and run them all.</p>
118
-            </section>
119
-        </div>
120
-        <div class="span3">
121
-            <section class="contentblock">
122 118
                 <h4>Any server</h4>
123 119
                 <p>Docker can run on any x64 machine with a modern linux kernel - whether it's a laptop, a bare metal server or a VM. This makes it perfect for multi-cloud deployments.</p>
120
+                <h4>Isolation</h4>
121
+                <p>Docker isolates processes from each other and from the underlying host, using lightweight containers.</p>
122
+                <h4>Repeatability</h4>
123
+                <p>Because each container is isolated in its own filesystem, they behave the same regardless of where, when, and alongside what they run.</p>
124 124
             </section>
125 125
         </div>
126
-        <div class="span3">
126
+        <div class="span6">
127 127
             <section class="contentblock">
128
-                <h4>Isolation</h4>
129
-                <p>docker isolates processes from each other and from the underlying host, using lightweight containers.</p>
128
+                <h1>New! Docker Index</h1>
129
+                On the Docker Index you can find and explore pre-made container images. It allows you to share your images and download them.
130
+
131
+                <br><br>
132
+                <a href="https://index.docker.io" target="_blank">
133
+                    <div class="indexlabel">
134
+                        DOCKER index
135
+                    </div>
136
+                </a>
137
+                &nbsp;
138
+                <input type="button" class="searchbutton" type="submit" value="Search images"
139
+                       onClick="window.open('https://index.docker.io')" />
140
+
130 141
             </section>
131
-        </div>
132
-        <div class="span3">
133 142
             <section class="contentblock">
134
-                <h4>Repeatability</h4>
135
-                <p>Because containers are isolated in their own filesystem, they behave the same regardless of where, when, and alongside what they run.</p>
143
+                <div id="wufoo-z7x3p3">
144
+                    Fill out my <a href="http://dotclouddocker.wufoo.com/forms/z7x3p3">online form</a>.
145
+                </div>
146
+                <script type="text/javascript">var z7x3p3;(function(d, t) {
147
+                    var s = d.createElement(t), options = {
148
+                        'userName':'dotclouddocker',
149
+                        'formHash':'z7x3p3',
150
+                        'autoResize':true,
151
+                        'height':'577',
152
+                        'async':true,
153
+                        'header':'show'};
154
+                    s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
155
+                    s.onload = s.onreadystatechange = function() {
156
+                        var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
157
+                        try { z7x3p3 = new WufooForm();z7x3p3.initialize(options);z7x3p3.display(); } catch (e) {}};
158
+                    var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
159
+                })(document, 'script');</script>
136 160
             </section>
137 161
         </div>
138 162
     </div>
163
+
139 164
 </div>
140 165
 
141 166
 <style>
... ...
@@ -183,18 +213,12 @@
183 183
     </div>
184 184
 </div>
185 185
 
186
-<!--         <p>Docker encapsulates heterogeneous payloads in <a href="#container">Standard Containers</a>, and runs them on any server with strong guarantees of isolation and repeatability.</p>
187
-
188
-        <p>It is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc.</p>
189
-
190
- -->
191 186
 <div class="container">
192 187
     <div class="row">
193 188
         <div class="span6">
194 189
 
195 190
             <section class="contentblock">
196 191
 
197
-                <!-- <img src="_static/lego_docker.jpg" width="600px" style="float:right; margin-left: 10px"> -->
198 192
                 <h2>Notable features</h2>
199 193
 
200 194
                 <ul>
... ...
@@ -218,35 +242,26 @@
218 218
                     <li><a href="http://lxc.sourceforge.net/">lxc</a>, a set of convenience scripts to simplify the creation of linux containers.</li>
219 219
                 </ul>
220 220
 
221
+                <h2>Who started it</h2>
222
+                <p>
223
+                    Docker is an open-source implementation of the deployment engine which powers <a href="http://dotcloud.com">dotCloud</a>, a popular Platform-as-a-Service.</p>
224
+
225
+                <p>It benefits directly from the experience accumulated over several years of large-scale operation and support of hundreds of thousands
226
+                    of applications and databases.
227
+                </p>
228
+
221 229
             </section>
222 230
         </div>
223 231
 
224 232
         <div class="span6">
225
-            <section class="contentblock">
226
-                <div id="wufoo-z7x3p3">
227
-                    Fill out my <a href="http://dotclouddocker.wufoo.com/forms/z7x3p3">online form</a>.
228
-                </div>
229
-                <script type="text/javascript">var z7x3p3;(function(d, t) {
230
-                    var s = d.createElement(t), options = {
231
-                        'userName':'dotclouddocker',
232
-                        'formHash':'z7x3p3',
233
-                        'autoResize':true,
234
-                        'height':'577',
235
-                        'async':true,
236
-                        'header':'show'};
237
-                    s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
238
-                    s.onload = s.onreadystatechange = function() {
239
-                        var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
240
-                        try { z7x3p3 = new WufooForm();z7x3p3.initialize(options);z7x3p3.display(); } catch (e) {}};
241
-                    var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
242
-                })(document, 'script');</script>
243
-            </section>
233
+
244 234
 
245 235
             <section class="contentblock">
246 236
                 <h3 id="twitter">Twitter</h3>
247 237
                 <a class="twitter-timeline" href="https://twitter.com/getdocker" data-widget-id="312730839718957056">Tweets by @getdocker</a>
248 238
                 <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
249 239
             </section>
240
+
250 241
         </div>
251 242
     </div>
252 243
 
... ...
@@ -6,6 +6,7 @@
6 6
 <head>
7 7
     <meta charset="utf-8">
8 8
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9
+    <meta name="google-site-verification" content="UxV66EKuPe87dgnH1sbrldrx6VsoWMrx5NjwkgUFxXI" />
9 10
 
10 11
     <title>Docker - {{ meta['title'] if meta and meta['title'] else title }}</title>
11 12
 
... ...
@@ -74,7 +75,7 @@
74 74
             </div>
75 75
 
76 76
             <div style="margin-left: -12px; float: left;">
77
-                <a href="{{ pathto('./', 1) }}"><img style="margin-top: 12px; height: 38px" src="{{ pathto('_static/img/docker-letters-logo.gif', 1) }}"></a>
77
+                <a href="http://www.docker.io"><img style="margin-top: 12px; height: 38px" src="{{ pathto('_static/img/docker-letters-logo.gif', 1) }}"></a>
78 78
             </div>
79 79
         </div>
80 80
 
... ...
@@ -82,7 +82,7 @@ h4 {
82 82
 .btn-custom {
83 83
   background-color: #292929 !important;
84 84
   background-repeat: repeat-x;
85
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#515151", endColorstr="#282828");
85
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr="#515151", endColorstr="#282828");
86 86
   background-image: -khtml-gradient(linear, left top, left bottom, from(#515151), to(#282828));
87 87
   background-image: -moz-linear-gradient(top, #515151, #282828);
88 88
   background-image: -ms-linear-gradient(top, #515151, #282828);
89 89
new file mode 100644
90 90
Binary files /dev/null and b/docs/theme/docker/static/img/docker_letters_500px.png differ
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"io"
10 10
 	"io/ioutil"
11 11
 	"net/http"
12
+	"net/url"
12 13
 	"path"
13 14
 	"strings"
14 15
 )
... ...
@@ -211,6 +212,11 @@ func (graph *Graph) getRemoteTags(stdout io.Writer, registries []string, reposit
211 211
 
212 212
 func (graph *Graph) getImageForTag(stdout io.Writer, tag, remote, registry string, token []string) (string, error) {
213 213
 	client := graph.getHttpClient()
214
+
215
+	if !strings.Contains(remote, "/") {
216
+		remote = "library/" + remote
217
+	}
218
+
214 219
 	registryEndpoint := "https://" + registry + "/v1"
215 220
 	repositoryTarget := registryEndpoint + "/repositories/" + remote + "/tags/" + tag
216 221
 
... ...
@@ -638,3 +644,33 @@ func (graph *Graph) Checksums(output io.Writer, repo Repository) ([]map[string]s
638 638
 	}
639 639
 	return result, nil
640 640
 }
641
+
642
+type SearchResults struct {
643
+	Query      string              `json:"query"`
644
+	NumResults int                 `json:"num_results"`
645
+	Results    []map[string]string `json:"results"`
646
+}
647
+
648
+func (graph *Graph) SearchRepositories(stdout io.Writer, term string) (*SearchResults, error) {
649
+	client := graph.getHttpClient()
650
+	u := INDEX_ENDPOINT + "/search?q=" + url.QueryEscape(term)
651
+	req, err := http.NewRequest("GET", u, nil)
652
+	if err != nil {
653
+		return nil, err
654
+	}
655
+	res, err := client.Do(req)
656
+	if err != nil {
657
+		return nil, err
658
+	}
659
+	defer res.Body.Close()
660
+	if res.StatusCode != 200 {
661
+		return nil, fmt.Errorf("Unexepected status code %d", res.StatusCode)
662
+	}
663
+	rawData, err := ioutil.ReadAll(res.Body)
664
+	if err != nil {
665
+		return nil, err
666
+	}
667
+	result := new(SearchResults)
668
+	err = json.Unmarshal(rawData, result)
669
+	return result, err
670
+}
... ...
@@ -72,7 +72,7 @@ func init() {
72 72
 		runtime: runtime,
73 73
 	}
74 74
 	// Retrieve the Image
75
-	if err := srv.ImagePull(unitTestImageName, os.Stdout); err != nil {
75
+	if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout); err != nil {
76 76
 		panic(err)
77 77
 	}
78 78
 }
... ...
@@ -43,6 +43,25 @@ func (srv *Server) ContainerExport(name string, file *os.File) error {
43 43
 	return fmt.Errorf("No such container: %s", name)
44 44
 }
45 45
 
46
+func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) {
47
+	results, err := srv.runtime.graph.SearchRepositories(nil, term)
48
+	if err != nil {
49
+                return nil, err
50
+        }
51
+	
52
+	var outs []ApiSearch
53
+	for _, repo := range results.Results {
54
+		var out ApiSearch
55
+		out.Description = repo["description"]
56
+                if len(out.Description) > 45 {
57
+                        out.Description = Trunc(out.Description, 42) + "..."
58
+                }
59
+		out.Name = repo["name"]
60
+		outs = append(outs, out)
61
+	}
62
+	return outs, nil
63
+}
64
+
46 65
 func (srv *Server) ImageInsert(name, url, path string, stdout *os.File) error {
47 66
 	img, err := srv.runtime.repositories.LookupImage(name)
48 67
 	if err != nil {
... ...
@@ -13,7 +13,7 @@ func TestCreateRm(t *testing.T) {
13 13
 
14 14
 	srv := &Server{runtime: runtime}
15 15
 
16
-	config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "echo test"})
16
+	config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "echo test"}, nil)
17 17
 	if err != nil {
18 18
 		t.Fatal(err)
19 19
 	}
... ...
@@ -46,7 +46,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
46 46
 
47 47
 	srv := &Server{runtime: runtime}
48 48
 
49
-	config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "/bin/cat"})
49
+	config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "/bin/cat"}, nil)
50 50
 	if err != nil {
51 51
 		t.Fatal(err)
52 52
 	}