docker-rails 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -1
- data/README.md +28 -2
- data/lib/docker/rails.rb +2 -1
- data/lib/docker/rails/app.rb +72 -74
- data/lib/docker/rails/cli/main.rb +8 -3
- data/lib/docker/rails/ext/container.rb +33 -0
- data/lib/docker/rails/{core_ext → ext}/hash.rb +0 -0
- data/lib/docker/rails/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 285dc77cef10695d9e17976de3d0d4ce48191422
|
4
|
+
data.tar.gz: f8e2eca7b132eb6b97dced3fe8a04b64512d5dd8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ab35a4c1b39129157b8962f383e02eb4004a37c798c2512aa49ad993e97f39e7fb5229a7b5901175a767b057d5d2ab38fbd20ba385534530cde0df53cb25a3a
|
7
|
+
data.tar.gz: a9f88b10b75cdf755de564ed85479d6eee098ec522d98415fdc4211e23b57c092d83fb299fdd2dd697c8cfd6af5c4a41a980d5c3ef1b0f1bd0f0e2059935aed5
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -18,6 +18,26 @@ A simplified pattern to execute rails applications within Docker (with a CI buil
|
|
18
18
|
### CI
|
19
19
|
|
20
20
|
CI, the reason this is built. Do it all, do it consistently, do it concurrently, do it easily, and always cleanup after yourself.
|
21
|
+
|
22
|
+
`bundle exec ci test`
|
23
|
+
|
24
|
+
#### CI workflow
|
25
|
+
|
26
|
+
`ci` executes:
|
27
|
+
|
28
|
+
1. `before_command` - run anything on the host prior to building the docker image e.g. `rm -Rf target`
|
29
|
+
2. `compose` - create the resolved `docker-compose.yml`
|
30
|
+
3. `gems_volume` - find or create the shared global gems volume for this ruby version
|
31
|
+
4. `build` - `docker-compose build` the configuration
|
32
|
+
5. `up` - `docker-compose up` the configuration
|
33
|
+
6. `cleanup`
|
34
|
+
1. `stop` - stop all containers for this configuration (including one-off sessions)
|
35
|
+
2. `extract` - extract any defined files from any container
|
36
|
+
3. `rm_volumes` - `docker-compose rm -v --force` to cleanup any container volumes (excluding the gems volume)
|
37
|
+
4. `rm_compose` - cleanup the generated compose.yml file for the `build`
|
38
|
+
5. `rm_dangling` - cleanup any dangling images
|
39
|
+
|
40
|
+
#### CI execution options
|
21
41
|
|
22
42
|
```bash
|
23
43
|
bundle exec docker-rails ci --build=222 test
|
@@ -33,7 +53,7 @@ or for local testing (uses `1` for build)
|
|
33
53
|
|
34
54
|
```bash
|
35
55
|
bundle exec docker-rails ci test
|
36
|
-
|
56
|
+
```
|
37
57
|
|
38
58
|
### General CLI
|
39
59
|
|
@@ -41,7 +61,7 @@ Almost all of the commands below are in support of the `ci` command, so why not
|
|
41
61
|
|
42
62
|
```bash
|
43
63
|
Commands:
|
44
|
-
docker-rails bash_connect <target> <service_name> # Open a bash shell to a running container e.g. bundle exec docker-rails bash --build=222 development db
|
64
|
+
docker-rails bash_connect <target> <service_name> # Open a bash shell to a running container (with automatic cleanup) e.g. bundle exec docker-rails bash --build=222 development db
|
45
65
|
docker-rails build <target> # Build for the given build/target e.g. bundle exec docker-rails build --build=222 development
|
46
66
|
docker-rails ci <target> # Execute the works, everything with cleanup included e.g. bundle exec docker-rails ci --build=222 test
|
47
67
|
docker-rails cleanup <target> # Runs container cleanup functions stop, rm_volumes, rm_compose, rm_dangling, ps_all e.g. bundle exec docker-rails cleanup --build=222 development
|
@@ -107,6 +127,12 @@ RUN apt-get update -qq && \
|
|
107
127
|
|
108
128
|
# https://github.com/docker/docker/issues/4032
|
109
129
|
ENV DEBIAN_FRONTEND newt
|
130
|
+
|
131
|
+
# Bypass the union file system for better performance https://docs.docker.com/userguide/dockervolumes/
|
132
|
+
VOLUME /project
|
133
|
+
|
134
|
+
# Copy the project files into the container (again, better performance). Use `extract` in the docker-rails.yml to obtain files such as test results.
|
135
|
+
COPY . /project
|
110
136
|
```
|
111
137
|
|
112
138
|
### 2. Add a docker-rails.yml
|
data/lib/docker/rails.rb
CHANGED
@@ -9,7 +9,8 @@ require 'thor'
|
|
9
9
|
require 'docker'
|
10
10
|
require 'archive/tar/minitar'
|
11
11
|
|
12
|
-
require 'docker/rails/
|
12
|
+
require 'docker/rails/ext/hash'
|
13
|
+
require 'docker/rails/ext/container'
|
13
14
|
|
14
15
|
require 'docker/rails/config'
|
15
16
|
require 'docker/rails/compose_config'
|
data/lib/docker/rails/app.rb
CHANGED
@@ -76,36 +76,15 @@ module Docker
|
|
76
76
|
end
|
77
77
|
|
78
78
|
puts "\nExtracting #{service_name} #{from} to #{to}"
|
79
|
-
|
79
|
+
begin
|
80
|
+
extract_files(container, from, to)
|
81
|
+
rescue => e
|
82
|
+
puts e.message
|
83
|
+
end
|
80
84
|
end
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
84
|
-
|
85
|
-
def extract_files(container, from, to)
|
86
|
-
# or something like
|
87
|
-
tar_stringio = StringIO.new
|
88
|
-
container.copy(from) do |chunk|
|
89
|
-
tar_stringio.write(chunk)
|
90
|
-
end
|
91
|
-
|
92
|
-
tar_stringio.rewind
|
93
|
-
|
94
|
-
input = Archive::Tar::Minitar::Input.new(tar_stringio)
|
95
|
-
input.each { |entry|
|
96
|
-
|
97
|
-
# Need to check the file name length to prevent some very bad things from happening.
|
98
|
-
if entry.full_name.length > 255
|
99
|
-
puts "ERROR - file name length is > 255 characters: #{entry.full_name}"
|
100
|
-
elsif entry.full_name.length <= 0
|
101
|
-
puts "ERROR - file name length is too small: #{entry.full_name}"
|
102
|
-
else
|
103
|
-
puts "Extracting #{entry.full_name}"
|
104
|
-
input.extract_entry(to, entry)
|
105
|
-
end
|
106
|
-
}
|
107
|
-
end
|
108
|
-
|
109
88
|
def compose
|
110
89
|
# Write a docker-compose.yml with interpolated variables
|
111
90
|
@compose_filename = compose_filename_from @build, @target
|
@@ -143,11 +122,21 @@ module Docker
|
|
143
122
|
exec_compose 'ps'
|
144
123
|
end
|
145
124
|
|
125
|
+
def exec_ps_all
|
126
|
+
puts "\n\nAll remaining containers..."
|
127
|
+
puts '-----------------------------'
|
128
|
+
exec 'docker ps -a'
|
129
|
+
end
|
130
|
+
|
146
131
|
def exec_stop
|
147
132
|
puts "\n\n\n\nStopping containers..."
|
148
133
|
puts '-----------------------------'
|
149
|
-
|
150
|
-
|
134
|
+
containers = Docker::Container.all(all: true)
|
135
|
+
containers.each do |container|
|
136
|
+
if is_build_container?(container)
|
137
|
+
puts container.compose
|
138
|
+
container.stop
|
139
|
+
end
|
151
140
|
end
|
152
141
|
puts 'Done.'
|
153
142
|
end
|
@@ -155,8 +144,14 @@ module Docker
|
|
155
144
|
def exec_remove_volumes
|
156
145
|
puts "\n\nRemoving container volumes..."
|
157
146
|
puts '-----------------------------'
|
158
|
-
|
159
|
-
|
147
|
+
|
148
|
+
# http://docs.docker.com/v1.7/reference/api/docker_remote_api_v1.19/#remove-a-container
|
149
|
+
containers = Docker::Container.all(all: true)
|
150
|
+
containers.each do |container|
|
151
|
+
if is_build_container?(container)
|
152
|
+
puts container.compose
|
153
|
+
container.remove(v: true, force: true)
|
154
|
+
end
|
160
155
|
end
|
161
156
|
puts 'Done.'
|
162
157
|
end
|
@@ -171,21 +166,21 @@ module Docker
|
|
171
166
|
puts 'Done.'
|
172
167
|
end
|
173
168
|
|
174
|
-
def show_all_containers
|
175
|
-
puts "\n\nAll remaining containers..."
|
176
|
-
puts '-----------------------------'
|
177
|
-
system 'docker ps -a'
|
178
|
-
end
|
179
|
-
|
180
169
|
def exec_run(service_name, command)
|
181
170
|
# Run the compose configuration
|
182
171
|
exec_compose "run #{service_name} #{command}"
|
183
172
|
end
|
184
173
|
|
185
174
|
def exec_bash_connect(service_name)
|
186
|
-
# docker exec -it
|
187
|
-
|
188
|
-
|
175
|
+
# docker exec -it 2ed97d0bb938 bash
|
176
|
+
container = get_container(service_name)
|
177
|
+
if container.nil?
|
178
|
+
puts "#{service_name} does not appear to be running for build #{@build}"
|
179
|
+
return
|
180
|
+
end
|
181
|
+
|
182
|
+
exec "docker exec -it #{container.id} bash"
|
183
|
+
container
|
189
184
|
end
|
190
185
|
|
191
186
|
# Create global gems data volume to cache gems for this version of ruby
|
@@ -220,46 +215,25 @@ module Docker
|
|
220
215
|
exec("docker-compose -f #{@compose_filename} -p #{@build} #{cmd} #{options}", capture)
|
221
216
|
end
|
222
217
|
|
223
|
-
# service_name i.e. 'db' or 'web'
|
224
|
-
def get_container_name(service_name)
|
225
|
-
output = exec_compose "ps #{service_name}", true
|
226
|
-
# puts "get_container(#{service_name}): \n#{output}"
|
227
|
-
output =~ /^(\w+)/ # grab the name, only thing that is at the start of the line
|
228
|
-
$1
|
229
|
-
end
|
230
|
-
|
231
218
|
def get_container(service_name)
|
232
|
-
Docker::Container.
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
# puts "#{service_name}: container_name #{container_name}"
|
239
|
-
#
|
240
|
-
# container = Docker::Container.get(container_name)
|
241
|
-
# # container.streaming_logs(stdout: true) { |stream, chunk| puts "#{service_name}: #{chunk}" }
|
242
|
-
# # puts container
|
243
|
-
#
|
244
|
-
# {service_name => {'container' => container, 'container_name' => container_name}}
|
245
|
-
# end
|
246
|
-
|
247
|
-
def rm_v(service_name)
|
248
|
-
exec_compose "rm -v --force #{service_name}"
|
249
|
-
end
|
219
|
+
containers = Docker::Container.all(all: true)
|
220
|
+
containers.each do |container|
|
221
|
+
if is_build_container?(container) && container.compose.service.eql?(service_name)
|
222
|
+
return container
|
223
|
+
end
|
224
|
+
end
|
250
225
|
|
251
|
-
|
252
|
-
exec_compose "stop #{service_name}"
|
226
|
+
nil
|
253
227
|
end
|
254
228
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
# skip = skips.include? command.to_s
|
259
|
-
# puts "Skipping #{command}" if skip && verbose?
|
260
|
-
# skip
|
261
|
-
# end
|
229
|
+
def is_build_container?(container)
|
230
|
+
# labels = container.info['Labels']
|
231
|
+
# build = labels['com.docker.compose.project']
|
262
232
|
|
233
|
+
return false if container.compose.nil?
|
234
|
+
return true if @build.eql? container.compose.project
|
235
|
+
false
|
236
|
+
end
|
263
237
|
|
264
238
|
def verbose?
|
265
239
|
@verbose ||= (@config['verbose'] unless @config.nil?) || false
|
@@ -281,6 +255,30 @@ module Docker
|
|
281
255
|
def compose_filename_from(build, target)
|
282
256
|
"docker-compose-#{target}-#{build}.yml"
|
283
257
|
end
|
258
|
+
|
259
|
+
def extract_files(container, from, to)
|
260
|
+
# or something like
|
261
|
+
tar_stringio = StringIO.new
|
262
|
+
container.copy(from) do |chunk|
|
263
|
+
tar_stringio.write(chunk)
|
264
|
+
end
|
265
|
+
|
266
|
+
tar_stringio.rewind
|
267
|
+
|
268
|
+
input = Archive::Tar::Minitar::Input.new(tar_stringio)
|
269
|
+
input.each { |entry|
|
270
|
+
|
271
|
+
# Need to check the file name length to prevent some very bad things from happening.
|
272
|
+
if entry.full_name.length > 255
|
273
|
+
puts "ERROR - file name length is > 255 characters: #{entry.full_name}"
|
274
|
+
elsif entry.full_name.length <= 0
|
275
|
+
puts "ERROR - file name length is too small: #{entry.full_name}"
|
276
|
+
else
|
277
|
+
puts "Extracting #{entry.full_name}"
|
278
|
+
input.extract_entry(to, entry)
|
279
|
+
end
|
280
|
+
}
|
281
|
+
end
|
284
282
|
end
|
285
283
|
end
|
286
284
|
end
|
@@ -131,10 +131,10 @@ module Docker
|
|
131
131
|
desc 'ps_all', 'List all remaining containers regardless of state e.g. bundle exec docker-rails ps_all'
|
132
132
|
|
133
133
|
def ps_all(build = nil, target = nil)
|
134
|
-
App.instance.
|
134
|
+
App.instance.exec_ps_all
|
135
135
|
end
|
136
136
|
|
137
|
-
desc 'bash_connect <target> <service_name>', 'Open a bash shell to a running container e.g. bundle exec docker-rails bash --build=222 development db'
|
137
|
+
desc 'bash_connect <target> <service_name>', 'Open a bash shell to a running container (with automatic cleanup) e.g. bundle exec docker-rails bash --build=222 development db'
|
138
138
|
|
139
139
|
def bash_connect(target, service_name)
|
140
140
|
# init singleton with full options
|
@@ -142,7 +142,12 @@ module Docker
|
|
142
142
|
|
143
143
|
invoke :compose, [target], []
|
144
144
|
|
145
|
-
app.exec_bash_connect(service_name)
|
145
|
+
container = app.exec_bash_connect(service_name)
|
146
|
+
|
147
|
+
# Automatically cleanup any remnants of a simple bash session.
|
148
|
+
return if container.nil?
|
149
|
+
container.stop
|
150
|
+
container.remove(v: true, force: true)
|
146
151
|
end
|
147
152
|
|
148
153
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Docker::Container
|
2
|
+
|
3
|
+
def compose
|
4
|
+
return nil unless Compose.is_compose_container?(self)
|
5
|
+
@_compose ||= Compose.new(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
class Compose
|
9
|
+
attr_reader :number, :oneoff, :project, :service, :version, :name
|
10
|
+
|
11
|
+
def initialize(container)
|
12
|
+
labels = container.info['Labels']
|
13
|
+
@service = labels['com.docker.compose.service']
|
14
|
+
@project = labels['com.docker.compose.project']
|
15
|
+
@oneoff = !!labels['com.docker.compose.oneoff']
|
16
|
+
@number = labels['com.docker.compose.container-number'].to_i
|
17
|
+
@version = labels['com.docker.compose.version']
|
18
|
+
@name = container.info['Names'][0].gsub(/^\//, '')
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
@name
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def is_compose_container?(container)
|
27
|
+
labels = container.info['Labels']
|
28
|
+
(!labels.nil? && !labels['com.docker.compose.version'].nil?)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
File without changes
|
data/lib/docker/rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Ross
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -162,7 +162,8 @@ files:
|
|
162
162
|
- lib/docker/rails/cli/main.rb
|
163
163
|
- lib/docker/rails/compose_config.rb
|
164
164
|
- lib/docker/rails/config.rb
|
165
|
-
- lib/docker/rails/
|
165
|
+
- lib/docker/rails/ext/container.rb
|
166
|
+
- lib/docker/rails/ext/hash.rb
|
166
167
|
- lib/docker/rails/version.rb
|
167
168
|
- spec/docker/rails/config_spec.rb
|
168
169
|
- spec/docker/rails/docker-rails.yml
|