docker-api 1.27.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +110 -10
- data/lib/docker.rb +7 -14
- data/lib/docker/connection.rb +3 -3
- data/lib/docker/container.rb +103 -45
- data/lib/docker/event.rb +100 -14
- data/lib/docker/exec.rb +6 -6
- data/lib/docker/image.rb +32 -11
- data/lib/docker/network.rb +16 -12
- data/lib/docker/util.rb +56 -16
- data/lib/docker/version.rb +1 -4
- data/lib/docker/volume.rb +8 -4
- metadata +16 -66
- data/.cane +0 -2
- data/.gitignore +0 -6
- data/.rspec +0 -1
- data/.simplecov +0 -4
- data/.travis.yml +0 -25
- data/Dockerfile +0 -2
- data/Gemfile +0 -3
- data/Rakefile +0 -54
- data/TESTING.md +0 -49
- data/docker-api.gemspec +0 -28
- data/script/docker +0 -149
- data/script/docker.conf +0 -61
- data/script/install_docker.sh +0 -35
- data/spec/docker/connection_spec.rb +0 -123
- data/spec/docker/container_spec.rb +0 -801
- data/spec/docker/event_spec.rb +0 -89
- data/spec/docker/exec_spec.rb +0 -181
- data/spec/docker/image_spec.rb +0 -683
- data/spec/docker/messages_spec.rb +0 -97
- data/spec/docker/messages_stack.rb +0 -26
- data/spec/docker/network_spec.rb +0 -150
- data/spec/docker/util_spec.rb +0 -154
- data/spec/docker/volume_spec.rb +0 -46
- data/spec/docker_spec.rb +0 -258
- data/spec/fixtures/build_from_dir/Dockerfile +0 -2
- data/spec/fixtures/export.tar +0 -0
- data/spec/fixtures/load.tar +0 -0
- data/spec/fixtures/top/Dockerfile +0 -2
- data/spec/spec_helper.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7c8d229ece5b5b347a925c62c3f199a940393e58de0b02049aed295090739b04
|
4
|
+
data.tar.gz: 619467ed3697f6b9221f89bab145ba298bd47f5f26209e86df89347b6e83fe08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a1a3a2a995c4a172217fc80eb573501502f7f05a337080bf4723d90bb2ba9053cde786aaa994993bd2841ebeeb18cc8a5e4dfa342792bb558fb84a3f4688b89
|
7
|
+
data.tar.gz: c9bbb7ae229ba1784859ddb0e3bc6e7df1651718d552779baac4e2ad49d34096aba760e6ce99fa41dfd14ef6ea0f3a5ddfc9178cf1c7c7f286a8385be1c59385
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
docker-api
|
2
2
|
==========
|
3
|
-
[](https://badge.fury.io/rb/docker-api) [](https://travis-ci.org/swipely/docker-api) [](https://codeclimate.com/github/swipely/docker-api)
|
4
4
|
|
5
|
-
This gem provides an object-oriented interface to the [Docker
|
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
6
|
|
7
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
8
|
|
@@ -36,7 +36,7 @@ docker-api is designed to be very lightweight. Almost no state is cached (aside
|
|
36
36
|
|
37
37
|
## Starting up
|
38
38
|
|
39
|
-
Follow the [installation instructions](https://docs.docker.com/
|
39
|
+
Follow the [installation instructions](https://docs.docker.com/install/), and then run:
|
40
40
|
|
41
41
|
```shell
|
42
42
|
$ sudo docker -d
|
@@ -52,7 +52,7 @@ If you're running Docker locally as a socket, there is no setup to do in Ruby. I
|
|
52
52
|
Docker.url = 'tcp://example.com:5422'
|
53
53
|
```
|
54
54
|
|
55
|
-
Two things to note here. The first is that this gem uses [excon](
|
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
56
|
|
57
57
|
Also, you may set the above variables via `ENV` variables. For example:
|
58
58
|
|
@@ -94,6 +94,21 @@ Docker.options = {
|
|
94
94
|
}
|
95
95
|
```
|
96
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
|
+
|
97
112
|
If you need to disable SSL verification, set the DOCKER_SSL_VERIFY variable to 'false'.
|
98
113
|
|
99
114
|
## Global calls
|
@@ -108,13 +123,17 @@ require 'docker'
|
|
108
123
|
Docker.version
|
109
124
|
# => { 'Version' => '0.5.2', 'GoVersion' => 'go1.1' }
|
110
125
|
|
111
|
-
# docker command for reference: docker info
|
126
|
+
# docker command for reference: docker info
|
112
127
|
Docker.info
|
113
128
|
# => { "Debug" => false, "Containers" => 187, "Images" => 196, "NFd" => 10, "NGoroutines" => 9, "MemoryLimit" => true }
|
114
129
|
|
115
130
|
# docker command for reference: docker login
|
116
131
|
Docker.authenticate!('username' => 'docker-fan-boi', 'password' => 'i<3docker', 'email' => 'dockerboy22@aol.com')
|
117
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
|
118
137
|
```
|
119
138
|
|
120
139
|
## Images
|
@@ -245,6 +264,16 @@ Docker::Image.get('df4f1bdecf40')
|
|
245
264
|
Docker::Image.exist?('ef723dcdac09')
|
246
265
|
# => true
|
247
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
|
+
|
248
277
|
# Export multiple images to a single tarball
|
249
278
|
# docker command for reference: docker save my_image1 my_image2:not_latest > my_export.tar
|
250
279
|
names = %w( my_image1 my_image2:not_latest )
|
@@ -314,9 +343,77 @@ container.kill(:signal => "SIGHUP")
|
|
314
343
|
container.top
|
315
344
|
# => [{"PID"=>"4851", "TTY"=>"pts/0", "TIME"=>"00:00:00", "CMD"=>"lxc-start"}]
|
316
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
|
+
|
317
414
|
# Export a Container. Since an export is typically at least 300M, chunks of the
|
318
415
|
# export are yielded instead of just returning the whole thing.
|
319
|
-
File.open('export.tar', 'w') do |
|
416
|
+
File.open('export.tar', 'w') do |file|
|
320
417
|
container.export { |chunk| file.write(chunk) }
|
321
418
|
end
|
322
419
|
# => nil
|
@@ -391,6 +488,10 @@ container = Docker::Container.create('Image' => 'ubuntu', 'Cmd' => command, 'Tty
|
|
391
488
|
container.tap(&:start).attach(:tty => true)
|
392
489
|
# => [["I'm a TTY!"], []]
|
393
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
|
+
|
394
495
|
# Create an Image from a Container's changes.
|
395
496
|
container.commit
|
396
497
|
# => Docker::Image { :id => eaeb8d00efdf, :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
|
@@ -436,6 +537,9 @@ container.exec(command, wait: 120)
|
|
436
537
|
container.delete(:force => true)
|
437
538
|
# => nil
|
438
539
|
|
540
|
+
# Update the container.
|
541
|
+
container.update("CpuShares" => 50000")
|
542
|
+
|
439
543
|
# Request a Container by ID or name.
|
440
544
|
Docker::Container.get('500f53b25e6e')
|
441
545
|
# => Docker::Container { :id => , :connection => Docker::Connection { :url => tcp://localhost, :options => {:port=>2375} } }
|
@@ -518,10 +622,6 @@ image 'repo:new_tag' => 'repo:tag' do
|
|
518
622
|
end
|
519
623
|
```
|
520
624
|
|
521
|
-
## Known issues
|
522
|
-
|
523
|
-
* If the docker daemon is always responding to your requests with a 400 Bad Request when using UNIX sockets, verify you're running Excon version 0.46.0 or greater. [Link](https://github.com/swipely/docker-api/issues/381)
|
524
|
-
|
525
625
|
## Not supported (yet)
|
526
626
|
|
527
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
|
data/lib/docker.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'cgi'
|
2
|
-
require '
|
2
|
+
require 'multi_json'
|
3
3
|
require 'excon'
|
4
4
|
require 'tempfile'
|
5
5
|
require 'base64'
|
@@ -14,7 +14,9 @@ require 'open-uri'
|
|
14
14
|
require 'excon/middlewares/hijack'
|
15
15
|
Excon.defaults[:middlewares].unshift Excon::Middleware::Hijack
|
16
16
|
|
17
|
-
|
17
|
+
Excon.defaults[:middlewares] << Excon::Middleware::RedirectFollower
|
18
|
+
|
19
|
+
# The top-level module for this gem. Its purpose is to hold global
|
18
20
|
# configuration variables that are used as defaults in other classes.
|
19
21
|
module Docker
|
20
22
|
attr_accessor :creds, :logger
|
@@ -119,25 +121,16 @@ module Docker
|
|
119
121
|
|
120
122
|
# Login to the Docker registry.
|
121
123
|
def authenticate!(options = {}, connection = self.connection)
|
122
|
-
creds = options
|
123
|
-
connection.post('/auth', {}, :
|
124
|
+
creds = MultiJson.dump(options)
|
125
|
+
connection.post('/auth', {}, body: creds)
|
124
126
|
@creds = creds
|
125
127
|
true
|
126
128
|
rescue Docker::Error::ServerError, Docker::Error::UnauthorizedError
|
127
129
|
raise Docker::Error::AuthenticationError
|
128
130
|
end
|
129
131
|
|
130
|
-
# When the correct version of Docker is installed, returns true. Otherwise,
|
131
|
-
# raises a VersionError.
|
132
|
-
def validate_version!
|
133
|
-
Docker.info
|
134
|
-
true
|
135
|
-
rescue Docker::Error::DockerError
|
136
|
-
raise Docker::Error::VersionError, "Expected API Version: #{API_VERSION}"
|
137
|
-
end
|
138
|
-
|
139
132
|
module_function :default_socket_url, :env_url, :url, :url=, :env_options,
|
140
133
|
:options, :options=, :creds, :creds=, :logger, :logger=,
|
141
134
|
:connection, :reset!, :reset_connection!, :version, :info,
|
142
|
-
:ping, :authenticate!, :
|
135
|
+
:ping, :authenticate!, :ssl_options
|
143
136
|
end
|
data/lib/docker/connection.rb
CHANGED
@@ -80,14 +80,14 @@ private
|
|
80
80
|
user_agent = "Swipely/Docker-API #{Docker::VERSION}"
|
81
81
|
{
|
82
82
|
:method => http_method,
|
83
|
-
:path =>
|
83
|
+
:path => path,
|
84
84
|
:query => query,
|
85
85
|
:headers => { 'Content-Type' => content_type,
|
86
86
|
'User-Agent' => user_agent,
|
87
87
|
}.merge(headers),
|
88
|
-
:expects => (200..204).to_a << 304,
|
88
|
+
:expects => (200..204).to_a << 301 << 304,
|
89
89
|
:idempotent => http_method == :get,
|
90
|
-
:request_block => block
|
90
|
+
:request_block => block,
|
91
91
|
}.merge(opts).reject { |_, v| v.nil? }
|
92
92
|
end
|
93
93
|
end
|
data/lib/docker/container.rb
CHANGED
@@ -11,17 +11,18 @@ class Docker::Container
|
|
11
11
|
}
|
12
12
|
|
13
13
|
info.merge!(self.json)
|
14
|
-
other && info.merge!(other.info)
|
14
|
+
other && info.merge!(other.info) { |key, info_value, other_value| info_value }
|
15
15
|
self
|
16
16
|
end
|
17
17
|
|
18
18
|
# Return a List of Hashes that represents the top running processes.
|
19
19
|
def top(opts = {})
|
20
|
+
format = opts.delete(:format) { :array }
|
20
21
|
resp = Docker::Util.parse_json(connection.get(path_for(:top), opts))
|
21
22
|
if resp['Processes'].nil?
|
22
|
-
[]
|
23
|
+
format == :array ? [] : {}
|
23
24
|
else
|
24
|
-
resp['Processes'].map { |ary| Hash[resp['Titles'].zip(ary)] }
|
25
|
+
format == :array ? resp['Processes'].map { |ary| Hash[resp['Titles'].zip(ary)] } : resp
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -51,33 +52,37 @@ class Docker::Container
|
|
51
52
|
# @param options [Hash] The options to pass to Docker::Exec
|
52
53
|
#
|
53
54
|
# @return [Docker::Exec] The Exec instance
|
54
|
-
def exec(command,
|
55
|
+
def exec(command, options = {}, &block)
|
55
56
|
# Establish values
|
56
|
-
tty =
|
57
|
-
detach =
|
58
|
-
user =
|
59
|
-
stdin =
|
60
|
-
stdout =
|
61
|
-
stderr =
|
57
|
+
tty = options.delete(:tty) || false
|
58
|
+
detach = options.delete(:detach) || false
|
59
|
+
user = options.delete(:user)
|
60
|
+
stdin = options.delete(:stdin)
|
61
|
+
stdout = options.delete(:stdout) || !detach
|
62
|
+
stderr = options.delete(:stderr) || !detach
|
63
|
+
wait = options.delete(:wait)
|
64
|
+
|
65
|
+
opts = {
|
66
|
+
'Container' => self.id,
|
67
|
+
'User' => user,
|
68
|
+
'AttachStdin' => !!stdin,
|
69
|
+
'AttachStdout' => stdout,
|
70
|
+
'AttachStderr' => stderr,
|
71
|
+
'Tty' => tty,
|
72
|
+
'Cmd' => command
|
73
|
+
}.merge(options)
|
62
74
|
|
63
75
|
# Create Exec Instance
|
64
76
|
instance = Docker::Exec.create(
|
65
|
-
|
66
|
-
'Container' => self.id,
|
67
|
-
'User' => user,
|
68
|
-
'AttachStdin' => !!stdin,
|
69
|
-
'AttachStdout' => stdout,
|
70
|
-
'AttachStderr' => stderr,
|
71
|
-
'Tty' => tty,
|
72
|
-
'Cmd' => command
|
73
|
-
},
|
77
|
+
opts,
|
74
78
|
self.connection
|
75
79
|
)
|
76
80
|
|
77
81
|
start_opts = {
|
78
82
|
:tty => tty,
|
79
83
|
:stdin => stdin,
|
80
|
-
:detach => detach
|
84
|
+
:detach => detach,
|
85
|
+
:wait => wait
|
81
86
|
}
|
82
87
|
|
83
88
|
if detach
|
@@ -95,7 +100,7 @@ class Docker::Container
|
|
95
100
|
end
|
96
101
|
|
97
102
|
# Attach to a container's standard streams / logs.
|
98
|
-
def attach(options = {}, &block)
|
103
|
+
def attach(options = {}, excon_params = {}, &block)
|
99
104
|
stdin = options.delete(:stdin)
|
100
105
|
tty = options.delete(:tty)
|
101
106
|
|
@@ -105,8 +110,6 @@ class Docker::Container
|
|
105
110
|
# Creates list to store stdout and stderr messages
|
106
111
|
msgs = Docker::Messages.new
|
107
112
|
|
108
|
-
excon_params = {}
|
109
|
-
|
110
113
|
if stdin
|
111
114
|
# If attaching to stdin, we must hijack the underlying TCP connection
|
112
115
|
# so we can stream stdin to the remote Docker process
|
@@ -132,10 +135,10 @@ class Docker::Container
|
|
132
135
|
# Based on the link, the config passed as run, needs to be passed as the
|
133
136
|
# body of the post so capture it, remove from the options, and pass it via
|
134
137
|
# the post body
|
135
|
-
config = options.delete('run')
|
136
|
-
hash = Docker::Util.parse_json(
|
137
|
-
|
138
|
-
|
138
|
+
config = MultiJson.dump(options.delete('run'))
|
139
|
+
hash = Docker::Util.parse_json(
|
140
|
+
connection.post('/commit', options, body: config)
|
141
|
+
)
|
139
142
|
Docker::Image.send(:new, self.connection, hash)
|
140
143
|
end
|
141
144
|
|
@@ -156,24 +159,47 @@ class Docker::Container
|
|
156
159
|
connection.get(path_for(:logs), opts)
|
157
160
|
end
|
158
161
|
|
162
|
+
def stats(options = {})
|
163
|
+
if block_given?
|
164
|
+
options[:read_timeout] ||= 10
|
165
|
+
options[:idempotent] ||= false
|
166
|
+
parser = lambda do |chunk, remaining_bytes, total_bytes|
|
167
|
+
yield Docker::Util.parse_json(chunk)
|
168
|
+
end
|
169
|
+
begin
|
170
|
+
connection.get(path_for(:stats), nil, {response_block: parser}.merge(options))
|
171
|
+
rescue Docker::Error::TimeoutError
|
172
|
+
# If the container stops, the docker daemon will hold the connection
|
173
|
+
# open forever, but stop sending events.
|
174
|
+
# So this Timeout indicates the stream is over.
|
175
|
+
end
|
176
|
+
else
|
177
|
+
Docker::Util.parse_json(connection.get(path_for(:stats), {stream: 0}.merge(options)))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
159
181
|
def rename(new_name)
|
160
182
|
query = {}
|
161
183
|
query['name'] = new_name
|
162
184
|
connection.post(path_for(:rename), query)
|
163
185
|
end
|
164
186
|
|
187
|
+
def update(opts)
|
188
|
+
connection.post(path_for(:update), {}, body: MultiJson.dump(opts))
|
189
|
+
end
|
190
|
+
|
165
191
|
def streaming_logs(opts = {}, &block)
|
166
|
-
stack_size = opts.delete('stack_size') || -1
|
192
|
+
stack_size = opts.delete('stack_size') || opts.delete(:stack_size) || -1
|
167
193
|
tty = opts.delete('tty') || opts.delete(:tty) || false
|
168
194
|
msgs = Docker::MessagesStack.new(stack_size)
|
169
|
-
excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty)}
|
195
|
+
excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty), idempotent: false}
|
170
196
|
|
171
197
|
connection.get(path_for(:logs), opts, excon_params)
|
172
198
|
msgs.messages.join
|
173
199
|
end
|
174
200
|
|
175
201
|
def start!(opts = {})
|
176
|
-
connection.post(path_for(:start), {}, :
|
202
|
+
connection.post(path_for(:start), {}, body: MultiJson.dump(opts))
|
177
203
|
self
|
178
204
|
end
|
179
205
|
|
@@ -198,8 +224,18 @@ class Docker::Container
|
|
198
224
|
define_method(:"#{method}!") do |opts = {}|
|
199
225
|
timeout = opts.delete('timeout')
|
200
226
|
query = {}
|
201
|
-
|
202
|
-
|
227
|
+
request_options = {
|
228
|
+
:body => MultiJson.dump(opts)
|
229
|
+
}
|
230
|
+
if timeout
|
231
|
+
query['t'] = timeout
|
232
|
+
# Ensure request does not timeout before Docker timeout
|
233
|
+
request_options.merge!(
|
234
|
+
read_timeout: timeout.to_i + 5,
|
235
|
+
write_timeout: timeout.to_i + 5
|
236
|
+
)
|
237
|
+
end
|
238
|
+
connection.post(path_for(method), query, request_options)
|
203
239
|
self
|
204
240
|
end
|
205
241
|
|
@@ -230,14 +266,6 @@ class Docker::Container
|
|
230
266
|
end
|
231
267
|
end
|
232
268
|
|
233
|
-
def copy(path, &block)
|
234
|
-
connection.post(path_for(:copy), {},
|
235
|
-
:body => { "Resource" => path }.to_json,
|
236
|
-
:response_block => block
|
237
|
-
)
|
238
|
-
self
|
239
|
-
end
|
240
|
-
|
241
269
|
def archive_out(path, &block)
|
242
270
|
connection.get(
|
243
271
|
path_for(:archive),
|
@@ -269,19 +297,43 @@ class Docker::Container
|
|
269
297
|
self
|
270
298
|
end
|
271
299
|
|
300
|
+
def read_file(path)
|
301
|
+
content = StringIO.new
|
302
|
+
archive_out(path) do |chunk|
|
303
|
+
content.write chunk
|
304
|
+
end
|
305
|
+
|
306
|
+
content.rewind
|
307
|
+
|
308
|
+
Gem::Package::TarReader.new(content) do |tar|
|
309
|
+
tar.each do |tarfile|
|
310
|
+
return tarfile.read
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def store_file(path, file_content)
|
316
|
+
output_io = StringIO.new(
|
317
|
+
Docker::Util.create_tar(
|
318
|
+
path => file_content
|
319
|
+
)
|
320
|
+
)
|
321
|
+
|
322
|
+
archive_in_stream("/", overwrite: true) { output_io.read }
|
323
|
+
end
|
324
|
+
|
272
325
|
# Create a new Container.
|
273
326
|
def self.create(opts = {}, conn = Docker.connection)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
resp = conn.post('/containers/create', query, :body => opts.to_json)
|
327
|
+
query = opts.select {|key| ['name', :name].include?(key) }
|
328
|
+
clean_opts = opts.reject {|key| ['name', :name].include?(key) }
|
329
|
+
resp = conn.post('/containers/create', query, :body => MultiJson.dump(clean_opts))
|
278
330
|
hash = Docker::Util.parse_json(resp) || {}
|
279
331
|
new(conn, hash)
|
280
332
|
end
|
281
333
|
|
282
334
|
# Return the container with specified ID
|
283
335
|
def self.get(id, opts = {}, conn = Docker.connection)
|
284
|
-
container_json = conn.get("/containers/#{
|
336
|
+
container_json = conn.get("/containers/#{id}/json", opts)
|
285
337
|
hash = Docker::Util.parse_json(container_json) || {}
|
286
338
|
new(conn, hash)
|
287
339
|
end
|
@@ -292,6 +344,12 @@ class Docker::Container
|
|
292
344
|
hashes.map { |hash| new(conn, hash) }
|
293
345
|
end
|
294
346
|
|
347
|
+
# Prune images
|
348
|
+
def self.prune(conn = Docker.connection)
|
349
|
+
conn.post("/containers/prune", {})
|
350
|
+
nil
|
351
|
+
end
|
352
|
+
|
295
353
|
# Convenience method to return the path for a particular resource.
|
296
354
|
def path_for(resource)
|
297
355
|
"/containers/#{self.id}/#{resource}"
|