docker-rails 0.0.1 → 0.0.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 +48 -45
- data/bin/docker-rails +64 -73
- data/bin/docker-rails-db-check +38 -0
- data/docker-rails.gemspec +1 -0
- data/lib/docker/rails/compose_config.rb +1 -0
- data/lib/docker/rails/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6052b133ad5e1cdb58cb484baa077de133994fdc
|
4
|
+
data.tar.gz: 33124a13ab2327fbc1dfe2ae28fed2542f2656f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9fd4e6b3e13e76beb5f914b9944860101f3ccb7c36792de0de1525372396c719fbff75c4c65d6144b7d3075302c0bb0be2d118cf31ba70746168cc1c2007e19
|
7
|
+
data.tar.gz: 30f5cf9246f18910399c7eb937fdc90ed2816243b1386a0af47c68ced889258f1452a2ede03e731e55d2034aceeca4020d3bc92352bccbc41e822c29ac8e4b0c
|
data/README.md
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
-
#
|
1
|
+
# docker-rails
|
2
2
|
|
3
3
|
A simplified pattern to execute rails applications within Docker (with a CI build emphasis).
|
4
4
|
|
5
|
-
Features
|
5
|
+
## Features
|
6
6
|
- cached global bundler data volume (automatic) based on ruby version
|
7
7
|
- interpolates `docker-compose.yml` making CI builds much easier
|
8
|
-
- starts `db` container first
|
9
|
-
-
|
8
|
+
- starts `db` container first and continues with `web`
|
9
|
+
- function provided for docker-compose `command` to check if db is ready, currently executed as script `docker-rails-db-check`
|
10
|
+
- cleans up all containers **and** volumes once completed
|
10
11
|
|
11
12
|
|
12
|
-
|
13
|
+
## Work in progress - contributions welcome
|
13
14
|
Open to pull requests, while this starts off as one-person's environment, it can be expanded to suit many different configurations.
|
14
15
|
|
15
|
-
|
16
|
-
- remove hardcoded ip for db ip resolution
|
16
|
+
TODO:
|
17
17
|
- remove or default hardcoded BUILD_NAME
|
18
|
-
- expand to different db status detection as needed
|
18
|
+
- expand to different db status detection as needed e.g. postgres
|
19
|
+
- move to proper CLI (it's mostly in script form at the moment)
|
20
|
+
- (perhaps) provide name based compose configurations, i.e. running `docker-rails development` vs. `docker-rails test` vs. `docker-rails parallel_tests` might be nice to have (and easy) since most of the configuration is the same, sans `command`.
|
21
|
+
|
19
22
|
|
20
23
|
## Installation
|
21
24
|
|
@@ -43,8 +46,7 @@ ENV DEBIAN_FRONTEND noninteractive
|
|
43
46
|
# For building, nokogiri support, capybara-webkit, mysql client
|
44
47
|
# Clean up APT when done.
|
45
48
|
RUN apt-get update -qq && \
|
46
|
-
apt-get install -qy build-essential libxml2-dev libxslt1-dev \
|
47
|
-
g++ qt5-default libqt5webkit5-dev xvfb libmysqlclient-dev && \
|
49
|
+
apt-get install -qy build-essential libxml2-dev libxslt1-dev g++ qt5-default libqt5webkit5-dev xvfb libmysqlclient-dev && \
|
48
50
|
|
49
51
|
# cleanup
|
50
52
|
apt-get clean && \
|
@@ -56,7 +58,6 @@ ENV DEBIAN_FRONTEND newt
|
|
56
58
|
|
57
59
|
ADD . /project
|
58
60
|
WORKDIR /project
|
59
|
-
RUN ["chmod", "+x", "/project/scripts/*"]
|
60
61
|
```
|
61
62
|
|
62
63
|
### 2. Add a docker-compose.yml
|
@@ -66,8 +67,36 @@ Environment variables will be interpolated, so feel free to use them.
|
|
66
67
|
```yaml
|
67
68
|
web:
|
68
69
|
build: .
|
70
|
+
# e.g. engine dummy, otherwise omit.
|
69
71
|
working_dir: /project/spec/dummy
|
70
|
-
command:
|
72
|
+
command: >
|
73
|
+
bash -c
|
74
|
+
"
|
75
|
+
echo 'Bundling gems'
|
76
|
+
&& bundle install --jobs 4 --retry 3
|
77
|
+
|
78
|
+
&& echo 'Generating Spring binstubs'
|
79
|
+
&& bundle exec spring binstub --all
|
80
|
+
|
81
|
+
&& echo 'Clearing logs'
|
82
|
+
&& bin/rake log:clear
|
83
|
+
|
84
|
+
&& echo 'Check and wait for database connection'
|
85
|
+
&& bundle exec docker-rails-db-check
|
86
|
+
|
87
|
+
&& echo 'Setting up new db if one doesn't exist'
|
88
|
+
&& bin/rake db:version || { bundle exec rake db:setup; }
|
89
|
+
|
90
|
+
&& echo 'Removing contents of tmp dirs'
|
91
|
+
&& bin/rake tmp:clear
|
92
|
+
|
93
|
+
&& echo 'Starting app server'
|
94
|
+
&& bundle exec rails s -p 3000
|
95
|
+
|
96
|
+
&& echo 'Setup and start foreman'
|
97
|
+
&& gem install foreman
|
98
|
+
&& foreman start
|
99
|
+
"
|
71
100
|
ports:
|
72
101
|
- "3000:3000"
|
73
102
|
links:
|
@@ -83,6 +112,10 @@ web:
|
|
83
112
|
# Tell bundler where to get the files
|
84
113
|
- GEM_HOME=#{GEMS_VOLUME_PATH}
|
85
114
|
|
115
|
+
elasticsearch:
|
116
|
+
image: library/elasticsearch:1.7
|
117
|
+
ports:
|
118
|
+
- "9200:9200"
|
86
119
|
db:
|
87
120
|
image: library/mysql:5.7.6
|
88
121
|
ports:
|
@@ -91,43 +124,13 @@ db:
|
|
91
124
|
- MYSQL_ALLOW_EMPTY_PASSWORD=true
|
92
125
|
```
|
93
126
|
|
94
|
-
### 3.
|
95
|
-
|
96
|
-
TODO: verify a good sample
|
97
|
-
|
98
|
-
```bash
|
99
|
-
#!/usr/bin/env bash
|
100
|
-
|
101
|
-
echo "Bundling gems"
|
102
|
-
bundle install --jobs 4 --retry 3
|
103
|
-
|
104
|
-
echo "Generating Spring binstubs"
|
105
|
-
bundle exec spring binstub --all
|
106
|
-
|
107
|
-
echo "Clearing logs"
|
108
|
-
bin/rake log:clear
|
109
|
-
|
110
|
-
echo "Setting up new db if one doesn't exist"
|
111
|
-
bin/rake db:version || { bundle exec rake db:setup; }
|
112
|
-
|
113
|
-
echo "Removing contents of tmp dirs"
|
114
|
-
bin/rake tmp:clear
|
115
|
-
|
116
|
-
echo "Starting app server"
|
117
|
-
bundle exec rails s -p 3000
|
118
|
-
|
119
|
-
# or use foreman
|
120
|
-
# gem install foreman
|
121
|
-
# foreman start
|
122
|
-
```
|
123
|
-
|
124
|
-
### 4. Run it
|
127
|
+
### 3. Run it
|
125
128
|
|
126
129
|
`bundle exec docker-rails`
|
127
130
|
|
128
|
-
###
|
131
|
+
### 4. Submit pull requests!
|
129
132
|
|
130
|
-
This is starting off simple, but again, we welcome pulls to make this and the process of using docker for rails
|
133
|
+
This is starting off simple, but again, we welcome pulls to make this and the process of using docker for rails even easier.
|
131
134
|
|
132
135
|
|
133
136
|
## Contributing
|
data/bin/docker-rails
CHANGED
@@ -11,13 +11,19 @@
|
|
11
11
|
# https://docs.docker.com/reference/api/docker_remote_api_v1.20
|
12
12
|
|
13
13
|
|
14
|
+
# docker-compose -f docker-compose-build-119.yml -p 119 up -d db
|
15
|
+
# docker-compose -f docker-compose-build-119.yml -p 119 up web
|
16
|
+
|
17
|
+
|
18
|
+
SHOW_COMMANDS = true
|
19
|
+
|
14
20
|
# enable local usage from cloned repo
|
15
21
|
root = File.expand_path('../..', __FILE__)
|
16
22
|
$LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
|
17
23
|
|
18
24
|
require 'docker/rails'
|
19
25
|
|
20
|
-
BUILD_NAME = '
|
26
|
+
BUILD_NAME = '119' # temp should be passed in
|
21
27
|
ENV['BUILD_NAME'] = BUILD_NAME
|
22
28
|
|
23
29
|
# Discover ruby version from the Dockerfile image
|
@@ -30,6 +36,19 @@ GEMS_VOLUME_NAME = "gems-#{BUILD_RUBY_VERSION}"
|
|
30
36
|
ENV['GEMS_VOLUME_PATH'] = GEMS_VOLUME_PATH
|
31
37
|
ENV['GEMS_VOLUME_NAME'] = GEMS_VOLUME_NAME
|
32
38
|
|
39
|
+
|
40
|
+
def exec(cmd, capture = false)
|
41
|
+
puts "Running `#{cmd}`" if SHOW_COMMANDS
|
42
|
+
if capture
|
43
|
+
output = %x[#{cmd}]
|
44
|
+
else
|
45
|
+
system cmd
|
46
|
+
end
|
47
|
+
|
48
|
+
raise "Failed to execute: `#{cmd}`" unless $?.success?
|
49
|
+
output
|
50
|
+
end
|
51
|
+
|
33
52
|
# -----------
|
34
53
|
# Create global gems data volume to cache gems for this version of ruby
|
35
54
|
#
|
@@ -37,112 +56,84 @@ ENV['GEMS_VOLUME_NAME'] = GEMS_VOLUME_NAME
|
|
37
56
|
#
|
38
57
|
require 'docker'
|
39
58
|
begin
|
40
|
-
|
59
|
+
Docker::Container.get(GEMS_VOLUME_NAME)
|
41
60
|
puts "Gem data volume container #{GEMS_VOLUME_NAME} already exists."
|
42
61
|
rescue Docker::Error::NotFoundError => e
|
43
|
-
|
62
|
+
|
63
|
+
exec "docker create -v #{GEMS_VOLUME_PATH} --name #{GEMS_VOLUME_NAME} busybox"
|
44
64
|
puts "Gem data volume container #{GEMS_VOLUME_NAME} created."
|
45
65
|
end
|
46
|
-
gems_container.streaming_logs(stdout: true) { |stream, chunk| puts "#{GEMS_VOLUME_NAME}: #{chunk}" }
|
66
|
+
# gems_container.streaming_logs(stdout: true) { |stream, chunk| puts "#{GEMS_VOLUME_NAME}: #{chunk}" }
|
67
|
+
|
68
|
+
# Delete old docker compose files
|
69
|
+
exec 'rm docker-compose-build-*.yml' rescue ''
|
47
70
|
|
48
71
|
# Read docker-compose.yml and rewrite with interpolated variables and BUILD_NAME
|
49
72
|
COMPOSE_FILENAME = "docker-compose-build-#{BUILD_NAME}.yml"
|
50
73
|
compose_config = Docker::Rails::ComposeConfig.interpolate_file(COMPOSE_FILENAME)
|
51
74
|
|
52
75
|
# convenience to execute docker-compose with file and project params
|
53
|
-
def
|
54
|
-
|
55
|
-
puts "Running `#{cmd}`"
|
56
|
-
output =`#{cmd}`
|
57
|
-
result=$?.success?
|
58
|
-
output
|
76
|
+
def exec_compose(cmd, capture = false)
|
77
|
+
exec("docker-compose -f #{COMPOSE_FILENAME} -p #{BUILD_NAME} #{cmd}", capture)
|
59
78
|
end
|
60
79
|
|
61
80
|
# service_name i.e. 'db' or 'web'
|
62
81
|
def get_container_name(service_name)
|
63
|
-
output =
|
82
|
+
output = exec_compose "ps #{service_name}", true
|
83
|
+
# puts "get_container(#{service_name}): \n#{output}"
|
64
84
|
output =~ /^(\w+)/ # grab the name, only thing that is at the start of the line
|
65
85
|
$1
|
66
86
|
end
|
67
87
|
|
68
|
-
|
69
|
-
|
70
|
-
cmd = "docker inspect --format '{{ .NetworkSettings.IPAddress }}' #{container_name}"
|
71
|
-
puts "Running `#{cmd}`"
|
72
|
-
output = `#{cmd}`
|
73
|
-
result=$?.success?
|
74
|
-
output
|
75
|
-
end
|
76
|
-
|
77
|
-
def up_container(service_name, options = '')
|
78
|
-
xc "up #{options} #{service_name}"
|
88
|
+
def up(service_name, options = '')
|
89
|
+
exec_compose "up #{options} #{service_name}"
|
79
90
|
container_name = get_container_name(service_name)
|
80
91
|
puts "#{service_name}: container_name #{container_name}"
|
81
92
|
|
82
93
|
container = Docker::Container.get(container_name)
|
83
|
-
container.streaming_logs(stdout: true) { |stream, chunk| puts "#{service_name}: #{chunk}" }
|
94
|
+
# container.streaming_logs(stdout: true) { |stream, chunk| puts "#{service_name}: #{chunk}" }
|
84
95
|
# puts container
|
85
96
|
|
86
|
-
|
87
|
-
[container, container_name, ip_address]
|
97
|
+
[container, container_name]
|
88
98
|
end
|
89
99
|
|
90
|
-
def
|
91
|
-
|
92
|
-
container.stop
|
93
|
-
container.delete(force: true)
|
100
|
+
def rm_v(service_name)
|
101
|
+
exec_compose "rm -v --force #{service_name}"
|
94
102
|
end
|
95
103
|
|
96
|
-
|
97
|
-
|
104
|
+
def stop(service_name)
|
105
|
+
exec_compose "stop #{service_name}"
|
106
|
+
end
|
98
107
|
|
99
|
-
# ping db to see if it is ready before continuing
|
100
|
-
require 'rubygems'
|
101
|
-
require 'active_record'
|
102
108
|
|
103
|
-
|
104
|
-
|
105
|
-
LOOP_LIMIT.times do |i|
|
106
|
-
if i == LOOP_LIMIT - 1
|
107
|
-
puts 'Time out waiting for db to be up.'
|
108
|
-
#docker logs --follow=false $DB_CONTAINER
|
109
|
-
break
|
110
|
-
end
|
111
|
-
|
112
|
-
ActiveRecord::Base.establish_connection ({
|
113
|
-
adapter: 'mysql2',
|
114
|
-
# host: db_ip_address,
|
115
|
-
host: '192.168.99.100',
|
116
|
-
port: 3306,
|
117
|
-
username: 'root'})
|
118
|
-
# connected = ActiveRecord::Base.connection_pool.with_connection { |con| con.active? } rescue false
|
119
|
-
connected =
|
120
|
-
begin
|
121
|
-
ActiveRecord::Base.connection_pool.with_connection { |con| con.active? }
|
122
|
-
rescue => e
|
123
|
-
# puts "#{e.class.name}: #{e.message}"
|
124
|
-
false
|
125
|
-
end
|
126
|
-
printf '.'
|
127
|
-
if connected
|
128
|
-
printf 'connected.'
|
129
|
-
break
|
130
|
-
end
|
131
|
-
sleep 1
|
132
|
-
end
|
133
|
-
puts ''
|
109
|
+
# make sure we are built
|
110
|
+
exec_compose 'build'
|
134
111
|
|
112
|
+
begin
|
113
|
+
# Start the db container
|
114
|
+
up('db', '-d')
|
135
115
|
|
136
|
-
# Start the web
|
137
|
-
|
116
|
+
# Start the web container
|
117
|
+
up('web')
|
138
118
|
|
119
|
+
ensure
|
120
|
+
puts "\n\n\n\nStopping containers..."
|
121
|
+
puts '-----------------------------'
|
122
|
+
compose_config.configuration.each_key do |service_name|
|
123
|
+
stop(service_name)
|
124
|
+
end
|
125
|
+
puts "\nDone."
|
139
126
|
|
140
|
-
puts
|
141
|
-
|
142
|
-
|
143
|
-
|
127
|
+
puts "\n\nRemoving container volumes..."
|
128
|
+
puts '-----------------------------'
|
129
|
+
compose_config.configuration.each_key do |service_name|
|
130
|
+
rm_v(service_name)
|
131
|
+
end
|
132
|
+
puts "\nDone."
|
133
|
+
puts "\n\n\n"
|
144
134
|
|
145
135
|
# cleanup build interpolated docker-compose.yml
|
146
|
-
#
|
136
|
+
# File.delete COMPOSE_FILENAME if File.exists? COMPOSE_FILENAME
|
147
137
|
|
148
|
-
system 'docker ps -a'
|
138
|
+
system 'docker ps -a'
|
139
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# TODO: make docker-rails CLI and put this in the lib, add optional ! method to raise if failed
|
4
|
+
|
5
|
+
# ping db to see if it is ready before continuing
|
6
|
+
require 'rubygems'
|
7
|
+
require 'active_record'
|
8
|
+
require 'mysql2'
|
9
|
+
|
10
|
+
LOOP_LIMIT=60
|
11
|
+
puts "\n"
|
12
|
+
printf 'Waiting for confirmation of db service startup...'
|
13
|
+
LOOP_LIMIT.times do |i|
|
14
|
+
if i == LOOP_LIMIT - 1
|
15
|
+
printf 'failed to connect.'
|
16
|
+
raise 'Failed to connect to db service.'
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveRecord::Base.establish_connection ({
|
20
|
+
adapter: 'mysql2',
|
21
|
+
host: 'db',
|
22
|
+
port: 3306,
|
23
|
+
username: 'root'})
|
24
|
+
connected =
|
25
|
+
begin
|
26
|
+
ActiveRecord::Base.connection_pool.with_connection { |con| con.active? }
|
27
|
+
rescue => e
|
28
|
+
# puts "#{e.class.name}: #{e.message}"
|
29
|
+
false
|
30
|
+
end
|
31
|
+
printf '.'
|
32
|
+
if connected
|
33
|
+
printf 'connected.'
|
34
|
+
break
|
35
|
+
end
|
36
|
+
sleep 1
|
37
|
+
end
|
38
|
+
puts "\n"
|
data/docker-rails.gemspec
CHANGED
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.0.
|
4
|
+
version: 0.0.2
|
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-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,11 +66,26 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 1.1.6
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mysql2
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.3.18
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.3.18
|
69
83
|
description: ''
|
70
84
|
email:
|
71
85
|
- kevin.ross@alienfast.com
|
72
86
|
executables:
|
73
87
|
- docker-rails
|
88
|
+
- docker-rails-db-check
|
74
89
|
extensions: []
|
75
90
|
extra_rdoc_files: []
|
76
91
|
files:
|
@@ -82,6 +97,7 @@ files:
|
|
82
97
|
- README.md
|
83
98
|
- Rakefile
|
84
99
|
- bin/docker-rails
|
100
|
+
- bin/docker-rails-db-check
|
85
101
|
- docker-rails.gemspec
|
86
102
|
- lib/docker/rails.rb
|
87
103
|
- lib/docker/rails/compose_config.rb
|