dc 0.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 +7 -0
- data/bin/dc +4 -0
- data/lib/dc.rb +200 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a1778827651668547f6a5ea1e41c8c29ad99f9675e8ecb0982f16e7fe41838e3
|
4
|
+
data.tar.gz: aaca72cc50e107ebfd0f6ba6517c1562d8b492217dfef2812048aef658e1c12b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b540e943a2b221b098565ab653a9dc98ad240cc31b9076bb4736c4273ecd271dc301c47eb41d315f81a7caa3cacc05fdee5f97220c736b3e0ecc673b83202c0c
|
7
|
+
data.tar.gz: fc98f1883b3a9daae99d646f75fd593124d547ad024590e1979078b5f0aef241cecac9198855e072239fb6adef2096406a51208b0cffce5ca407368c3da2d377
|
data/bin/dc
ADDED
data/lib/dc.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
module DC
|
2
|
+
require 'forwardable'
|
3
|
+
require 'yaml'
|
4
|
+
require 'docker'
|
5
|
+
|
6
|
+
class Container
|
7
|
+
def initialize name, ports: []
|
8
|
+
@name = name
|
9
|
+
@container = if ports.empty?
|
10
|
+
Docker::Container.create name: name, Image: name
|
11
|
+
else
|
12
|
+
port_maps = ports.map do |port|
|
13
|
+
if port.is_a? PortMap
|
14
|
+
port
|
15
|
+
else
|
16
|
+
to, from = port.split ':'
|
17
|
+
PortMap.new from: from, to: to
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Docker::Container.create(
|
22
|
+
name: name, Image: name,
|
23
|
+
ExposedPorts: port_maps.map do |map|
|
24
|
+
["#{map.internal_port}/tcp", {}]
|
25
|
+
end.to_h,
|
26
|
+
HostConfig: {
|
27
|
+
PortBindings: port_maps.map do |map|
|
28
|
+
array = [{ HostPort: map.external_port, HostIp: map.external_ip }]
|
29
|
+
["#{map.internal_port}/tcp", array]
|
30
|
+
end.to_h
|
31
|
+
}
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :name
|
37
|
+
|
38
|
+
def internal_container
|
39
|
+
@container
|
40
|
+
end
|
41
|
+
|
42
|
+
extend Forwardable
|
43
|
+
delegate [:id, :start, :kill!, :remove] => :internal_container
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
kill!.remove
|
47
|
+
end
|
48
|
+
|
49
|
+
class PortMap
|
50
|
+
def initialize from:, to:, external_ip: '0.0.0.0'
|
51
|
+
@internal_port = from.to_s
|
52
|
+
@external_port = to.to_s
|
53
|
+
@external_ip = external_ip
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_reader :internal_port, :external_port, :external_ip
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Image
|
61
|
+
class << self
|
62
|
+
def all
|
63
|
+
@all ||= {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def [] name
|
67
|
+
all[name]
|
68
|
+
end
|
69
|
+
|
70
|
+
def []= name, image
|
71
|
+
all[name] = image
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize name, directory: name
|
76
|
+
@name = name
|
77
|
+
@directory = directory
|
78
|
+
self.class[name] = self
|
79
|
+
end
|
80
|
+
|
81
|
+
attr_reader :name
|
82
|
+
|
83
|
+
def exist?
|
84
|
+
Docker::Image.exist? @name
|
85
|
+
end
|
86
|
+
|
87
|
+
def build
|
88
|
+
build_parent_image_if_available
|
89
|
+
image = Docker::Image.build_from_dir @directory do |json|
|
90
|
+
puts JSON.parse json
|
91
|
+
end
|
92
|
+
image.tag repo: @name
|
93
|
+
image
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def build_parent_image_if_available
|
98
|
+
dockerfile = IO.read "#{@directory}/Dockerfile"
|
99
|
+
from, image_name = dockerfile.each_line.first.split ' '
|
100
|
+
fail from unless from == 'FROM'
|
101
|
+
|
102
|
+
if image = self.class[image_name]
|
103
|
+
unless image.exist?
|
104
|
+
puts "Building parent image #{image.name}."
|
105
|
+
image.build
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class Network
|
112
|
+
def initialize name = 'common'
|
113
|
+
@network = prepare_network_with_name name
|
114
|
+
end
|
115
|
+
|
116
|
+
def internal_network
|
117
|
+
@network
|
118
|
+
end
|
119
|
+
|
120
|
+
extend Forwardable
|
121
|
+
delegate [:id, :connect] => :internal_network
|
122
|
+
|
123
|
+
def name
|
124
|
+
@network.info['Name']
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
def prepare_network_with_name name
|
129
|
+
Docker::Network.get name
|
130
|
+
rescue Docker::Error::NotFoundError
|
131
|
+
Docker::Network.create name
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Project
|
136
|
+
def initialize directory: '.', docker_socket: 'tcp://127.0.0.1:2375'
|
137
|
+
check_if_docker_is_available_at docker_socket
|
138
|
+
|
139
|
+
@directory = File.expand_path directory
|
140
|
+
@images_directory = "#{@directory}/.docker/images"
|
141
|
+
@services_file = "#{@directory}/.docker/services.yml"
|
142
|
+
end
|
143
|
+
|
144
|
+
attr_reader :containers
|
145
|
+
|
146
|
+
def run
|
147
|
+
prepare_images
|
148
|
+
prepare_services
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
def check_if_docker_is_available_at docker_socket
|
153
|
+
Docker.url = docker_socket
|
154
|
+
Docker.version
|
155
|
+
#rescue Excon::Error::Socket
|
156
|
+
end
|
157
|
+
|
158
|
+
def prepare_images
|
159
|
+
if Dir.exist? @images_directory
|
160
|
+
images = (Dir.entries(@images_directory) - ['.', '..']).map do |name|
|
161
|
+
Image.new name, directory: "#{@images_directory}/#{name}"
|
162
|
+
end
|
163
|
+
|
164
|
+
images.each do |image|
|
165
|
+
image.build unless image.exist?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def prepare_services
|
171
|
+
if File.exist? @services_file
|
172
|
+
hash = YAML.load_file @services_file
|
173
|
+
|
174
|
+
images = hash.keys.map do |name|
|
175
|
+
Image.new name, directory: "#{@directory}/#{name}"
|
176
|
+
end
|
177
|
+
|
178
|
+
images.each do |image|
|
179
|
+
image.build unless image.exist?
|
180
|
+
end
|
181
|
+
|
182
|
+
@containers = hash.map do |name, value|
|
183
|
+
ports = if value.is_a?(Hash) && value['ports'].is_a?(Array)
|
184
|
+
value['ports']
|
185
|
+
else
|
186
|
+
[]
|
187
|
+
end
|
188
|
+
|
189
|
+
Container.new name, ports: ports
|
190
|
+
end
|
191
|
+
|
192
|
+
network = Network.new
|
193
|
+
@containers.each { |container| network.connect container.id }
|
194
|
+
|
195
|
+
@containers.each &:start
|
196
|
+
at_exit { @containers.each &:destroy }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anatoly Chernow
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: docker-api
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
executables:
|
30
|
+
- dc
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- bin/dc
|
35
|
+
- lib/dc.rb
|
36
|
+
homepage:
|
37
|
+
licenses: []
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.7.6
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Manage projects with Docker conveniently.
|
59
|
+
test_files: []
|