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 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