docker-app 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker-app.gemspec +36 -0
- data/exe/docker-app +20 -0
- data/lib/docker_app.rb +23 -0
- data/lib/docker_app/builder/packer.rb +105 -0
- data/lib/docker_app/chef/.chef/knife.rb +118 -0
- data/lib/docker_app/chef/chef_build_image.rb +55 -0
- data/lib/docker_app/chef/chef_destroy_container.rb +13 -0
- data/lib/docker_app/chef/chef_destroy_image.rb +17 -0
- data/lib/docker_app/chef/chef_exec_container.rb +16 -0
- data/lib/docker_app/chef/chef_run_container.rb +64 -0
- data/lib/docker_app/chef/install_container_service.rb +14 -0
- data/lib/docker_app/cli.rb +502 -0
- data/lib/docker_app/command.rb +16 -0
- data/lib/docker_app/config.rb +249 -0
- data/lib/docker_app/config/dsl.rb +64 -0
- data/lib/docker_app/config/helpers.rb +99 -0
- data/lib/docker_app/manager_container.rb +376 -0
- data/lib/docker_app/manager_image.rb +119 -0
- data/lib/docker_app/manager_swarm.rb +66 -0
- data/lib/docker_app/provisioner/base.rb +179 -0
- data/lib/docker_app/provisioner/chef.rb +93 -0
- data/lib/docker_app/server_settings.rb +361 -0
- data/lib/docker_app/version.rb +3 -0
- data/lib/templates/example-chef/.chef/knife.rb +5 -0
- data/lib/templates/example-chef/config.rb.erb +18 -0
- data/lib/templates/example-chef/servers/server1/.chef/knife.rb +8 -0
- data/lib/templates/example-chef/servers/server1/config.rb.erb +54 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/README.md +1 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/metadata.rb.erb +8 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/build.rb +10 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/install.rb +36 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/recipes/install_host.rb +9 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/templates/index.html.erb +5 -0
- data/lib/templates/example-chef/servers/server1/cookbooks/server1/templates/nginx-sites/default.conf.erb +45 -0
- data/readme.md +853 -0
- data/readme_developers.md +54 -0
- metadata +129 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
module DockerApp
|
2
|
+
class ManagerImage
|
3
|
+
|
4
|
+
###
|
5
|
+
def self.build_image(server_name, settings=nil)
|
6
|
+
puts "building image for #{server_name}..."
|
7
|
+
#puts "settings: #{settings}"
|
8
|
+
#puts "debug: #{settings['properties']}"
|
9
|
+
|
10
|
+
#settings = load_settings(server_name)
|
11
|
+
|
12
|
+
t = settings['build']['build_type']
|
13
|
+
if t=='' || t=='none'
|
14
|
+
#
|
15
|
+
puts "no build needed..."
|
16
|
+
|
17
|
+
elsif t.downcase=='dockerfile'
|
18
|
+
return build_image_with_dockerfile(settings)
|
19
|
+
elsif t.downcase=='github'
|
20
|
+
return build_image_with_dockerfile_github(settings)
|
21
|
+
|
22
|
+
elsif t=='chef'
|
23
|
+
return build_image_with_chef(settings)
|
24
|
+
elsif t=='packer'
|
25
|
+
return build_image_with_packer(settings)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build_image_with_dockerfile(settings)
|
30
|
+
puts "build image with Dockerfile"
|
31
|
+
|
32
|
+
#cmd %Q(cd #{name} && docker build -t #{settings.image_name} . )
|
33
|
+
cmd %Q(docker build -t #{settings.image_name} #{settings.dir_server_root} )
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.build_image_with_dockerfile_github(settings)
|
38
|
+
puts "build image with Dockerfile from github"
|
39
|
+
|
40
|
+
cmd %Q(docker build -t #{settings.image_name} #{settings.properties['build']['base_image']['repository']} )
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def self.build_image_with_chef(settings)
|
46
|
+
puts "build image with chef"
|
47
|
+
|
48
|
+
# config json
|
49
|
+
save_chef_config(settings)
|
50
|
+
|
51
|
+
# check node
|
52
|
+
cmd %Q(cd #{Config.root_path} && chef exec knife node show #{settings.chef_node_name} -c #{chef_config_knife_path})
|
53
|
+
|
54
|
+
|
55
|
+
#cmd %Q(SERVER_NAME=#{settings.name} SERVER_PATH=#{settings.dir_server_root} chef exec chef-client -z -N #{settings.image_name} -j #{settings.filename_config_json} -c #{chef_config_knife_path} #{chef_recipe_path('chef_build_image.rb')} )
|
56
|
+
res_recipe = run_chef_recipe(settings, 'chef_build_image.rb')
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def self.build_image_with_packer(settings)
|
61
|
+
require_relative '../../lib/docker_app/builder/packer'
|
62
|
+
|
63
|
+
puts "build image with packer"
|
64
|
+
|
65
|
+
builder = DockerApp::Builder::Packer.new(settings)
|
66
|
+
builder.build
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def self.destroy_image(server_name, settings={})
|
71
|
+
puts "destroying image for server #{server_name}"
|
72
|
+
|
73
|
+
cmd %Q(docker rmi #{settings.image_name} )
|
74
|
+
cmd %Q(docker rm -f chef.converge.#{settings.image_name} )
|
75
|
+
|
76
|
+
# delete chef data
|
77
|
+
if settings['build']['build_type']=='chef'
|
78
|
+
return destroy_image_chef(settings)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def self.destroy_image_chef(settings)
|
84
|
+
puts "destroying image with chef..."
|
85
|
+
|
86
|
+
# config json
|
87
|
+
save_chef_config(settings)
|
88
|
+
|
89
|
+
# destroy temp container
|
90
|
+
cmd %Q(docker rm -f chef-converge.#{settings.image_name} )
|
91
|
+
|
92
|
+
#
|
93
|
+
cmd %Q(cd #{Config.root_path} && chef exec knife node delete #{settings.chef_node_name} -y -c #{chef_config_knife_path})
|
94
|
+
|
95
|
+
res_recipe = run_chef_recipe(settings, 'chef_destroy_image.rb')
|
96
|
+
|
97
|
+
chef_remove_data(settings)
|
98
|
+
|
99
|
+
# work - before 2016-nov-19
|
100
|
+
#cmd %Q(cd #{Config.root_path} && chef exec knife node delete #{settings.chef_node_name} -y -c #{chef_config_knife_path})
|
101
|
+
|
102
|
+
# clean chef client, node
|
103
|
+
#cmd %Q(cd #{Config.root_path} && rm -f #{settings.filename_chef_node_json} )
|
104
|
+
#cmd %Q(cd #{Config.root_path} && rm -f #{settings.filename_chef_client_json} )
|
105
|
+
end
|
106
|
+
|
107
|
+
###
|
108
|
+
|
109
|
+
def self.image_exist?(settings)
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
###
|
114
|
+
def self.cmd(s)
|
115
|
+
Command.cmd(s)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module DockerApp
|
2
|
+
class ManagerSwarm
|
3
|
+
|
4
|
+
def self.destroy_service(server_name, settings)
|
5
|
+
puts "destroying service #{server_name}..."
|
6
|
+
|
7
|
+
#
|
8
|
+
cmd %Q(docker service rm #{settings.service_name} )
|
9
|
+
|
10
|
+
#
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def self.create_service(server_name, settings={})
|
16
|
+
puts "create swarm service.."
|
17
|
+
|
18
|
+
# destroy
|
19
|
+
destroy_service(server_name, settings)
|
20
|
+
|
21
|
+
|
22
|
+
# prepare
|
23
|
+
create_volumes_dirs(settings)
|
24
|
+
|
25
|
+
# create service
|
26
|
+
docker_opts = settings.properties['docker']
|
27
|
+
|
28
|
+
run_opts = []
|
29
|
+
run_opts << "--network #{docker_opts['swarm_network']}" if docker_opts['swarm_network']
|
30
|
+
run_opts << settings.docker_ports_string
|
31
|
+
run_opts << settings.run_env_variables_string
|
32
|
+
|
33
|
+
# volumes
|
34
|
+
#--mount type=bind,source=/path/on/host,destination=/path/in/container
|
35
|
+
run_opts << settings.docker_volumes.map{|r| "--mount type=bind,source=#{r[0]},destination=#{r[1]}" }.join(' ')
|
36
|
+
|
37
|
+
#
|
38
|
+
run_opts << docker_opts['swarm_options']
|
39
|
+
|
40
|
+
cmd %Q(docker service create \
|
41
|
+
--name #{settings.service_name} \
|
42
|
+
#{run_opts.join(' ')} \
|
43
|
+
#{settings.image_name} #{settings['docker']['command']}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# volumes
|
49
|
+
def self.create_volumes_dirs(settings)
|
50
|
+
settings.docker_volumes.each do |r|
|
51
|
+
dirpath = "#{r[0]}"
|
52
|
+
if !Dir.exists?(dirpath)
|
53
|
+
FileUtils.mkdir_p(dirpath) rescue nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# helpers
|
59
|
+
|
60
|
+
def self.cmd(s)
|
61
|
+
Command.cmd(s)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module DockerApp
|
2
|
+
module Provisioner
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def self.run_provision_scripts_setup(settings)
|
6
|
+
#
|
7
|
+
setup_scripts = (settings['provision']['setup'] rescue [])
|
8
|
+
if setup_scripts
|
9
|
+
setup_scripts.each do |script|
|
10
|
+
_run_setup_script(settings, script)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def self.run_provision_scripts_bootstrap(settings)
|
18
|
+
#
|
19
|
+
bootstrap_scripts = (settings['provision']['bootstrap'] rescue [])
|
20
|
+
if bootstrap_scripts
|
21
|
+
bootstrap_scripts.each do |script|
|
22
|
+
_run_bootstrap_script(settings, script)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
=begin
|
28
|
+
# commented - 2017-02-22
|
29
|
+
|
30
|
+
#
|
31
|
+
install_node_script_type = (settings['install']['node']['script_type'] rescue nil)
|
32
|
+
install_bootstrap_script = (settings['install']['bootstrap']['script'] rescue nil)
|
33
|
+
|
34
|
+
if install_node_script_type && install_node_script_type=='chef_recipe'
|
35
|
+
# run container and provision with chef
|
36
|
+
#_run_container_chef(settings)
|
37
|
+
|
38
|
+
# ???
|
39
|
+
#_provision_container_chef_recipe(settings)
|
40
|
+
|
41
|
+
elsif install_node_script_type && install_node_script_type=='shell'
|
42
|
+
# docker run
|
43
|
+
#create_and_run_container(settings)
|
44
|
+
|
45
|
+
# provision with shell script
|
46
|
+
run_shell_script_in_container(settings, "install.sh")
|
47
|
+
|
48
|
+
else
|
49
|
+
# no script for provision
|
50
|
+
#_run_container_docker(settings)
|
51
|
+
|
52
|
+
# docker run
|
53
|
+
#create_and_run_container(settings)
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# bootstrap
|
58
|
+
if install_bootstrap_script
|
59
|
+
#script = settings['install']['bootstrap']['script'] || '/opt/bootstrap/bootstrap.sh'
|
60
|
+
|
61
|
+
# bootstsrap with shell script
|
62
|
+
run_bootstrap_shell_script_in_container(settings, install_bootstrap_script)
|
63
|
+
end
|
64
|
+
=end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
### provision - setup
|
72
|
+
|
73
|
+
def self._run_setup_script(settings, script)
|
74
|
+
puts "run script #{script}"
|
75
|
+
|
76
|
+
if script['type']=='shell'
|
77
|
+
return _run_setup_script_on_host_shell(settings, script)
|
78
|
+
elsif script['type']=='chef'
|
79
|
+
return _run_setup_script_on_host_chef(settings, script)
|
80
|
+
end
|
81
|
+
|
82
|
+
return nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def self._run_setup_script_on_host_shell(settings, script)
|
86
|
+
cmd %Q(cd #{settings.dir_server_root} && #{script['script']} )
|
87
|
+
end
|
88
|
+
|
89
|
+
def self._run_setup_script_on_host_chef(settings, script)
|
90
|
+
raise 'NOT implemented'
|
91
|
+
|
92
|
+
# run script on host machine
|
93
|
+
script_name = settings['install']['host']['script'] || 'install_host'
|
94
|
+
|
95
|
+
# check script exists
|
96
|
+
#script_path = "#{settings.name}/cookbooks/#{settings.name}/recipes/#{script_name}.rb"
|
97
|
+
#f = File.expand_path('.', script_path)
|
98
|
+
|
99
|
+
#if !File.exists?(f)
|
100
|
+
# puts "script not found: #{f}. Skipping"
|
101
|
+
# return false
|
102
|
+
#end
|
103
|
+
|
104
|
+
#puts "pwd= #{Dir.pwd}"
|
105
|
+
#puts "root = #{Config.root_path}"
|
106
|
+
#exit
|
107
|
+
|
108
|
+
#
|
109
|
+
|
110
|
+
return true
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
### provision - bootstrap
|
117
|
+
|
118
|
+
def self._run_bootstrap_script(settings, script)
|
119
|
+
puts "run BS script #{script}"
|
120
|
+
|
121
|
+
if script['type']=='shell' && script['run_from']=='host'
|
122
|
+
return _run_bootstrap_script_on_host_shell(settings, script)
|
123
|
+
elsif script['type']=='shell' && (script['run_from'].nil? || script['run_from']=='')
|
124
|
+
_run_bootstrap_script_in_container_shell(settings, script)
|
125
|
+
elsif script['type']=='chef'
|
126
|
+
_run_bootstrap_script_in_container_chef(settings, script)
|
127
|
+
end
|
128
|
+
|
129
|
+
return nil
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def self._run_bootstrap_script_on_host_shell(settings, script)
|
134
|
+
cmd %Q(cd #{settings.dir_server_root} && #{script['script']} )
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
def self._run_bootstrap_script_in_container_shell(settings, script)
|
140
|
+
script_path = script['script']
|
141
|
+
|
142
|
+
# exec
|
143
|
+
cmd %Q(docker exec #{settings.container_name} #{script_path} )
|
144
|
+
end
|
145
|
+
|
146
|
+
def self._run_bootstrap_script_in_container_chef(settings, script)
|
147
|
+
req = DockerApp::Provisioner::Chef.new(settings)
|
148
|
+
return req.run_recipe_in_container script['dir_base'], script['recipe_name']
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
### helpers - shell
|
154
|
+
|
155
|
+
def self.run_script_in_container_shell(settings, script_name)
|
156
|
+
script_path = settings.make_path_full("scripts/#{script_name}")
|
157
|
+
|
158
|
+
# copy
|
159
|
+
cmd %Q(cd #{Config.root_path} && docker cp #{script_path} #{settings.container_name}:/tmp/#{script_name} )
|
160
|
+
|
161
|
+
# exec
|
162
|
+
cmd %Q(docker exec #{settings.container_name} chmod +x /tmp/#{script_name} )
|
163
|
+
cmd %Q(docker exec #{settings.container_name} /tmp/#{script_name} )
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
|
170
|
+
###
|
171
|
+
def self.cmd(s)
|
172
|
+
Command.cmd(s)
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module DockerApp
|
2
|
+
module Provisioner
|
3
|
+
class Chef
|
4
|
+
|
5
|
+
attr_accessor :server
|
6
|
+
|
7
|
+
def server=(v)
|
8
|
+
@server = v
|
9
|
+
@server
|
10
|
+
end
|
11
|
+
|
12
|
+
def server
|
13
|
+
@server
|
14
|
+
end
|
15
|
+
|
16
|
+
def settings
|
17
|
+
server
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def initialize(_settings)
|
22
|
+
self.server = _settings
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
###
|
27
|
+
|
28
|
+
def copy_config_file
|
29
|
+
# config json
|
30
|
+
save_config
|
31
|
+
|
32
|
+
# copy to container
|
33
|
+
DockerApp::Command.cmd %Q(docker cp #{filename_config} #{settings.container_name}:#{docker_filename_config})
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def save_config
|
38
|
+
require 'json'
|
39
|
+
filename = filename_config
|
40
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
41
|
+
File.open(filename,"w+") do |f|
|
42
|
+
f.write(build_config.to_json)
|
43
|
+
end
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def filename_config
|
49
|
+
File.join(Config.root_path, 'temp', "bootstrap-#{settings.name}.json")
|
50
|
+
end
|
51
|
+
|
52
|
+
def docker_filename_config
|
53
|
+
"/opt/bootstrap/config.json"
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_config
|
57
|
+
res = {}
|
58
|
+
|
59
|
+
attr = settings.properties['attributes']
|
60
|
+
res = attr
|
61
|
+
|
62
|
+
#res = settings.all_attributes
|
63
|
+
|
64
|
+
res
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
### run recipes
|
69
|
+
def run_recipe_in_container(dir_base, recipe_name)
|
70
|
+
|
71
|
+
recipe_name ||= "server::bootstrap"
|
72
|
+
|
73
|
+
# generate config
|
74
|
+
copy_config_file
|
75
|
+
|
76
|
+
|
77
|
+
#
|
78
|
+
q = %Q(cd #{dir_base} && chef-client -z -j #{docker_filename_config} --override-runlist "recipe[#{recipe_name}]" )
|
79
|
+
|
80
|
+
# exec
|
81
|
+
docker_run_cmd q
|
82
|
+
end
|
83
|
+
|
84
|
+
###
|
85
|
+
def docker_run_cmd(s)
|
86
|
+
DockerApp::Command.cmd %Q(docker exec #{settings.container_name} bash -c '#{s}')
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|