docker-rails 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -5
- data/lib/docker/rails/app.rb +45 -12
- data/lib/docker/rails/cli/main.rb +12 -21
- data/lib/docker/rails/ext/container.rb +27 -6
- data/lib/docker/rails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec5c1185350ab97e62cf01109148ddf3423d1610
|
4
|
+
data.tar.gz: d0e552e9dba679b392c90ec2bc567332d0b79bcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1da0e5553d88912677d1e7108a3804a014d68ff6d6958c181e18490465323b6bb74ad5cac06754c093972446c52cf9c554a56f372877c4bedaf10fea4e52e8b5
|
7
|
+
data.tar.gz: d9288310748ee68a9477aa009cba469f808bb1d27cd181bb7177574219a71b48d7630d786268d5e1396a73fd835ef5c15f74402191cae8e76769a452861a6b43
|
data/README.md
CHANGED
@@ -12,6 +12,7 @@ A simplified pattern to execute rails applications within Docker (with a CI buil
|
|
12
12
|
- Automated cached global gems data volume based on ruby version
|
13
13
|
- Interpolates variables `docker-compose.yml` making CI builds much easier
|
14
14
|
- DB check CLI function provided for docker-compose `command` to check if db is ready
|
15
|
+
- Configurable exit_code for `ci` - determine which container's exit code will be the result of the process (useful for CI tests)
|
15
16
|
|
16
17
|
## Usage
|
17
18
|
|
@@ -19,7 +20,7 @@ A simplified pattern to execute rails applications within Docker (with a CI buil
|
|
19
20
|
|
20
21
|
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
|
|
22
|
-
`
|
23
|
+
`docker-rails ci test`
|
23
24
|
|
24
25
|
#### CI workflow
|
25
26
|
|
@@ -39,20 +40,30 @@ CI, the reason this is built. Do it all, do it consistently, do it concurrently,
|
|
39
40
|
|
40
41
|
#### CI execution options
|
41
42
|
|
43
|
+
**NOTE:** If using `bundle exec`, you'll need to do a `bundle` on both the host and container. These examples avoid `bundle exec` on the host for that reason (ran inside rvm).
|
44
|
+
|
45
|
+
In your environment, ensure that `docker-rails` is present:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
gem install --no-ri --no-rdoc docker-rails
|
49
|
+
```
|
50
|
+
|
51
|
+
Then run it:
|
52
|
+
|
42
53
|
```bash
|
43
|
-
|
54
|
+
docker-rails ci --build=222 test
|
44
55
|
```
|
45
56
|
|
46
57
|
or with the environment variable option
|
47
58
|
|
48
59
|
```bash
|
49
|
-
DOCKER_RAILS_BUILD=222
|
60
|
+
DOCKER_RAILS_BUILD=222 docker-rails ci test
|
50
61
|
```
|
51
62
|
|
52
63
|
or for local testing (uses `1` for build)
|
53
64
|
|
54
65
|
```bash
|
55
|
-
|
66
|
+
docker-rails ci test
|
56
67
|
```
|
57
68
|
|
58
69
|
### General CLI
|
@@ -86,7 +97,6 @@ Options:
|
|
86
97
|
Open to pull requests. Open to refactoring. It can be expanded to suit many different configurations.
|
87
98
|
|
88
99
|
TODO:
|
89
|
-
- **Permissions** - [Shared volume for project has files written as root](https://github.com/alienfast/docker-rails/issues/5)
|
90
100
|
- **DB versatility** - expand to different db status detection as-needed e.g. postgres. CLI is now modularized to allow for this.
|
91
101
|
|
92
102
|
|
@@ -142,6 +152,7 @@ The rails engine example below shows an example with all of the environments `de
|
|
142
152
|
|
143
153
|
```yaml
|
144
154
|
verbose: true
|
155
|
+
exit_code: web
|
145
156
|
before_command: bash -c "rm -Rf target && rm -Rf spec/dummy/log"
|
146
157
|
|
147
158
|
extractions: &extractions
|
data/lib/docker/rails/app.rb
CHANGED
@@ -3,7 +3,15 @@ module Docker
|
|
3
3
|
require 'singleton'
|
4
4
|
class App
|
5
5
|
include Singleton
|
6
|
-
attr_reader :config,
|
6
|
+
attr_reader :config,
|
7
|
+
:compose_config,
|
8
|
+
:ruby_version,
|
9
|
+
:build,
|
10
|
+
:target,
|
11
|
+
:gems_volume_path,
|
12
|
+
:gems_volume_name,
|
13
|
+
:compose_filename,
|
14
|
+
:exit_code
|
7
15
|
|
8
16
|
class << self
|
9
17
|
def configured(target, options)
|
@@ -95,6 +103,13 @@ module Docker
|
|
95
103
|
|
96
104
|
@compose_config = Docker::Rails::ComposeConfig.new
|
97
105
|
@compose_config.load!(nil, @compose_filename)
|
106
|
+
|
107
|
+
# check the exit_code
|
108
|
+
if @config['exit_code'].nil?
|
109
|
+
first_defined_service = @compose_config.keys[0]
|
110
|
+
puts "exit_code not set in configuration, using exit code from first defined service: #{first_defined_service}"
|
111
|
+
@config['exit_code'] = first_defined_service
|
112
|
+
end
|
98
113
|
end
|
99
114
|
|
100
115
|
def rm_compose
|
@@ -102,46 +117,64 @@ module Docker
|
|
102
117
|
exec "rm #{compose_filename_from '*', '*'}" rescue ''
|
103
118
|
end
|
104
119
|
|
105
|
-
def
|
120
|
+
def before_command
|
106
121
|
before_command = @config['before_command']
|
107
122
|
(exec before_command unless before_command.nil?) #unless skip? :before_command
|
108
123
|
end
|
109
124
|
|
110
|
-
def
|
125
|
+
def up(options = '')
|
111
126
|
# Run the compose configuration
|
112
127
|
exec_compose 'up', false, options #unless skip? :up
|
113
128
|
end
|
114
129
|
|
115
|
-
def
|
130
|
+
def build
|
116
131
|
# Run the compose configuration
|
117
132
|
exec_compose 'build'
|
118
133
|
end
|
119
134
|
|
120
|
-
def
|
135
|
+
def ps
|
121
136
|
# Run the compose configuration
|
122
137
|
exec_compose 'ps'
|
123
138
|
end
|
124
139
|
|
125
|
-
def
|
140
|
+
def ps_all
|
126
141
|
puts "\n\nAll remaining containers..."
|
127
142
|
puts '-----------------------------'
|
128
143
|
exec 'docker ps -a'
|
129
144
|
end
|
130
145
|
|
131
|
-
def
|
146
|
+
def stop
|
132
147
|
puts "\n\n\n\nStopping containers..."
|
133
148
|
puts '-----------------------------'
|
134
149
|
containers = Docker::Container.all(all: true)
|
135
150
|
containers.each do |container|
|
136
151
|
if is_build_container?(container)
|
137
|
-
|
152
|
+
printf "#{container.name}.."
|
138
153
|
container.stop
|
154
|
+
60.times do |i|
|
155
|
+
printf '.'
|
156
|
+
if container.down?
|
157
|
+
printf "done.\n"
|
158
|
+
break
|
159
|
+
end
|
160
|
+
sleep 1
|
161
|
+
end
|
162
|
+
|
163
|
+
service_name = container.compose.service
|
164
|
+
if @config['exit_code'].eql?(service_name)
|
165
|
+
if container.up?
|
166
|
+
puts "Unable to determine exit code, the #{service_name} is still up, current status: #{container.status}"
|
167
|
+
@exit_code = -999
|
168
|
+
else
|
169
|
+
@exit_code = container.exit_code
|
170
|
+
end
|
171
|
+
end
|
139
172
|
end
|
140
173
|
end
|
141
174
|
puts 'Done.'
|
142
175
|
end
|
143
176
|
|
144
|
-
def
|
177
|
+
def rm_volumes
|
145
178
|
puts "\n\nRemoving container volumes..."
|
146
179
|
puts '-----------------------------'
|
147
180
|
|
@@ -149,7 +182,7 @@ module Docker
|
|
149
182
|
containers = Docker::Container.all(all: true)
|
150
183
|
containers.each do |container|
|
151
184
|
if is_build_container?(container)
|
152
|
-
puts container.
|
185
|
+
puts container.name
|
153
186
|
container.remove(v: true, force: true)
|
154
187
|
end
|
155
188
|
end
|
@@ -166,12 +199,12 @@ module Docker
|
|
166
199
|
puts 'Done.'
|
167
200
|
end
|
168
201
|
|
169
|
-
def
|
202
|
+
def run_service_command(service_name, command)
|
170
203
|
# Run the compose configuration
|
171
204
|
exec_compose "run #{service_name} #{command}"
|
172
205
|
end
|
173
206
|
|
174
|
-
def
|
207
|
+
def bash_connect(service_name)
|
175
208
|
# docker exec -it 2ed97d0bb938 bash
|
176
209
|
container = get_container(service_name)
|
177
210
|
if container.nil?
|
@@ -22,7 +22,7 @@ module Docker
|
|
22
22
|
|
23
23
|
def ci(target)
|
24
24
|
# init singleton with full options
|
25
|
-
App.configured(target, options)
|
25
|
+
app = App.configured(target, options)
|
26
26
|
|
27
27
|
invoke :before, [target], []
|
28
28
|
invoke :compose, [target], []
|
@@ -33,6 +33,8 @@ module Docker
|
|
33
33
|
ensure
|
34
34
|
invoke :cleanup
|
35
35
|
end
|
36
|
+
|
37
|
+
exit app.exit_code
|
36
38
|
end
|
37
39
|
|
38
40
|
desc 'extract <target>', 'Invoke extractions', hide: true
|
@@ -69,17 +71,16 @@ module Docker
|
|
69
71
|
compose_options = ''
|
70
72
|
compose_options = '-d' if options[:detached]
|
71
73
|
|
72
|
-
app.
|
74
|
+
app.up(compose_options)
|
73
75
|
end
|
74
76
|
|
75
77
|
desc 'build <target>', 'Build for the given build/target e.g. bundle exec docker-rails build --build=222 development'
|
76
78
|
|
77
79
|
def build(target)
|
78
80
|
invoke :compose
|
79
|
-
App.configured(target, options).
|
81
|
+
App.configured(target, options).build
|
80
82
|
end
|
81
83
|
|
82
|
-
|
83
84
|
desc 'compose <target>', 'Writes a resolved docker-compose.yml file e.g. bundle exec docker-rails compose --build=222 test'
|
84
85
|
|
85
86
|
def compose(target)
|
@@ -91,22 +92,21 @@ module Docker
|
|
91
92
|
def before(target)
|
92
93
|
app = App.configured(target, options)
|
93
94
|
invoke :compose, [target], []
|
94
|
-
app.
|
95
|
+
app.before_command
|
95
96
|
end
|
96
97
|
|
97
|
-
|
98
98
|
desc 'stop <target>', 'Stop all running containers for the given build/target e.g. bundle exec docker-rails stop --build=222 development'
|
99
99
|
|
100
100
|
def stop(target)
|
101
101
|
invoke :compose
|
102
|
-
App.configured(target, options).
|
102
|
+
App.configured(target, options).stop
|
103
103
|
end
|
104
104
|
|
105
105
|
desc 'rm_volumes <target>', 'Stop all running containers and remove corresponding volumes for the given build/target e.g. bundle exec docker-rails rm_volumes --build=222 development'
|
106
106
|
|
107
107
|
def rm_volumes(target)
|
108
108
|
invoke :stop
|
109
|
-
App.configured(target, options).
|
109
|
+
App.configured(target, options).rm_volumes
|
110
110
|
end
|
111
111
|
|
112
112
|
desc 'rm_compose', 'Remove generated docker_compose file e.g. bundle exec docker-rails rm_compose --build=222 development', hide: true
|
@@ -125,13 +125,13 @@ module Docker
|
|
125
125
|
|
126
126
|
def ps(target)
|
127
127
|
invoke :compose
|
128
|
-
App.configured(target, options).
|
128
|
+
App.configured(target, options).ps
|
129
129
|
end
|
130
130
|
|
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.ps_all
|
135
135
|
end
|
136
136
|
|
137
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'
|
@@ -142,7 +142,7 @@ module Docker
|
|
142
142
|
|
143
143
|
invoke :compose, [target], []
|
144
144
|
|
145
|
-
container = app.
|
145
|
+
container = app.bash_connect(service_name)
|
146
146
|
|
147
147
|
# Automatically cleanup any remnants of a simple bash session.
|
148
148
|
return if container.nil?
|
@@ -150,7 +150,6 @@ module Docker
|
|
150
150
|
container.remove(v: true, force: true)
|
151
151
|
end
|
152
152
|
|
153
|
-
|
154
153
|
desc 'exec <target> <service_name> <command>', 'Run an arbitrary command on a given service container e.g. bundle exec docker-rails exec --build=222 development db bash'
|
155
154
|
|
156
155
|
def exec(target, service_name, command)
|
@@ -159,16 +158,8 @@ module Docker
|
|
159
158
|
|
160
159
|
invoke :compose, [target], []
|
161
160
|
|
162
|
-
app.
|
161
|
+
app.run_service_command(service_name, command)
|
163
162
|
end
|
164
|
-
|
165
|
-
|
166
|
-
protected
|
167
|
-
|
168
|
-
# invoke with an empty set of options
|
169
|
-
# def invoke_new(command, options=[])
|
170
|
-
# invoke command, nil, options
|
171
|
-
# end
|
172
163
|
end
|
173
164
|
end
|
174
165
|
end
|
@@ -1,12 +1,38 @@
|
|
1
1
|
class Docker::Container
|
2
2
|
|
3
|
+
def name
|
4
|
+
info['Names'][0].gsub(/^\//, '')
|
5
|
+
end
|
6
|
+
|
7
|
+
def status
|
8
|
+
info['Status']
|
9
|
+
end
|
10
|
+
|
11
|
+
def up?
|
12
|
+
status =~ /^(up|Up)/
|
13
|
+
end
|
14
|
+
|
15
|
+
def down?
|
16
|
+
!up?
|
17
|
+
end
|
18
|
+
|
19
|
+
def exit_code
|
20
|
+
return nil if up?
|
21
|
+
return nil unless (status =~ /xited/)
|
22
|
+
|
23
|
+
# Up 10 seconds
|
24
|
+
# Exited (0) 2 seconds ago
|
25
|
+
status =~ /^.* \((\w+)\)/
|
26
|
+
$1.to_i
|
27
|
+
end
|
28
|
+
|
3
29
|
def compose
|
4
30
|
return nil unless Compose.is_compose_container?(self)
|
5
31
|
@_compose ||= Compose.new(self)
|
6
32
|
end
|
7
33
|
|
8
34
|
class Compose
|
9
|
-
attr_reader :number, :oneoff, :project, :service, :version
|
35
|
+
attr_reader :number, :oneoff, :project, :service, :version
|
10
36
|
|
11
37
|
def initialize(container)
|
12
38
|
labels = container.info['Labels']
|
@@ -15,11 +41,6 @@ class Docker::Container
|
|
15
41
|
@oneoff = !!labels['com.docker.compose.oneoff']
|
16
42
|
@number = labels['com.docker.compose.container-number'].to_i
|
17
43
|
@version = labels['com.docker.compose.version']
|
18
|
-
@name = container.info['Names'][0].gsub(/^\//, '')
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
@name
|
23
44
|
end
|
24
45
|
|
25
46
|
class << self
|
data/lib/docker/rails/version.rb
CHANGED