docker-api 2.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 88fd03d58560759042d6b5513da603fa2db7e1553e47ddcd85cf6af9df34ecf5
4
+ data.tar.gz: cccb4daff0e134328e485a81862609371990697af2c36a4694cb9ba2053e8423
5
+ SHA512:
6
+ metadata.gz: ce528e7f874a062c36fc71c531fcc038501495a9cddd71b6187169ea2278e404cb6a9fdf9d07f39327613bde8c99403d093b471e7d56717b1cb93e21f1f26d10
7
+ data.tar.gz: 04f96ad64f0aab19bd1d96d8816b247f55530b110c8717e4ee24447036302ff3ddd79070768ede3858b1c08ebc3f91b998191d48980396c1ab94c47a0c25c4ba
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Swipely, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+
@@ -0,0 +1,633 @@
1
+ docker-api
2
+ ==========
3
+ [![Gem Version](https://badge.fury.io/rb/docker-api.svg)](https://badge.fury.io/rb/docker-api) [![travis-ci](https://travis-ci.org/swipely/docker-api.svg?branch=master)](https://travis-ci.org/swipely/docker-api) [![Code Climate](https://codeclimate.com/github/swipely/docker-api.svg)](https://codeclimate.com/github/swipely/docker-api)
4
+
5
+ This gem provides an object-oriented interface to the [Docker Engine API](https://docs.docker.com/develop/sdk/). Every method listed there is implemented. At the time of this writing, docker-api is meant to interface with Docker version 1.4.*
6
+
7
+ If you're interested in using Docker to package your apps, we recommend the [dockly](https://github.com/swipely/dockly) gem. Dockly provides a simple DSL for describing Docker containers that install as Debian packages and are controlled by upstart scripts.
8
+
9
+ Installation
10
+ ------------
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'docker-api'
16
+ ```
17
+
18
+ And then run:
19
+
20
+ ```shell
21
+ $ bundle install
22
+ ```
23
+
24
+ Alternatively, if you wish to just use the gem in a script, you can run:
25
+
26
+ ```shell
27
+ $ gem install docker-api
28
+ ```
29
+
30
+ Finally, just add `require 'docker'` to the top of the file using this gem.
31
+
32
+ Usage
33
+ -----
34
+
35
+ docker-api is designed to be very lightweight. Almost no state is cached (aside from id's which are immutable) to ensure that each method call's information is up to date. As such, just about every external method represents an API call.
36
+
37
+ ## Starting up
38
+
39
+ Follow the [installation instructions](https://docs.docker.com/install/), and then run:
40
+
41
+ ```shell
42
+ $ sudo docker -d
43
+ ```
44
+
45
+ This will daemonize Docker so that it can be used for the remote API calls.
46
+
47
+ ### Host
48
+
49
+ If you're running Docker locally as a socket, there is no setup to do in Ruby. If you're not using a socket or have changed the path of the socket, you'll have to point the gem to your socket or local/remote port. For example:
50
+
51
+ ```ruby
52
+ Docker.url = 'tcp://example.com:5422'
53
+ ```
54
+
55
+ Two things to note here. The first is that this gem uses [excon](https://github.com/excon/excon), so any of the options that are valid for `Excon.new` are also valid for `Docker.options`. Second, by default Docker runs on a socket. The gem will assume you want to connect to the socket unless you specify otherwise.
56
+
57
+ Also, you may set the above variables via `ENV` variables. For example:
58
+
59
+ ```shell
60
+ $ DOCKER_URL=unix:///var/docker.sock irb
61
+ irb(main):001:0> require 'docker'
62
+ => true
63
+ irb(main):002:0> Docker.url
64
+ => "unix:///var/docker.sock"
65
+ irb(main):003:0> Docker.options
66
+ => {}
67
+ ```
68
+
69
+ ```shell
70
+ $ DOCKER_URL=tcp://example.com:1000 irb
71
+ irb(main):001:0> require 'docker'
72
+ => true
73
+ irb(main):003:0> Docker.url
74
+ => "tcp://example.com:1000"
75
+ irb(main):004:0> Docker.options
76
+ => {}
77
+ ```
78
+
79
+ Before doing anything else, ensure you have the correct version of the Docker API. To do this, run `Docker.validate_version!`. If your installed version is not supported, a `Docker::Error::VersionError` is raised.
80
+
81
+ ### SSL
82
+
83
+ When running docker using SSL, setting the DOCKER_CERT_PATH will configure docker-api to use SSL.
84
+ The cert path is a folder that contains the cert, key and cacert files.
85
+ docker-api is expecting the files to be named: cert.pem, key.pem, and ca.pem.
86
+ If your files are named different, you'll want to set your options explicity:
87
+
88
+ ```
89
+ Docker.options = {
90
+ client_cert: File.join(cert_path, 'cert.pem'),
91
+ client_key: File.join(cert_path, 'key.pem'),
92
+ ssl_ca_file: File.join(cert_path, 'ca.pem'),
93
+ scheme: 'https'
94
+ }
95
+ ```
96
+
97
+ If you want to load the cert files from a variable, e.g. you want to load them from ENV as needed on Heroku:
98
+
99
+ ```
100
+ cert_store = OpenSSL::X509::Store.new
101
+ certificate = OpenSSL::X509::Certificate.new ENV["DOCKER_CA"]
102
+ cert_store.add_cert certificate
103
+
104
+ Docker.options = {
105
+ client_cert_data: ENV["DOCKER_CERT"],
106
+ client_key_data: ENV["DOCKER_KEY"],
107
+ ssl_cert_store: cert_store,
108
+ scheme: 'https'
109
+ }
110
+ ```
111
+
112
+ If you need to disable SSL verification, set the DOCKER_SSL_VERIFY variable to 'false'.
113
+
114
+ ## Global calls
115
+
116
+ All of the following examples require a connection to a Docker server. See the <a href="#starting-up">Starting up</a> section above for more information.
117
+
118
+ ```ruby
119
+ require 'docker'
120
+ # => true
121
+
122
+ # docker command for reference: docker version
123
+ Docker.version
124
+ # => { 'Version' => '0.5.2', 'GoVersion' => 'go1.1' }
125
+
126
+ # docker command for reference: docker info
127
+ Docker.info
128
+ # => { "Debug" => false, "Containers" => 187, "Images" => 196, "NFd" => 10, "NGoroutines" => 9, "MemoryLimit" => true }
129
+
130
+ # docker command for reference: docker login
131
+ Docker.authenticate!('username' => 'docker-fan-boi', 'password' => 'i<3docker', 'email' => 'dockerboy22@aol.com')
132
+ # => true
133
+
134
+ # docker command for reference: docker login registry.gitlab.com
135
+ Docker.authenticate!('username' => 'docker-fan-boi', 'password' => 'i<3docker', 'email' => 'dockerboy22@aol.com', 'serveraddress' => 'https://registry.gitlab.com/v1/')
136
+ # => true
137
+ ```
138
+
139
+ ## Images
140
+
141
+ Just about every method here has a one-to-one mapping with the [Images](https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#2-2-images) section of the API. If an API call accepts query parameters, these can be passed as an Hash to it's corresponding method. Also, note that `Docker::Image.new` is a private method, so you must use `.create`, `.build`, `.build_from_dir`, `build_from_tar`, or `.import` to make an instance.
142
+
143
+ ```ruby
144
+ require 'docker'
145
+ # => true
146
+
147
+ # Pull an Image.
148
+ # docker command for reference: docker pull ubuntu:14.04
149
+ image = Docker::Image.create('fromImage' => 'ubuntu:14.04')
150
+ # => Docker::Image { :id => ae7ffbcd1, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
151
+
152
+ # Insert a local file into an Image.
153
+ image.insert_local('localPath' => 'Gemfile', 'outputPath' => '/')
154
+ # => Docker::Image { :id => 682ea192f, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
155
+
156
+ # Insert multiple local files into an Image.
157
+ image.insert_local('localPath' => [ 'Gemfile', 'Rakefile' ], 'outputPath' => '/')
158
+ # => Docker::Image { :id => eb693ec80, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
159
+
160
+ # Add a repo name to Image.
161
+ # docker command for reference: docker tag <IMAGE.ID> base2
162
+ image.tag('repo' => 'base2', 'force' => true)
163
+ # => ["base2"]
164
+
165
+ # Add a repo name and tag an Image.
166
+ # docker command for reference: docker tag <IMAGE.ID> base2:latest
167
+ image.tag('repo' => 'base2', 'tag' => 'latest', force: true)
168
+ # => ["base2:latest"]
169
+
170
+ # Get more information about the Image.
171
+ # docker command for reference: docker inspect <IMAGE.ID>
172
+ image.json
173
+ # => {"id"=>"67859327bf22ef8b5b9b4a6781f72b2015acd894fa03ce07e0db7af170ba468c", "comment"=>"Imported from -", "created"=>"2013-06-19T18:42:58.287944526-04:00", "container_config"=>{"Hostname"=>"", "User"=>"", "Memory"=>0, "MemorySwap"=>0, "CpuShares"=>0, "AttachStdin"=>false, "AttachStdout"=>false, "AttachStderr"=>false, "PortSpecs"=>nil, "Tty"=>false, "OpenStdin"=>false, "StdinOnce"=>false, "Env"=>nil, "Cmd"=>nil, "Dns"=>nil, "Image"=>"", "Volumes"=>nil, "VolumesFrom"=>""}, "docker_version"=>"0.4.0", "architecture"=>"x86_64"}
174
+
175
+ # View the history of the Image.
176
+ image.history
177
+ # => [{"Id"=>"67859327bf22", "Created"=>1371681778}]
178
+
179
+ # Push the Image to the Docker registry. Note that you have to login using
180
+ # `Docker.authenticate!` and tag the Image first.
181
+ # docker command for reference: docker push <IMAGE.ID>
182
+ image.push
183
+ # => Docker::Image { @connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} }, @info = { "id" => eb693ec80, "RepoTags" => ["base2", "base2/latest"]} }
184
+
185
+ # Push individual tag to the Docker registry.
186
+ image.push(nil, tag: "tag_name")
187
+ image.push(nil, repo_tag: 'registry/repo_name:tag_name')
188
+
189
+ # Given a command, create a new Container to run that command in the Image.
190
+ # docker command for reference: docker run -ti <IMAGE.ID> ls -l
191
+ image.run('ls -l')
192
+ # => Docker::Container { id => aaef712eda, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
193
+
194
+ # Remove the Image from the server.
195
+ # docker command for reference: docker rmi -f <IMAGE.ID>
196
+ image.remove(:force => true)
197
+ # => true
198
+
199
+ # Export a single Docker Image to a file
200
+ # docker command for reference: docker save <IMAGE.ID> my_export.tar
201
+ image.save('my_export.tar')
202
+ # => Docker::Image { :id => 66b712aef, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
203
+
204
+ # Return the raw image binary data
205
+ image.save
206
+ # => "abiglongbinarystring"
207
+
208
+ # Stream the contents of the image to a block:
209
+ image.save_stream { |chunk| puts chunk }
210
+ # => nil
211
+
212
+ # Given a Container's export, creates a new Image.
213
+ # docker command for reference: docker import some-export.tar
214
+ Docker::Image.import('some-export.tar')
215
+ # => Docker::Image { :id => 66b712aef, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
216
+
217
+ # `Docker::Image.import` can also import from a URI
218
+ Docker::Image.import('http://some-site.net/my-image.tar')
219
+ # => Docker::Image { :id => 6b462b2d2, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
220
+
221
+ # For a lower-level interface for importing tars, `Docker::Image.import_stream` may be used.
222
+ # It accepts a block, and will call that block until it returns an empty `String`.
223
+ File.open('my-export.tar') do |file|
224
+ Docker::Image.import_stream { file.read(1000).to_s }
225
+ end
226
+
227
+ # Create an Image from a Dockerfile as a String.
228
+ Docker::Image.build("from base\nrun touch /test")
229
+ # => Docker::Image { :id => b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
230
+
231
+ # Create an Image from a Dockerfile.
232
+ # docker command for reference: docker build .
233
+ Docker::Image.build_from_dir('.')
234
+ # => Docker::Image { :id => 1266dc19e, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
235
+
236
+ # Create an Image from a file other than Dockerfile.
237
+ # docker command for reference: docker build -f Dockerfile.Centos .
238
+ Docker::Image.build_from_dir('.', { 'dockerfile' => 'Dockerfile.Centos' })
239
+ # => Docker::Image { :id => 1266dc19e, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
240
+
241
+ # Create an Image from a Dockerfile and stream the logs
242
+ Docker::Image.build_from_dir('.') do |v|
243
+ if (log = JSON.parse(v)) && log.has_key?("stream")
244
+ $stdout.puts log["stream"]
245
+ end
246
+ end
247
+
248
+ # Create an Image from a tar file.
249
+ # docker command for reference: docker build - < docker_image.tar
250
+ Docker::Image.build_from_tar(File.open('docker_image.tar', 'r'))
251
+ # => Docker::Image { :id => 1266dc19e, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
252
+
253
+ # Load all Images on your Docker server.
254
+ # docker command for reference: docker images
255
+ Docker::Image.all
256
+ # => [Docker::Image { :id => b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
257
+
258
+ # Get Image from the server, with id
259
+ # docker command for reference: docker images <IMAGE.ID>
260
+ Docker::Image.get('df4f1bdecf40')
261
+ # => Docker::Image { :id => eb693ec80, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
262
+
263
+ # Check if an image with a given id exists on the server.
264
+ Docker::Image.exist?('ef723dcdac09')
265
+ # => true
266
+
267
+ # Load an image from the file system
268
+ Docker::Image.load('./my-image.tar')
269
+ # => ""
270
+
271
+ # An IO object may also be specified for loading
272
+ File.open('./my-image.tar', 'rb') do |file|
273
+ Docker::Image.load(file)
274
+ end
275
+ # => ""
276
+
277
+ # Export multiple images to a single tarball
278
+ # docker command for reference: docker save my_image1 my_image2:not_latest > my_export.tar
279
+ names = %w( my_image1 my_image2:not_latest )
280
+ Docker::Image.save(names, 'my_export.tar')
281
+ # => nil
282
+
283
+ # Return the raw image binary data
284
+ names = %w( my_image1 my_image2:not_latest )
285
+ Docker::Image.save(names)
286
+ # => "abiglongbinarystring"
287
+
288
+ # Stream the raw binary data
289
+ names = %w( my_image1 my_image2:not_latest )
290
+ Docker::Image.save_stream(names) { |chunk| puts chunk }
291
+ # => nil
292
+
293
+ # Search the Docker registry.
294
+ # docker command for reference: docker search sshd
295
+ Docker::Image.search('term' => 'sshd')
296
+ # => [Docker::Image { :id => cespare/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => johnfuller/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => dhrp/mongodb-sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => rayang2004/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => dhrp/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => toorop/daemontools-sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => toorop/daemontools-sshd-nginx, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => toorop/daemontools-sshd-nginx-php-fpm, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => mbkan/lamp, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => toorop/golang, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => wma55/u1210sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => jdswinbank/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }, Docker::Image { :id => vgauthier/sshd, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
297
+ ```
298
+
299
+ ## Containers
300
+
301
+ Much like the Images, this object also has a one-to-one mapping with the [Containers](https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#2-1-containers) section of the API. Also like Images, `.new` is a private method, so you must use `.create` to make an instance.
302
+
303
+ ```ruby
304
+ require 'docker'
305
+
306
+ # Create a Container.
307
+ container = Docker::Container.create('Cmd' => ['ls'], 'Image' => 'base')
308
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
309
+
310
+ # Get more information about the Container.
311
+ container.json
312
+ # => {"ID"=>"492510dd38e4da7703f36dfccd013de672b8250f57f59d1555ced647766b5e82", "Created"=>"2013-06-20T10:46:02.897548-04:00", "Path"=>"ls", "Args"=>[], "Config"=>{"Hostname"=>"492510dd38e4", "User"=>"", "Memory"=>0, "MemorySwap"=>0, "CpuShares"=>0, "AttachStdin"=>false, "AttachStdout"=>false, "AttachStderr"=>false, "PortSpecs"=>nil, "Tty"=>false, "OpenStdin"=>false, "StdinOnce"=>false, "Env"=>nil, "Cmd"=>["ls"], "Dns"=>nil, "Image"=>"base", "Volumes"=>nil, "VolumesFrom"=>""}, "State"=>{"Running"=>false, "Pid"=>0, "ExitCode"=>0, "StartedAt"=>"0001-01-01T00:00:00Z", "Ghost"=>false}, "Image"=>"b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", "NetworkSettings"=>{"IpAddress"=>"", "IpPrefixLen"=>0, "Gateway"=>"", "Bridge"=>"", "PortMapping"=>nil}, "SysInitPath"=>"/usr/bin/docker", "ResolvConfPath"=>"/etc/resolv.conf", "Volumes"=>nil}
313
+
314
+ # Start running the Container.
315
+ container.start
316
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
317
+
318
+ # Stop running the Container.
319
+ container.stop
320
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
321
+
322
+ # Restart the Container.
323
+ container.restart
324
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
325
+
326
+ # Pause the running Container processes.
327
+ container.pause
328
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
329
+
330
+ # Unpause the running Container processes.
331
+ container.unpause
332
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
333
+
334
+ # Kill the command running in the Container.
335
+ container.kill
336
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
337
+
338
+ # Kill the Container specifying the kill signal.
339
+ container.kill(:signal => "SIGHUP")
340
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
341
+
342
+ # Return the currently executing processes in a Container.
343
+ container.top
344
+ # => [{"PID"=>"4851", "TTY"=>"pts/0", "TIME"=>"00:00:00", "CMD"=>"lxc-start"}]
345
+
346
+ # Same as above, but uses the original format
347
+ container.top(format: :hash)
348
+ # => {
349
+ # "Titles" => ["PID", "TTY", "TIME", "CMD"],
350
+ # "Processes" => [["4851", "pts/0", "00:00:00", "lxc-start"]]
351
+ # }
352
+
353
+ # To expose 1234 to bridge
354
+ # In Dockerfile: EXPOSE 1234/tcp
355
+ # docker run resulting-image-name
356
+ Docker::Container.create(
357
+ 'Image' => 'image-name',
358
+ 'HostConfig' => {
359
+ 'PortBindings' => {
360
+ '1234/tcp' => [{}]
361
+ }
362
+ }
363
+ )
364
+
365
+ # To expose 1234 to host with any port
366
+ # docker run -p 1234 image-name
367
+ Docker::Container.create(
368
+ 'Image' => 'image-name',
369
+ 'ExposedPorts' => { '1234/tcp' => {} },
370
+ 'HostConfig' => {
371
+ 'PortBindings' => {
372
+ '1234/tcp' => [{}]
373
+ }
374
+ }
375
+ )
376
+
377
+ # To expose 1234 to host with a specified host port
378
+ # docker run -p 1234:1234 image-name
379
+ Docker::Container.create(
380
+ 'Image' => 'image-name',
381
+ 'ExposedPorts' => { '1234/tcp' => {} },
382
+ 'HostConfig' => {
383
+ 'PortBindings' => {
384
+ '1234/tcp' => [{ 'HostPort' => '1234' }]
385
+ }
386
+ }
387
+ )
388
+
389
+ # To expose 1234 to host with a specified host port and host IP
390
+ # docker run -p 192.168.99.100:1234:1234 image-name
391
+ Docker::Container.create(
392
+ 'Image' => 'image-name',
393
+ 'ExposedPorts' => { '1234/tcp' => {} },
394
+ 'HostConfig' => {
395
+ 'PortBindings' => {
396
+ '1234/tcp' => [{ 'HostPort' => '1234', 'HostIp' => '192.168.99.100' }]
397
+ }
398
+ }
399
+ )
400
+
401
+ # To set container name pass `name` key to options
402
+ Docker::Container.create(
403
+ 'name' => 'my-new-container',
404
+ 'Image' => 'image-name'
405
+ )
406
+
407
+ # Stores a file with the given content in the container
408
+ container.store_file("/test", "Hello world")
409
+
410
+ # Reads a file from the container
411
+ container.read_file("/test")
412
+ # => "Hello world"
413
+
414
+ # Export a Container. Since an export is typically at least 300M, chunks of the
415
+ # export are yielded instead of just returning the whole thing.
416
+ File.open('export.tar', 'w') do |file|
417
+ container.export { |chunk| file.write(chunk) }
418
+ end
419
+ # => nil
420
+
421
+ # Inspect a Container's changes to the file system.
422
+ container.changes
423
+ # => [{'Path'=>'/dev', 'Kind'=>0}, {'Path'=>'/dev/kmsg', 'Kind'=>1}]
424
+
425
+ # Copy files/directories from the Container. Note that these are exported as tars.
426
+ container.copy('/etc/hosts') { |chunk| puts chunk }
427
+
428
+ hosts0000644000000000000000000000023412100405636007023 0ustar
429
+ 127.0.0.1 localhost
430
+ ::1 localhost ip6-localhost ip6-loopback
431
+ fe00::0 ip6-localnet
432
+ ff00::0 ip6-mcastprefix
433
+ ff02::1 ip6-allnodes
434
+ ff02::2 ip6-allrouters
435
+ # => Docker::Container { :id => a1759f3e2873, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
436
+
437
+ # Wait for the current command to finish executing. If an argument is given,
438
+ # will timeout after that number of seconds. The default is one minute.
439
+ container.wait(15)
440
+ # => {'StatusCode'=>0}
441
+
442
+ # Attach to the Container. Currently, the below options are the only valid ones.
443
+ # By default, :stream, :stdout, and :stderr are set.
444
+ container.attach(:stream => true, :stdin => nil, :stdout => true, :stderr => true, :logs => true, :tty => false)
445
+ # => [["bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nselinux\nsrv\nsys\ntmp\nusr\nvar", []]
446
+
447
+ # If you wish to stream the attach method, a block may be supplied.
448
+ container = Docker::Container.create('Image' => 'base', 'Cmd' => ['find / -name *'])
449
+ container.tap(&:start).attach { |stream, chunk| puts "#{stream}: #{chunk}" }
450
+ stderr: 2013/10/30 17:16:24 Unable to locate find / -name *
451
+ # => [[], ["2013/10/30 17:16:24 Unable to locate find / -name *\n"]]
452
+
453
+ # If you want to attach to stdin of the container, supply an IO-like object:
454
+ container = Docker::Container.create('Image' => 'base', 'Cmd' => ['cat'], 'OpenStdin' => true, 'StdinOnce' => true)
455
+ container.tap(&:start).attach(stdin: StringIO.new("foo\nbar\n"))
456
+ # => [["foo\nbar\n"], []]
457
+
458
+ # Similar to the stdout/stderr attach method, there is logs and streaming_logs
459
+
460
+ # logs will only return after the container has exited. The output will be the raw output from the logs stream.
461
+ # streaming_logs will collect the messages out of the multiplexed form and also execute a block on each line that comes in (block takes a stream and a chunk as arguments)
462
+
463
+ # Raw logs from a TTY-enabled container after exit
464
+ container.logs(stdout: true)
465
+ # => "\e]0;root@8866c76564e8: /\aroot@8866c76564e8:/# echo 'i\b \bdocker-api'\r\ndocker-api\r\n\e]0;root@8866c76564e8: /\aroot@8866c76564e8:/# exit\r\n"
466
+
467
+ # Logs from a non-TTY container with multiplex prefix
468
+ container.logs(stdout: true)
469
+ # => "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00021\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00022\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00023\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00024\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00025\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00026\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00027\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00028\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00029\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u000310\n"
470
+
471
+ # Streaming logs from non-TTY container removing multiplex prefix with a block printing out each line (block not possible with Container#logs)
472
+ container.streaming_logs(stdout: true) { |stream, chunk| puts "#{stream}: #{chunk}" }
473
+ stdout: 1
474
+ stdout: 2
475
+ stdout: 3
476
+ stdout: 4
477
+ stdout: 5
478
+ stdout: 6
479
+ stdout: 7
480
+ stdout: 8
481
+ stdout: 9
482
+ stdout: 10
483
+ # => "1\n\n2\n\n3\n\n4\n\n5\n\n6\n\n7\n\n8\n\n9\n\n10\n"
484
+
485
+ # If the container has TTY enabled, set `tty => true` to get the raw stream:
486
+ command = ["bash", "-c", "if [ -t 1 ]; then echo -n \"I'm a TTY!\"; fi"]
487
+ container = Docker::Container.create('Image' => 'ubuntu', 'Cmd' => command, 'Tty' => true)
488
+ container.tap(&:start).attach(:tty => true)
489
+ # => [["I'm a TTY!"], []]
490
+
491
+ # Obtaining the current statistics of a container
492
+ container.stats
493
+ # => {"read"=>"2016-02-29T20:47:05.221608695Z", "precpu_stats"=>{"cpu_usage"=> ... }
494
+
495
+ # Create an Image from a Container's changes.
496
+ container.commit
497
+ # => Docker::Image { :id => eaeb8d00efdf, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
498
+
499
+ # Commit the Container and run a new command. The second argument is the number
500
+ # of seconds the Container should wait before stopping its current command.
501
+ container.run('pwd', 10)
502
+ # => Docker::Image { :id => 4427be4199ac, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
503
+
504
+ # Run an Exec instance inside the container and capture its output and exit status
505
+ container.exec(['date'])
506
+ # => [["Wed Nov 26 11:10:30 CST 2014\n"], [], 0]
507
+
508
+ # Launch an Exec instance without capturing its output or status
509
+ container.exec(['./my_service'], detach: true)
510
+ # => Docker::Exec { :id => be4eaeb8d28a, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
511
+
512
+ # Parse the output of an Exec instance
513
+ container.exec(['find', '/', '-name *']) { |stream, chunk| puts "#{stream}: #{chunk}" }
514
+ stderr: 2013/10/30 17:16:24 Unable to locate find / -name *
515
+ # => [[], ["2013/10/30 17:16:24 Unable to locate find / -name *\n"], 1]
516
+
517
+ # Run an Exec instance by grab only the STDOUT output
518
+ container.exec(['date'], stderr: false)
519
+ # => [["Wed Nov 26 11:10:30 CST 2014\n"], [], 0]
520
+
521
+ # Pass input to an Exec instance command via Stdin
522
+ container.exec(['cat'], stdin: StringIO.new("foo\nbar\n"))
523
+ # => [["foo\nbar\n"], [], 0]
524
+
525
+ # Get the raw stream of data from an Exec instance
526
+ command = ["bash", "-c", "if [ -t 1 ]; then echo -n \"I'm a TTY!\"; fi"]
527
+ container.exec(command, tty: true)
528
+ # => [["I'm a TTY!"], [], 0]
529
+
530
+ # Wait for the current command to finish executing. If an argument is given,
531
+ # will timeout after that number of seconds. The default is one minute.
532
+ command = ["bash", "-c", "if [ -t 1 ]; then echo -n \"Set max seconds for exec!!\"; fi"]
533
+ container.exec(command, wait: 120)
534
+ # => [["Set max seconds for exec!"], [], 0]
535
+
536
+ # Delete a Container.
537
+ container.delete(:force => true)
538
+ # => nil
539
+
540
+ # Update the container.
541
+ container.update("CpuShares" => 50000")
542
+
543
+ # Request a Container by ID or name.
544
+ Docker::Container.get('500f53b25e6e')
545
+ # => Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
546
+
547
+ # Request all of the Containers. By default, will only return the running Containers.
548
+ Docker::Container.all(:all => true)
549
+ # => [Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
550
+ ```
551
+
552
+ ## JSON encoded values
553
+
554
+ For JSON encoded values, nothing is done implicitly, meaning you need to explicitly call `to_json` on your parameter before the call. For example, to request all of the Containers using a filter:
555
+
556
+ ```ruby
557
+ require 'docker'
558
+
559
+ # Request all of the Containers, filtering by status exited.
560
+ Docker::Container.all(all: true, filters: { status: ["exited"] }.to_json)
561
+ # => [Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
562
+
563
+ # Request all of the Container, filtering by label_name.
564
+ Docker::Container.all(all: true, filters: { label: [ "label_name" ] }.to_json)
565
+ # => [Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
566
+
567
+ # Request all of the Container, filtering by label label_name that have the value label_value_.
568
+ Docker::Container.all(all: true, filters: { label: [ "label_name=label_value" ] }.to_json)
569
+ # => [Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }]
570
+ ```
571
+
572
+ This applies for all parameters that are requested to be JSON encoded by the docker api.
573
+
574
+ ## Events
575
+
576
+ ```ruby
577
+ require 'docker'
578
+
579
+ # Action on a stream of events as they come in
580
+ Docker::Event.stream { |event| puts event; break }
581
+ Docker::Event { :status => create, :id => aeb8b55726df63bdd69d41e1b2650131d7ce32ca0d2fa5cbc75f24d0df34c7b0, :from => base:latest, :time => 1416958554 }
582
+ # => nil
583
+
584
+ # Action on all events after a given time (will execute the block for all events up till the current time, and wait to execute on any new events after)
585
+ Docker::Event.since(1416958763) { |event| puts event; puts Time.now.to_i; break }
586
+ Docker::Event { :status => die, :id => 663005cdeb56f50177c395a817dbc8bdcfbdfbdaef329043b409ecb97fb68d7e, :from => base:latest, :time => 1416958764 }
587
+ 1416959041
588
+ # => nil
589
+ ```
590
+
591
+ These methods are prone to read timeouts. `Docker.options[:read_timeout]` will need to be made higher than 60 seconds if expecting a long time between events.
592
+
593
+ ## Connecting to Multiple Servers
594
+
595
+ By default, each object connects to the connection specified by `Docker.connection`. If you need to connect to multiple servers, you can do so by specifying the connection on `#new` or in the utilizing class method. For example:
596
+
597
+ ```ruby
598
+ require 'docker'
599
+
600
+ Docker::Container.all({}, Docker::Connection.new('tcp://example.com:2375', {}))
601
+ ```
602
+
603
+ ## Rake Task
604
+
605
+ To create images through `rake`, a DSL task is provided. For example:
606
+
607
+
608
+ ```ruby
609
+ require 'rake'
610
+ require 'docker'
611
+
612
+ image 'repo:tag' do
613
+ image = Docker::Image.create('fromImage' => 'repo', 'tag' => 'old_tag')
614
+ image = Docker::Image.run('rm -rf /etc').commit
615
+ image.tag('repo' => 'repo', 'tag' => 'tag')
616
+ end
617
+
618
+ image 'repo:new_tag' => 'repo:tag' do
619
+ image = Docker::Image.create('fromImage' => 'repo', 'tag' => 'tag')
620
+ image = image.insert_local('localPath' => 'some-file.tar.gz', 'outputPath' => '/')
621
+ image.tag('repo' => 'repo', 'tag' => 'new_tag')
622
+ end
623
+ ```
624
+
625
+ ## Not supported (yet)
626
+
627
+ * Generating a tarball of images and metadata for a repository specified by a name: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#get-a-tarball-containing-all-images-and-tags-in-a-repository
628
+ * Load a tarball generated from docker that contains all the images and metadata of a repository: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#load-a-tarball-with-a-set-of-images-and-tags-into-docker
629
+
630
+ License
631
+ -----
632
+
633
+ This program is licensed under the MIT license. See LICENSE for details.