railsdock 0.1.0
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 +7 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +173 -0
- data/LICENSE.txt +20 -0
- data/README.md +55 -0
- data/Rakefile +14 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/railsdock +18 -0
- data/ext/railsdock/extconf.rb +3 -0
- data/ext/railsdock/railsdock.c +9 -0
- data/ext/railsdock/railsdock.h +6 -0
- data/lib/railsdock.rb +6 -0
- data/lib/railsdock/cli.rb +33 -0
- data/lib/railsdock/command.rb +101 -0
- data/lib/railsdock/commands/install.rb +142 -0
- data/lib/railsdock/logo.rb +49 -0
- data/lib/railsdock/templates/install/default/Dockerfile +101 -0
- data/lib/railsdock/templates/install/default/default.env.erb +44 -0
- data/lib/railsdock/templates/install/default/docker-compose.mac.yml +7 -0
- data/lib/railsdock/templates/install/default/docker-compose.yml.erb +51 -0
- data/lib/railsdock/templates/install/memcached/Dockerfile +7 -0
- data/lib/railsdock/templates/install/memcached/docker-compose.yml.erb +11 -0
- data/lib/railsdock/templates/install/mysql/Dockerfile +7 -0
- data/lib/railsdock/templates/install/mysql/database.yml.erb +18 -0
- data/lib/railsdock/templates/install/mysql/docker-compose.yml.erb +13 -0
- data/lib/railsdock/templates/install/postgres/Dockerfile +7 -0
- data/lib/railsdock/templates/install/postgres/database.yml.erb +18 -0
- data/lib/railsdock/templates/install/postgres/docker-compose.yml.erb +11 -0
- data/lib/railsdock/templates/install/redis/Dockerfile +7 -0
- data/lib/railsdock/templates/install/redis/docker-compose.yml.erb +11 -0
- data/lib/railsdock/version.rb +3 -0
- data/railsdock.gemspec +60 -0
- data/railsdock.png +0 -0
- metadata +393 -0
data/lib/railsdock.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Railsdock
|
6
|
+
# Handle the application command line parsing
|
7
|
+
# and the dispatch to various command objects
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class CLI < Thor
|
11
|
+
# Error raised by this runner
|
12
|
+
Error = Class.new(StandardError)
|
13
|
+
|
14
|
+
desc 'version', 'railsdock version'
|
15
|
+
def version
|
16
|
+
require_relative 'version'
|
17
|
+
puts "Railsdock v#{Railsdock::VERSION}"
|
18
|
+
end
|
19
|
+
map %w[--version -v] => :version
|
20
|
+
|
21
|
+
desc 'install', 'Install Railsdock in an existing rails application'
|
22
|
+
method_option :help, aliases: '-h', type: :boolean,
|
23
|
+
desc: 'Display usage information'
|
24
|
+
def install(app_name = nil)
|
25
|
+
if options[:help]
|
26
|
+
invoke :help, ['install']
|
27
|
+
else
|
28
|
+
require_relative 'commands/install'
|
29
|
+
Railsdock::Commands::Install.new(options.merge(app_name: app_name)).execute
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Railsdock
|
6
|
+
class Command
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :command, :run
|
10
|
+
|
11
|
+
# Execute this command
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def execute(*)
|
15
|
+
raise(
|
16
|
+
NotImplementedError,
|
17
|
+
"#{self.class}##{__method__} must be implemented"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
# The external commands runner
|
22
|
+
#
|
23
|
+
# @see http://www.rubydoc.info/gems/tty-command
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def cmd(**options)
|
27
|
+
require 'tty-command'
|
28
|
+
TTY::Command.new(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
# The cursor movement
|
32
|
+
#
|
33
|
+
# @see http://www.rubydoc.info/gems/tty-cursor
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def cursor
|
37
|
+
require 'tty-cursor'
|
38
|
+
TTY::Cursor
|
39
|
+
end
|
40
|
+
|
41
|
+
# The generating config files
|
42
|
+
#
|
43
|
+
# @see http://www.rubydoc.info/gems/tty-config
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def config
|
47
|
+
require 'tty-config'
|
48
|
+
TTY::Config
|
49
|
+
end
|
50
|
+
|
51
|
+
# Open a file or text in the user's preferred editor
|
52
|
+
#
|
53
|
+
# @see http://www.rubydoc.info/gems/tty-editor
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
def editor
|
57
|
+
require 'tty-editor'
|
58
|
+
TTY::Editor
|
59
|
+
end
|
60
|
+
|
61
|
+
# File manipulation utility methods.
|
62
|
+
#
|
63
|
+
# @see http://www.rubydoc.info/gems/tty-file
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def file
|
67
|
+
require 'tty-file'
|
68
|
+
TTY::File
|
69
|
+
end
|
70
|
+
|
71
|
+
# Terminal platform and OS properties
|
72
|
+
#
|
73
|
+
# @see http://www.rubydoc.info/gems/tty-platform
|
74
|
+
#
|
75
|
+
# @api public
|
76
|
+
def platform
|
77
|
+
require 'tty-platform'
|
78
|
+
TTY::Platform.new
|
79
|
+
end
|
80
|
+
|
81
|
+
# The interactive prompt
|
82
|
+
#
|
83
|
+
# @see http://www.rubydoc.info/gems/tty-prompt
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
def prompt(**options)
|
87
|
+
require 'tty-prompt'
|
88
|
+
TTY::Prompt.new(options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def progress(*options)
|
92
|
+
require 'tty-progressbar'
|
93
|
+
TTY::ProgressBar.new(*options)
|
94
|
+
end
|
95
|
+
|
96
|
+
def color
|
97
|
+
require 'pastel'
|
98
|
+
Pastel.new
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
require 'erb'
|
5
|
+
require_relative '../command'
|
6
|
+
require_relative '../logo'
|
7
|
+
|
8
|
+
module Railsdock
|
9
|
+
module Commands
|
10
|
+
class Install < Railsdock::Command
|
11
|
+
OPTIONS_HASH = {
|
12
|
+
database: {
|
13
|
+
name: 'Database',
|
14
|
+
options: %i[postgres mysql]
|
15
|
+
},
|
16
|
+
mem_store: {
|
17
|
+
name: 'In-Memory Store',
|
18
|
+
options: %i[redis memcached]
|
19
|
+
}
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
POST_INSTALL_MESSAGE =<<~PIM
|
23
|
+
Railsdock successfully installed
|
24
|
+
|
25
|
+
Run `docker-compose build` then `docker-compose up` to start your app,
|
26
|
+
|
27
|
+
PIM
|
28
|
+
|
29
|
+
BASE_TEMPLATE_DIR = File.expand_path("#{__dir__}/../templates/install").freeze
|
30
|
+
|
31
|
+
def initialize(options)
|
32
|
+
@options = options
|
33
|
+
@variables = OpenStruct.new(
|
34
|
+
app_name: options[:app_name] || get_app_name,
|
35
|
+
is_windows?: platform.windows?,
|
36
|
+
is_mac?: platform.mac?,
|
37
|
+
uid: cmd.run('id -u').out.chomp
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def execute(input: $stdin, output: $stdout)
|
42
|
+
output.puts Railsdock::Logo.call
|
43
|
+
@variables[:dockerfile_dir] = prompt_for_dockerfile_directory
|
44
|
+
copy_default_files
|
45
|
+
service_hash = collect_service_selections
|
46
|
+
service_hash.each do |type, service|
|
47
|
+
file.copy_file("#{BASE_TEMPLATE_DIR}/#{service}/Dockerfile", [@variables.dockerfile_dir, service, "/Dockerfile"].join)
|
48
|
+
inject_driver_config(service)
|
49
|
+
append_erb_to_compose_file(service)
|
50
|
+
file.inject_into_file('./docker-compose.yml', "\n #{service}:", after: "\nvolumes:")
|
51
|
+
append_service_config_to_env(service)
|
52
|
+
copy_db_yml("#{BASE_TEMPLATE_DIR}/#{service}/database.yml.erb") if type == :database
|
53
|
+
end
|
54
|
+
output.puts POST_INSTALL_MESSAGE
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def get_app_name
|
60
|
+
::File.open('./config/application.rb').read.match(/module (.+)\s/)[1].downcase
|
61
|
+
end
|
62
|
+
|
63
|
+
def copy_db_yml(erb_file)
|
64
|
+
file.copy_file(erb_file, './config/database.yml', context: @variables)
|
65
|
+
end
|
66
|
+
|
67
|
+
def collect_service_selections
|
68
|
+
prompt.collect do
|
69
|
+
OPTIONS_HASH.each do |key, value|
|
70
|
+
key(key).select("Select the #{value[:name]} used by your application:", value[:options])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def inject_driver_config(service)
|
76
|
+
file.inject_into_file('./docker-compose.yml', after: " node_modules:\n driver: ${VOLUMES_DRIVER}\n") do
|
77
|
+
<<-YAML
|
78
|
+
#{service}:
|
79
|
+
driver: ${VOLUMES_DRIVER}
|
80
|
+
YAML
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def generate_erb(source_path)
|
85
|
+
template = if ERB.version.scan(/\d+\.\d+\.\d+/)[0].to_f >= 2.2
|
86
|
+
ERB.new(::File.binread(source_path), trim_mode: '-', eoutvar: '@output_buffer')
|
87
|
+
else
|
88
|
+
ERB.new(::File.binread(source_path), nil, '-', '@output_buffer')
|
89
|
+
end
|
90
|
+
template.result(@variables.instance_eval('binding'))
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_or_append_to_file(source_path, destination_path)
|
94
|
+
if ::File.exist?(destination_path) && generate_erb(source_path) != ::File.binread(destination_path)
|
95
|
+
file.safe_append_to_file(destination_path, generate_erb(source_path))
|
96
|
+
else
|
97
|
+
file.copy_file(source_path, destination_path, context: @variables)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def append_erb_to_compose_file(service)
|
102
|
+
file.safe_append_to_file('./docker-compose.yml') do
|
103
|
+
generate_erb("#{BASE_TEMPLATE_DIR}/#{service}/docker-compose.yml.erb")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def append_service_config_to_env(service)
|
108
|
+
file.safe_append_to_file('./.env') do
|
109
|
+
::File.binread("#{BASE_TEMPLATE_DIR}/#{service}/#{service}.env")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def prompt_for_dockerfile_directory
|
114
|
+
prompt.ask('Where would you like your docker container configuration files to live?') do |q|
|
115
|
+
q.default './docker/'
|
116
|
+
q.validate(%r{\.\/[A-z\/]+\/})
|
117
|
+
q.modify :remove
|
118
|
+
q.messages[:valid?] = 'Invalid directory path (should start with ./ and end with /)'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def copy_default_files
|
123
|
+
Dir["#{BASE_TEMPLATE_DIR}/default/*"].each do |path|
|
124
|
+
destination_file(path)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def destination_file(path)
|
129
|
+
case File.basename(path)
|
130
|
+
when 'Dockerfile'
|
131
|
+
file.copy_file(path, "#{@variables.dockerfile_dir}ruby/Dockerfile", context: @variables)
|
132
|
+
when 'docker-compose.yml.erb'
|
133
|
+
file.copy_file(path, './docker-compose.yml', context: @variables)
|
134
|
+
when 'default.env.erb'
|
135
|
+
create_or_append_to_file(path, './.env')
|
136
|
+
else
|
137
|
+
file.copy_file(path, "./#{File.basename(path)}", context: @variables)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pastel'
|
2
|
+
|
3
|
+
module Railsdock
|
4
|
+
class Logo
|
5
|
+
def self.call
|
6
|
+
color = Pastel.new
|
7
|
+
color.red(" `yy: `.
|
8
|
+
-oo` .-/+ooyysooo//-/sy
|
9
|
+
`+ooyyhhhhhhhhhhhhhhhys/-`
|
10
|
+
`-oyhhhhhhhhhhhhhhhyyyyyhhhys/-
|
11
|
+
.- .:yhhhhhhhhhhhhysoo+````:os-:/oyyy+.
|
12
|
+
:yy:/yhhhhhhhhhhhyo-` :o/ `.- ``:oss:`
|
13
|
+
.+shhhhhhhhhhhho++ `-+o.
|
14
|
+
`oyhhhhhhhhhhhy-.so` `
|
15
|
+
.shhhhhhhhhhhhy. `
|
16
|
+
` -yhhhhhhhhhhhhh/:`", color.cyan(" -+/. "), color.red("
|
17
|
+
:ys/-yhhhhhhhhhhhhho/hs"), color.cyan(" -oooo/. "), color.red("
|
18
|
+
/os:yhhhhhhhhhhhhhh:`::"), color.cyan(" `ooooooo: "), color.red("
|
19
|
+
`ohhhhhhhhhhhhhhh."), color.cyan(" :oooooooo: "), color.red("
|
20
|
+
:hhhhhhhhhhhhhhhh...`"), color.cyan(" /ooooooooo:////::.` "), color.red("
|
21
|
+
`yhhhhhhhhhhhhhhhh-sys"), color.cyan(" -oooooooooooooooooo:"), color.red("
|
22
|
+
-yyyyyyyyyyyyyyyyy/-/+."), color.cyan(" /oooooooooooooooo+.
|
23
|
+
.-------"), color.red("/////////////////:"), color.cyan("---------------------------:/+oooooooooooooo+:`
|
24
|
+
:oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo++/-`
|
25
|
+
+oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-..``
|
26
|
+
/ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
|
27
|
+
:oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
|
28
|
+
.ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
|
29
|
+
+ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
|
30
|
+
.ooooooooooooooooooooooooooooooooooooooooooooooooooooooo+.
|
31
|
+
:ooooooooooooooooooooooooooooooooooooooooooooooooooooo:`
|
32
|
+
/oooooooooooooooooooooooooooooooooooooooooooooooooo:`
|
33
|
+
/ooooooooooooooooooooooooooooooooooooooooooooooo/`
|
34
|
+
-+oooooooooooooooooooooooooooooooooooooooooo+-`
|
35
|
+
-+ooooooooooooooooooooooooooooooooooooo/-`
|
36
|
+
.:/ooooooooooooooooooooooooooooo+/-.
|
37
|
+
`.-:/++oooooooooooo++//:-.`
|
38
|
+
|
39
|
+
╠╬ ╠╬
|
40
|
+
╠░ ╠░"), color.red("
|
41
|
+
████████▖ ▄██████▄ ███ ███ ▟█████▌"), color.cyan(" ╓φ╬╬░╬╦╬░ ,φ╬╬░╬▒╦ ╦╬╬░╬▒╦ ╠░ ,╦╬╬"), color.red("
|
42
|
+
███ ▐███ ███ ███ ███ ███ ▐██▙▄▄"), color.cyan(" ╠░╩ `╬░ ╔░╩ ╬╬ ╒╬╩ ` ╠░╓φ╬╩╜"), color.red("
|
43
|
+
███▄▄███▘ ███▄▄███ ███ ███ ▀▀████▙"), color.cyan(" ░░ ╠░ ╠░ ░░⌐░░⌐ ╠░╜╙╬╦"), color.red("
|
44
|
+
███▀███▄ ███▀▀███ ███ ███▄▄▄▄ ▄▄▄▄▄██"), color.cyan(" ╙╬╬╖, ╓φ░╩ ╬╬╦, ,φ░╩ ╠╠╦, ,╦╦ ╠░ ╙░╦"), color.red("
|
45
|
+
▀▀▀ ▝▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀▀▀▘"), color.cyan(" `╙╨╩╜^ `╙╨╩╜╜ ╙╙╨╜╜ ╙╜ ╙╜"))
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
ARG RAILSDOCK_RUBY_VERSION=2.6
|
2
|
+
|
3
|
+
FROM ruby:$RAILSDOCK_RUBY_VERSION
|
4
|
+
|
5
|
+
LABEL maintainer="Nate Vick <nate.vick@hint.io>"
|
6
|
+
|
7
|
+
ARG DEBIAN_FRONTEND=noninteractive
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
# Base Software Install
|
11
|
+
###############################################################################
|
12
|
+
|
13
|
+
ARG RAILSDOCK_NODE_VERSION=11
|
14
|
+
|
15
|
+
RUN curl -sL https://deb.nodesource.com/setup_$RAILSDOCK_NODE_VERSION.x | bash -
|
16
|
+
|
17
|
+
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
18
|
+
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
19
|
+
|
20
|
+
RUN apt-get update && apt-get install -y \
|
21
|
+
build-essential \
|
22
|
+
nodejs \
|
23
|
+
yarn \
|
24
|
+
locales \
|
25
|
+
git \
|
26
|
+
netcat \
|
27
|
+
vim \
|
28
|
+
sudo
|
29
|
+
|
30
|
+
###############################################################################
|
31
|
+
# Railsdock non-root user
|
32
|
+
###############################################################################
|
33
|
+
|
34
|
+
ARG RUBY_UID
|
35
|
+
ENV RUBY_UID $RUBY_UID
|
36
|
+
ARG RUBY_GID
|
37
|
+
ENV RUBY_GID $RUBY_GID
|
38
|
+
ARG USER=ruby
|
39
|
+
ENV USER $USER
|
40
|
+
|
41
|
+
RUN groupadd -g $RUBY_GID $USER && \
|
42
|
+
useradd -u $RUBY_UID -g $USER -m $USER && \
|
43
|
+
usermod -p "*" $USER && \
|
44
|
+
usermod -aG sudo $USER && \
|
45
|
+
echo "$USER ALL=NOPASSWD: ALL" >> /etc/sudoers.d/50-$USER
|
46
|
+
|
47
|
+
###############################################################################
|
48
|
+
# Ruby, Rubygems, and Bundler Defaults
|
49
|
+
###############################################################################
|
50
|
+
|
51
|
+
ENV LANG C.UTF-8
|
52
|
+
|
53
|
+
# Point Bundler at /gems. This will cause Bundler to re-use gems that have already been installed on the gems volume
|
54
|
+
ENV BUNDLE_PATH /gems
|
55
|
+
ENV BUNDLE_HOME /gems
|
56
|
+
|
57
|
+
# Increase how many threads Bundler uses when installing. Optional!
|
58
|
+
ARG RAILSDOCK_BUNDLE_JOBS=20
|
59
|
+
ENV BUNDLE_JOBS $RAILSDOCK_BUNDLE_JOBS
|
60
|
+
|
61
|
+
# How many times Bundler will retry a gem download. Optional!
|
62
|
+
ARG RAILSDOCK_BUNDLE_RETRY=5
|
63
|
+
ENV BUNDLE_RETRY $RAILSDOCK_BUNDLE_RETRY
|
64
|
+
|
65
|
+
# Where Rubygems will look for gems, similar to BUNDLE_ equivalents.
|
66
|
+
ENV GEM_HOME /gems
|
67
|
+
ENV GEM_PATH /gems
|
68
|
+
|
69
|
+
# Add /gems/bin to the path so any installed gem binaries are runnable from bash.
|
70
|
+
ENV PATH /gems/bin:$PATH
|
71
|
+
|
72
|
+
###############################################################################
|
73
|
+
# Optional Software Install
|
74
|
+
###############################################################################
|
75
|
+
|
76
|
+
#------------------------------------------------------------------------------
|
77
|
+
# Postgres Client:
|
78
|
+
#------------------------------------------------------------------------------
|
79
|
+
|
80
|
+
ARG INSTALL_PG_CLIENT=false
|
81
|
+
|
82
|
+
RUN if [ "$INSTALL_PG_CLIENT" = true ]; then \
|
83
|
+
# Install the pgsql client
|
84
|
+
apt-get install -y postgresql-client \
|
85
|
+
;fi
|
86
|
+
|
87
|
+
###############################################################################
|
88
|
+
# Final Touches
|
89
|
+
###############################################################################
|
90
|
+
|
91
|
+
RUN mkdir -p "$GEM_HOME" && chown $USER:$USER "$GEM_HOME"
|
92
|
+
|
93
|
+
RUN mkdir -p /app
|
94
|
+
WORKDIR /app
|
95
|
+
|
96
|
+
RUN mkdir -p node_modules && chown $USER:$USER node_modules
|
97
|
+
|
98
|
+
USER $USER
|
99
|
+
|
100
|
+
# Install latest bundler
|
101
|
+
RUN gem install bundler
|