docker-rails 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4daf7ed396ab33b4baccadbe1a1f888af9a3271d
4
- data.tar.gz: 7a38191133060c00417437db6ba84e93d3f936a5
3
+ metadata.gz: 6052b133ad5e1cdb58cb484baa077de133994fdc
4
+ data.tar.gz: 33124a13ab2327fbc1dfe2ae28fed2542f2656f5
5
5
  SHA512:
6
- metadata.gz: 8d8ffca0992dbbbd4edfd75b36de681f018933d497f1b9cd37d05edb0cd59471c06fd15136de6e031867f928904732c8570f45e219c69b714a5e24f94cd2cdd3
7
- data.tar.gz: 49cea1c9d37dcb37d519e3db6d0345185f6fc6cb6dac30c0a6f1d17fa708a7de2bf7df8cbd397f5daea0e0555046dc1a3f1a86d8b9df5562e888e148c4f863e7
6
+ metadata.gz: a9fd4e6b3e13e76beb5f914b9944860101f3ccb7c36792de0de1525372396c719fbff75c4c65d6144b7d3075302c0bb0be2d118cf31ba70746168cc1c2007e19
7
+ data.tar.gz: 30f5cf9246f18910399c7eb937fdc90ed2816243b1386a0af47c68ced889258f1452a2ede03e731e55d2034aceeca4020d3bc92352bccbc41e822c29ac8e4b0c
data/README.md CHANGED
@@ -1,21 +1,24 @@
1
- # Docker::Rails
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, and continues with `web` once `db` is ready
9
- - cleans up `db` and `web` containers once completed
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
- **Very much a work in progress - contributions welcome**
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
- Needs:
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: /project/script/start
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. Add a startup script
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
- ### 5. Submit pull requests!
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 much easier.
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 = '113' # temp should be passed in
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
- gems_container = Docker::Container.get(GEMS_VOLUME_NAME)
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
- gems_container = Docker::Container.create('name' => GEMS_VOLUME_NAME, 'Image' => 'busybox', 'Mounts' => [{'Destination' => GEMS_VOLUME_PATH}])
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 xc(cmd)
54
- cmd = "docker-compose -f #{COMPOSE_FILENAME} -p #{BUILD_NAME} #{cmd}"
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 = xc "ps #{service_name}"
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
- # http://blog.oddbit.com/2014/08/11/four-ways-to-connect-a-docker/
69
- def get_ip_address(container_name)
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
- ip_address = get_ip_address(container_name)
87
- [container, container_name, ip_address]
97
+ [container, container_name]
88
98
  end
89
99
 
90
- def destroy_container(container, container_name)
91
- puts "Stopping and deleting #{container_name}..."
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
- # Start the db container
97
- db_container, db_container_name, db_ip_address = *up_container('db', '-d')
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
- LOOP_LIMIT=60
104
- puts "=> Waiting for confirmation of #{db_container_name} db service startup at #{db_ip_address}..."
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 containers
137
- web_container, web_container_name, web_ip_address = *up_container('web')
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 'Cleaning up containers...'
141
- destroy_container(db_container, db_container_name)
142
- destroy_container(web_container, web_container_name)
143
- puts "Done.\n\n\n"
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
- # File.delete COMPOSE_FILENAME if File.exists? COMPOSE_FILENAME
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
@@ -24,4 +24,5 @@ Gem::Specification.new do |s|
24
24
  s.add_dependency 'docker-api'
25
25
  # s.add_dependency 'parallel_tests'
26
26
  s.add_dependency 'dry-config', '>= 1.1.6'
27
+ s.add_dependency 'mysql2', '~> 0.3.18' # http://stackoverflow.com/a/32466950/2363935
27
28
  end
@@ -7,6 +7,7 @@ module Docker
7
7
  compose = ComposeConfig.new(symbolize: false)
8
8
  compose.load!(nil, input_filename)
9
9
  compose.write_yaml_file(output_filename)
10
+ compose
10
11
  end
11
12
  end
12
13
  end
@@ -1,5 +1,5 @@
1
1
  module Docker
2
2
  module Rails
3
- VERSION = "0.0.1"
3
+ VERSION = '0.0.2'
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.0.1
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-10 00:00:00.000000000 Z
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