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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 201c27258faf2fd7c7e3da8be4ef103692af5d3d
4
- data.tar.gz: 2cddc4422dd2fbde906a8b3eebeae4fe5659b4f8
3
+ metadata.gz: 285dc77cef10695d9e17976de3d0d4ce48191422
4
+ data.tar.gz: f8e2eca7b132eb6b97dced3fe8a04b64512d5dd8
5
5
  SHA512:
6
- metadata.gz: 10b164b7176bc7bc04fbf1aafe8700c108bc5916be22ee49ff961d253cadc39be6b6ae5f755dde04f6bbd469c694a9cccb9f535ba71cbbcd7800d36a0b7b2660
7
- data.tar.gz: fcaf8df78943d829d525c630d71517c28bf47d681d85d65ea6401d9b470ae0d2568979c1a13eb1c9b6728109055b71af27c4583bd9b8f8a45bb5e9ac04c08096
6
+ metadata.gz: 8ab35a4c1b39129157b8962f383e02eb4004a37c798c2512aa49ad993e97f39e7fb5229a7b5901175a767b057d5d2ab38fbd20ba385534530cde0df53cb25a3a
7
+ data.tar.gz: a9f88b10b75cdf755de564ed85479d6eee098ec522d98415fdc4211e23b57c092d83fb299fdd2dd697c8cfd6af5c4a41a980d5c3ef1b0f1bd0f0e2059935aed5
data/.travis.yml CHANGED
@@ -10,4 +10,9 @@ matrix:
10
10
  - rvm: ruby-head
11
11
  - rvm: jruby-head
12
12
 
13
- script: rake
13
+ script: rake
14
+
15
+ notifications:
16
+ email:
17
+ on_success: change
18
+ on_failure: change
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/core_ext/hash'
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'
@@ -76,36 +76,15 @@ module Docker
76
76
  end
77
77
 
78
78
  puts "\nExtracting #{service_name} #{from} to #{to}"
79
- extract_files(container, from, to)
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
- @compose_config.each_key do |service_name|
150
- stop(service_name)
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
- @compose_config.each_key do |service_name|
159
- rm_v(service_name)
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 222_db_1 bash
187
- container_name = get_container_name(service_name)
188
- exec "docker exec -it #{container_name} bash"
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.get(get_container_name(service_name))
233
- end
234
-
235
- # def up_service(service_name, options = '')
236
- # exec_compose "up #{options} #{service_name}"
237
- # container_name = get_container_name(service_name)
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
- def stop(service_name)
252
- exec_compose "stop #{service_name}"
226
+ nil
253
227
  end
254
228
 
255
- # def skip?(command)
256
- # skips = @config[:skip]
257
- # return false if skips.nil?
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.show_all_containers
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
@@ -1,5 +1,5 @@
1
1
  module Docker
2
2
  module Rails
3
- VERSION = '0.4.1'
3
+ VERSION = '0.5.0'
4
4
  end
5
5
  end
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.1
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-28 00:00:00.000000000 Z
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/core_ext/hash.rb
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