docker_compose_deploy 1.0.0
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/Gemfile +4 -0
- data/README.md +15 -0
- data/Rakefile +2 -0
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/docker_compose_deploy.gemspec +27 -0
- data/exe/dcd +6 -0
- data/lib/docker_compose_deploy/actions/backup.rb +43 -0
- data/lib/docker_compose_deploy/actions/deployment.rb +42 -0
- data/lib/docker_compose_deploy/actions/docker_compose/file.rb +32 -0
- data/lib/docker_compose_deploy/actions/hosts.rb +30 -0
- data/lib/docker_compose_deploy/actions/image.rb +41 -0
- data/lib/docker_compose_deploy/actions/server.rb +27 -0
- data/lib/docker_compose_deploy/actions/skeleton.rb +43 -0
- data/lib/docker_compose_deploy/actions.rb +6 -0
- data/lib/docker_compose_deploy/cli.rb +49 -0
- data/lib/docker_compose_deploy/util/color.rb +26 -0
- data/lib/docker_compose_deploy/util/shell.rb +74 -0
- data/lib/docker_compose_deploy/version.rb +3 -0
- data/lib/docker_compose_deploy.rb +40 -0
- data/template/Vagrantfile +8 -0
- data/template/config.yml +80 -0
- data/template/docker-compose.yml +26 -0
- data/template/sites/config/proxy/nginx.conf +36 -0
- data/template/ssh_config_overrides +27 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d0c48329c119fc90532529e8a141a52b3cf45b17
|
4
|
+
data.tar.gz: 7489ff60f598b4fe35f69ddf371dc177e1655fed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c584fece997fe67ba5826b8df74f41c48455d5a6b6feb247f557c32858f5a1ab8072f3974898be0b8d8b9bb249618237b3ff9dea044dcd52f583735a315c69d4
|
7
|
+
data.tar.gz: 8ac15de15749951c7a48b01ae6c3f828df6c20cc564a71d5ca50dad59823da647e895b307a67ced72038e4f17971addab037023df435820b670fa8a77fd68f76
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
### Easily deploy a docker-compose.yml
|
2
|
+
|
3
|
+
This gem is a collection of scripts that I use to deploy my personal websites using docker-compose. This gem will help you:
|
4
|
+
|
5
|
+
- Generate a skeleton for you project
|
6
|
+
- Provision a server with Docker and Docker Compose
|
7
|
+
- Test your deployment on a vagrant machine
|
8
|
+
- Deploy your docker-compose project
|
9
|
+
- Backup the data that your applications Generate
|
10
|
+
|
11
|
+
While these scripts are great for your personal projects, they will not help you with zero-downtime deploys, rotating your logs, or any of that other fancy stuff.
|
12
|
+
|
13
|
+
This doesn't provide much over using docker-machine, but it will simplify working with volumes and allow you to test your deployment in a realistic environment.
|
14
|
+
|
15
|
+
### The Skeleton
|
data/Rakefile
ADDED
data/bin/console
ADDED
File without changes
|
data/bin/setup
ADDED
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'docker_compose_deploy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "docker_compose_deploy"
|
8
|
+
spec.version = DockerComposeDeploy::VERSION
|
9
|
+
spec.authors = ["Pete Kinnecom"]
|
10
|
+
spec.email = ["rubygems@k7u7.com"]
|
11
|
+
spec.licenses = ['MIT']
|
12
|
+
|
13
|
+
spec.summary = %q{This helps you deploy a website using docker-compose}
|
14
|
+
spec.homepage = "http://www.petekinnecom.net"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "thor", "~> 0.19"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
end
|
data/exe/dcd
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module DockerComposeDeploy
|
2
|
+
module Actions
|
3
|
+
class Backup < Struct.new(:shell)
|
4
|
+
|
5
|
+
def save
|
6
|
+
shell.notify("Backing up remote ./sites/data directory")
|
7
|
+
shell.notify("This may take a while...")
|
8
|
+
shell.run!("mkdir -p ./backups")
|
9
|
+
|
10
|
+
shell.ssh!("mkdir -p ./sites/backups")
|
11
|
+
shell.ssh!("tar -zcvf ./sites/backups/#{filename} ./sites/data")
|
12
|
+
shell.scp!("#{connection}:./sites/backups/#{filename}", "./backups/#{filename}")
|
13
|
+
shell.ssh!("rm ./sites/backups/#{filename}")
|
14
|
+
|
15
|
+
shell.notify "success"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def tmp_dir
|
21
|
+
@tmp_dir ||= "./tmp".tap do |dir|
|
22
|
+
FileUtils.mkdir_p(dir)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def filename
|
27
|
+
@filename ||= begin
|
28
|
+
time_str = Time.now.strftime("%Y-%m-%d_%H.%M.%S")
|
29
|
+
|
30
|
+
"backup__#{connection}__#{time_str}.tar.gz"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def tmp_file_path
|
35
|
+
File.join(tmp_dir, filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
def connection
|
39
|
+
DockerComposeDeploy.config.connection
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "docker_compose_deploy/actions/docker_compose/file"
|
2
|
+
|
3
|
+
module DockerComposeDeploy
|
4
|
+
module Actions
|
5
|
+
class Deployment < Struct.new(:ignore_pull_failures, :shell)
|
6
|
+
|
7
|
+
def create
|
8
|
+
shell.ssh!("mkdir -p ./sites")
|
9
|
+
shell.ssh!("rm -rf ./sites/config") # bin/deploy is irreversible :)
|
10
|
+
shell.scp!("./sites/config/", "#{connection}:./sites/config", "-r")
|
11
|
+
|
12
|
+
docker_compose.services.each do |service_name|
|
13
|
+
shell.ssh!("mkdir -p ./sites/data/#{service_name}")
|
14
|
+
shell.ssh!("mkdir -p ./sites/log/#{service_name}")
|
15
|
+
end
|
16
|
+
|
17
|
+
shell.scp!(docker_compose.path, "#{connection}:./docker-compose.yml")
|
18
|
+
shell.ssh!("docker-compose down")
|
19
|
+
shell.ssh!("docker-compose pull #{ignore_pull_failures_option}")
|
20
|
+
shell.ssh!("docker-compose up -d")
|
21
|
+
|
22
|
+
shell.notify "success"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def ignore_pull_failures_option
|
28
|
+
if ignore_pull_failures
|
29
|
+
"--ignore-pull-failures"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def docker_compose
|
34
|
+
@docker_compose ||= DockerCompose::File.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def connection
|
38
|
+
DockerComposeDeploy.config.connection
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module DockerComposeDeploy
|
4
|
+
module Actions
|
5
|
+
module DockerCompose
|
6
|
+
class File
|
7
|
+
attr_reader :path
|
8
|
+
def initialize(path="./docker-compose.yml")
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
def services
|
13
|
+
if !hash["services"]
|
14
|
+
raise "This is build to work with version 2 or 3 of docker-compose. It requires the 'services' top level key."
|
15
|
+
end
|
16
|
+
|
17
|
+
hash["services"].keys
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def hash
|
23
|
+
@hash ||= YAML.load(string)
|
24
|
+
end
|
25
|
+
|
26
|
+
def string
|
27
|
+
@string ||= ::File.read(@path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DockerComposeDeploy
|
2
|
+
module Actions
|
3
|
+
class Hosts < Struct.new(:shell)
|
4
|
+
|
5
|
+
def hijack
|
6
|
+
return unless DockerComposeDeploy.config.domains.any?
|
7
|
+
|
8
|
+
shell.notify("Creating hosts entries for test_domains")
|
9
|
+
|
10
|
+
host_entries = ["localhost", "vagrant"] + DockerComposeDeploy.config.domains
|
11
|
+
Tempfile.open do |f|
|
12
|
+
host_entries.each do |host|
|
13
|
+
f.puts("127.0.0.1 #{host}")
|
14
|
+
end
|
15
|
+
f.close
|
16
|
+
shell.scp!(f.path, "#{connection}:/tmp/hosts")
|
17
|
+
shell.ssh!("sudo mv /tmp/hosts /etc/hosts")
|
18
|
+
shell.notify("Wrote to /etc/hosts on test server:")
|
19
|
+
shell.puts(`cat #{f.path}`)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def connection
|
26
|
+
DockerComposeDeploy.config.connection
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module DockerComposeDeploy
|
5
|
+
module Actions
|
6
|
+
class Image < Struct.new(:name, :shell)
|
7
|
+
|
8
|
+
def push
|
9
|
+
shell.notify "Pushing #{name} to remote"
|
10
|
+
|
11
|
+
shell.run!("docker save #{name} > #{tmp_file_path}")
|
12
|
+
shell.run!("bzip2 #{tmp_file_path}")
|
13
|
+
shell.scp!("#{tmp_file_path}.bz2", "#{connection}:/tmp/")
|
14
|
+
shell.run!("rm #{tmp_file_path}.bz2")
|
15
|
+
shell.ssh!("docker load -i /tmp/#{filename}.bz2")
|
16
|
+
|
17
|
+
shell.notify "success"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def tmp_dir
|
23
|
+
@tmp_dir ||= "./tmp".tap do |dir|
|
24
|
+
FileUtils.mkdir_p(dir)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def filename
|
29
|
+
@filename ||= "#{name.gsub('/', '__')}_#{SecureRandom.hex}.tar"
|
30
|
+
end
|
31
|
+
|
32
|
+
def tmp_file_path
|
33
|
+
File.join(tmp_dir, filename)
|
34
|
+
end
|
35
|
+
|
36
|
+
def connection
|
37
|
+
DockerComposeDeploy.config.connection
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module DockerComposeDeploy
|
2
|
+
module Actions
|
3
|
+
class Server < Struct.new(:shell)
|
4
|
+
|
5
|
+
def provision
|
6
|
+
shell.notify("Provisioning: #{connection}")
|
7
|
+
shell.ssh!("sudo groupadd docker")
|
8
|
+
shell.ssh!("sudo usermod -aG docker $USER")
|
9
|
+
shell.ssh!("true", "-O exit") # resets the connection, so that our group changes take effect
|
10
|
+
|
11
|
+
shell.ssh!("wget -qO- https://get.docker.com/ | bash")
|
12
|
+
shell.ssh!("curl -L https://github.com/docker/compose/releases/download/1.11.1/run.sh > ./docker-compose")
|
13
|
+
shell.ssh!("chmod +x docker-compose")
|
14
|
+
shell.ssh!("sudo mv ./docker-compose /usr/local/bin/docker-compose")
|
15
|
+
shell.ssh!("docker-compose -v")
|
16
|
+
|
17
|
+
shell.notify "success"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def connection
|
23
|
+
DockerComposeDeploy.config.connection
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DockerComposeDeploy
|
2
|
+
module Actions
|
3
|
+
class Skeleton < Struct.new(:name, :shell)
|
4
|
+
|
5
|
+
def create
|
6
|
+
shell.notify("Creating new skeleton")
|
7
|
+
if File.exist?(name)
|
8
|
+
shell.warn("Directory or file: '#{name}' already exists. Exiting.")
|
9
|
+
exit(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
begin
|
13
|
+
Dir.mkdir(name)
|
14
|
+
Dir.rmdir(name)
|
15
|
+
rescue
|
16
|
+
shell.warn("Unable to make directory '#{name}'. Is it a valid directory name? Exiting.")
|
17
|
+
end
|
18
|
+
|
19
|
+
template_path = File.expand_path(File.join(__dir__, "../../../template"))
|
20
|
+
FileUtils.cp_r(template_path, name)
|
21
|
+
shell.notify("Created skeleton app in '#{name}'.")
|
22
|
+
shell.puts <<-MESSAGE
|
23
|
+
To see the skeleton app in action, run the following commands
|
24
|
+
|
25
|
+
# Move into the directory
|
26
|
+
1. cd #{name}
|
27
|
+
|
28
|
+
# Use vagrant to create the virtual machine for testing (it will open a window and will display Ubuntu's desktop)
|
29
|
+
2. vagrant up
|
30
|
+
|
31
|
+
# Install docker and docker-compose on the vagrant machine
|
32
|
+
3. dcd provision
|
33
|
+
|
34
|
+
# Deploy the skeleton app to the vagrant machine
|
35
|
+
4. dcd deploy
|
36
|
+
|
37
|
+
# See the server in action:
|
38
|
+
5. Open firefox on the vagrant machine and visit http://www.test
|
39
|
+
MESSAGE
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require "docker_compose_deploy/actions/deployment"
|
2
|
+
require "docker_compose_deploy/actions/server"
|
3
|
+
require "docker_compose_deploy/actions/backup"
|
4
|
+
require "docker_compose_deploy/actions/image"
|
5
|
+
require "docker_compose_deploy/actions/hosts"
|
6
|
+
require "docker_compose_deploy/actions/skeleton"
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "thor"
|
2
|
+
$LOAD_PATH.unshift(File.expand_path("..", __dir__))
|
3
|
+
require "docker_compose_deploy"
|
4
|
+
require "docker_compose_deploy/util/shell"
|
5
|
+
require "docker_compose_deploy/actions"
|
6
|
+
|
7
|
+
module DockerComposeDeploy
|
8
|
+
class CLI < Thor
|
9
|
+
desc "push IMAGE_NAME", "push IMAGE_NAME to configured host"
|
10
|
+
option :e, required: true, default: "test"
|
11
|
+
def push(*image_names)
|
12
|
+
DockerComposeDeploy.configure!(options[:e])
|
13
|
+
shell = Util::Shell.new
|
14
|
+
image_names.each do |image_name|
|
15
|
+
Actions::Image.new(image_name, shell).push
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "deploy", "deploy your docker-compose.yml to configured host"
|
20
|
+
option :e, required: true, default: "test"
|
21
|
+
def deploy
|
22
|
+
DockerComposeDeploy.configure!(options[:e])
|
23
|
+
ignore_pull_failures = DockerComposeDeploy.config.ignore_pull_failures
|
24
|
+
shell = Util::Shell.new
|
25
|
+
|
26
|
+
Actions::Deployment.new(ignore_pull_failures, shell).create
|
27
|
+
Actions::Hosts.new(shell).hijack
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "backup", "backup the data directory of the configured host"
|
31
|
+
option :e, required: true, default: "test"
|
32
|
+
def backup
|
33
|
+
DockerComposeDeploy.configure!(options[:e])
|
34
|
+
Actions::Backup.new(Util::Shell.new).save
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "provision", "provision the host to work with docker"
|
38
|
+
option :e, required: true, default: "test"
|
39
|
+
def provision
|
40
|
+
DockerComposeDeploy.configure!(options[:e])
|
41
|
+
Actions::Server.new(Util::Shell.new).provision
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "new", "create a new docker-compose server skeleton"
|
45
|
+
def new(name)
|
46
|
+
Actions::Skeleton.new(name, Util::Shell.new).create
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DockerComposeDeploy
|
2
|
+
module Util
|
3
|
+
module Color
|
4
|
+
CODES = {
|
5
|
+
red: 31,
|
6
|
+
green: 32,
|
7
|
+
yellow: 33,
|
8
|
+
blue: 34,
|
9
|
+
pink: 35,
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
CODES.each do |color, code|
|
13
|
+
self.send(:define_method, color) do |string|
|
14
|
+
colorize(string, code)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# colorization
|
21
|
+
def colorize(string, color_code)
|
22
|
+
"\e[#{color_code}m#{string}\e[0m"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'docker_compose_deploy/util/color'
|
2
|
+
|
3
|
+
module DockerComposeDeploy
|
4
|
+
module Util
|
5
|
+
class Shell
|
6
|
+
include Color
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
$stderr.sync = true
|
10
|
+
$stdout.sync = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(cmd)
|
14
|
+
puts blue(cmd)
|
15
|
+
IO.popen(cmd) do |io|
|
16
|
+
while (line = io.gets) do
|
17
|
+
puts line
|
18
|
+
end
|
19
|
+
end
|
20
|
+
$?
|
21
|
+
end
|
22
|
+
|
23
|
+
def run!(cmd)
|
24
|
+
if run(cmd) != 0
|
25
|
+
exit("\nCommand failed:\n#{cmd}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def warn(msg)
|
30
|
+
puts red(msg)
|
31
|
+
end
|
32
|
+
|
33
|
+
def notify(msg)
|
34
|
+
puts yellow(msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
def puts(msg)
|
38
|
+
Kernel.puts(msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
def exit(msg)
|
42
|
+
warn(msg)
|
43
|
+
Kernel.exit(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
def ssh(cmd)
|
47
|
+
run(ssh_cmd(cmd))
|
48
|
+
end
|
49
|
+
|
50
|
+
def ssh!(cmd, opts="")
|
51
|
+
run!(ssh_cmd(cmd, opts))
|
52
|
+
end
|
53
|
+
|
54
|
+
def scp!(src, dest, opts="")
|
55
|
+
run!("scp -F ~/.ssh/config -F ssh_config_overrides #{opts} #{src} #{dest} > /dev/tty")
|
56
|
+
end
|
57
|
+
|
58
|
+
def confirm?(question)
|
59
|
+
warn "#{question} [Yn]"
|
60
|
+
STDIN.gets.strip.downcase != 'n'
|
61
|
+
end
|
62
|
+
|
63
|
+
def ssh_cmd(cmd, opts)
|
64
|
+
"ssh -F ~/.ssh/config -F ssh_config_overrides #{opts} #{connection} '#{cmd}'"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def connection
|
70
|
+
DockerComposeDeploy.config.connection
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "docker_compose_deploy/version"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module DockerComposeDeploy
|
5
|
+
class << self
|
6
|
+
def config
|
7
|
+
@config || raise("Not configured")
|
8
|
+
end
|
9
|
+
|
10
|
+
def configure!(environment)
|
11
|
+
yaml = YAML.load(File.read("./config.yml"))
|
12
|
+
@config = Configuration.new(environment, yaml)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Configuration
|
17
|
+
def initialize(environment, yaml)
|
18
|
+
@environment = environment
|
19
|
+
@yaml = yaml
|
20
|
+
end
|
21
|
+
|
22
|
+
def ignore_pull_failures
|
23
|
+
config_block.fetch("ignore_pull_failures", false)
|
24
|
+
end
|
25
|
+
|
26
|
+
def connection
|
27
|
+
config_block["connection"] || raise("INVALID CONFIG: Environment '#{@environment}' does not specify a connection string in config.yml")
|
28
|
+
end
|
29
|
+
|
30
|
+
def domains
|
31
|
+
config_block.fetch("domains", [])
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def config_block
|
37
|
+
@yaml[@environment] || raise("INVALID ENVIRONMENT: Environment '#{@environment}' is not configured in config.yml")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/template/config.yml
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Environment configuration
|
2
|
+
#
|
3
|
+
# You can define as many "environments" as you like. I've found
|
4
|
+
# that I only need two. The "test" environment is the vagrant
|
5
|
+
# box, the "production" environment uses my virtual machine on
|
6
|
+
# DigitalOcean.
|
7
|
+
#
|
8
|
+
# When using the `dcd` command, you can specify the environment
|
9
|
+
# using the `-e` flag. Here is an example:
|
10
|
+
#
|
11
|
+
# dcd deploy -e production
|
12
|
+
#
|
13
|
+
# If the `-e` is not set, it will default to "test".
|
14
|
+
#
|
15
|
+
################################################################
|
16
|
+
#
|
17
|
+
# "connection": How we connect to the host machine
|
18
|
+
#
|
19
|
+
# For each, we must configure the connection string that we use
|
20
|
+
# to connect to the host using ssh. The "test" environment is
|
21
|
+
# already setup for the vagrant host. You need to configure the
|
22
|
+
# production environment.
|
23
|
+
#
|
24
|
+
################################################################
|
25
|
+
#
|
26
|
+
# "ignore_pull_failures": Pull Failures configuration
|
27
|
+
#
|
28
|
+
# For each environment we can also set the "ignore_pull_failures"
|
29
|
+
# flag. This flag is used when deploying your docker-compose.yml.
|
30
|
+
#
|
31
|
+
# We run `docker-compose pull` to pull down the latest
|
32
|
+
# images from hub.docker.com. If you have decided instead
|
33
|
+
# to push your images directly to your host (using
|
34
|
+
# `dcd push image_name`) then these images will fail to be pulled
|
35
|
+
# from hub.docker.com (since they were never put there).
|
36
|
+
#
|
37
|
+
# If images cannot be pulled, then `docker-compose pull` will
|
38
|
+
# consider this an error. Setting `ignore_pull_failures` to `true`
|
39
|
+
# will tell docker-compose to ignore any errors generated while
|
40
|
+
# pulling down the latest image.
|
41
|
+
#
|
42
|
+
# If you are using hub.docker.com, leave this as false.
|
43
|
+
#
|
44
|
+
# If you are using `dcd push image_name` then set this to true
|
45
|
+
#
|
46
|
+
################################################################
|
47
|
+
#
|
48
|
+
# "domains" => Urls to hijack on the host machine
|
49
|
+
#
|
50
|
+
# It can be tricky to ensure that the nginx configuration that
|
51
|
+
# your proxy is using is routing things to the correct docker
|
52
|
+
# container.
|
53
|
+
#
|
54
|
+
# In order to help test things on the vagrant machine, we add
|
55
|
+
# the listed domains to the /etc/hosts file of the machine.
|
56
|
+
# We can then use firefox on the vagrant machine to visit one
|
57
|
+
# of the domains and the request will be routed back to our
|
58
|
+
# nginx proxy.
|
59
|
+
#
|
60
|
+
# Add an entry here for each subdomain that you have on your
|
61
|
+
# production server. Notice how the three domains specified
|
62
|
+
# here are present in the sites/config/proxy/nginx.conf file.
|
63
|
+
#
|
64
|
+
# Note that you can specify any domain, but using the ".test"
|
65
|
+
# domain will keep things clear while testing.
|
66
|
+
#
|
67
|
+
# You should have no reason to add domains for your production
|
68
|
+
# server.
|
69
|
+
#
|
70
|
+
|
71
|
+
test:
|
72
|
+
connection: "vagrant@default"
|
73
|
+
ignore_pull_failures: false
|
74
|
+
domains:
|
75
|
+
- www.test
|
76
|
+
- site1.test
|
77
|
+
- site2.test
|
78
|
+
production:
|
79
|
+
connection: "user@yourserver"
|
80
|
+
ignore_pull_failures: false
|
@@ -0,0 +1,26 @@
|
|
1
|
+
version: '3'
|
2
|
+
services:
|
3
|
+
proxy:
|
4
|
+
image: nginx:1.11.10
|
5
|
+
command: ["nginx", "-c", "/mnt/config/nginx.conf", "-g", "daemon off;"]
|
6
|
+
volumes:
|
7
|
+
- ./sites/config/proxy:/mnt/config
|
8
|
+
- ./sites/data/proxy:/mnt/data
|
9
|
+
- ./sites/log/proxy:/mnt/log
|
10
|
+
ports:
|
11
|
+
- 80:80
|
12
|
+
depends_on:
|
13
|
+
- site1
|
14
|
+
- site2
|
15
|
+
site1:
|
16
|
+
image: petekinnecom/compose_deploy_site:1.0
|
17
|
+
volumes:
|
18
|
+
- ./sites/config/site1:/mnt/config
|
19
|
+
- ./sites/data/site1:/mnt/data
|
20
|
+
- ./sites/log/site1:/mnt/log
|
21
|
+
site2:
|
22
|
+
image: petekinnecom/compose_deploy_site:2.0
|
23
|
+
volumes:
|
24
|
+
- ./sites/config/site2:/mnt/config
|
25
|
+
- ./sites/data/site2:/mnt/data
|
26
|
+
- ./sites/log/site2:/mnt/log
|
@@ -0,0 +1,36 @@
|
|
1
|
+
events {
|
2
|
+
worker_connections 1024;
|
3
|
+
}
|
4
|
+
|
5
|
+
http {
|
6
|
+
access_log /mnt/log/access.log;
|
7
|
+
error_log /mnt/log/error.log;
|
8
|
+
|
9
|
+
server {
|
10
|
+
listen 80;
|
11
|
+
server_name www.*;
|
12
|
+
|
13
|
+
location / {
|
14
|
+
add_header Content-Type text/html;
|
15
|
+
return 200 "<a href='http://site1.test'>site1</a> or <a href='http://site2.test'>site2</a>";
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
server {
|
20
|
+
listen 80;
|
21
|
+
server_name site1.*;
|
22
|
+
|
23
|
+
location / {
|
24
|
+
proxy_pass http://site1/;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
server {
|
29
|
+
listen 80;
|
30
|
+
server_name site2.*;
|
31
|
+
|
32
|
+
location / {
|
33
|
+
proxy_pass http://site2/;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# This keeps the connection alive for two seconds
|
2
|
+
# after each usage. This improves performance.
|
3
|
+
|
4
|
+
Host *
|
5
|
+
ControlPath ~/.ssh/sock-%r@%h:%p
|
6
|
+
ControlMaster auto
|
7
|
+
ControlPersist 2
|
8
|
+
|
9
|
+
# The following configuration for the "default" host works
|
10
|
+
# with the default Vagrant file and vagrant 1.9.1. If you
|
11
|
+
# cannot connect using:
|
12
|
+
#
|
13
|
+
# ssh -F ssh_config_overrides vagrant@default
|
14
|
+
#
|
15
|
+
# Then replace this Host definition with the output from
|
16
|
+
# the command: `vagrant ssh-config`
|
17
|
+
|
18
|
+
Host default
|
19
|
+
HostName 127.0.0.1
|
20
|
+
User vagrant
|
21
|
+
Port 2222
|
22
|
+
UserKnownHostsFile /dev/null
|
23
|
+
StrictHostKeyChecking no
|
24
|
+
PasswordAuthentication no
|
25
|
+
IdentityFile .vagrant/machines/default/virtualbox/private_key
|
26
|
+
IdentitiesOnly yes
|
27
|
+
LogLevel FATAL
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docker_compose_deploy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pete Kinnecom
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.19'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.19'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.14'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- rubygems@k7u7.com
|
58
|
+
executables:
|
59
|
+
- dcd
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- bin/console
|
68
|
+
- bin/setup
|
69
|
+
- docker_compose_deploy.gemspec
|
70
|
+
- exe/dcd
|
71
|
+
- lib/docker_compose_deploy.rb
|
72
|
+
- lib/docker_compose_deploy/actions.rb
|
73
|
+
- lib/docker_compose_deploy/actions/backup.rb
|
74
|
+
- lib/docker_compose_deploy/actions/deployment.rb
|
75
|
+
- lib/docker_compose_deploy/actions/docker_compose/file.rb
|
76
|
+
- lib/docker_compose_deploy/actions/hosts.rb
|
77
|
+
- lib/docker_compose_deploy/actions/image.rb
|
78
|
+
- lib/docker_compose_deploy/actions/server.rb
|
79
|
+
- lib/docker_compose_deploy/actions/skeleton.rb
|
80
|
+
- lib/docker_compose_deploy/cli.rb
|
81
|
+
- lib/docker_compose_deploy/util/color.rb
|
82
|
+
- lib/docker_compose_deploy/util/shell.rb
|
83
|
+
- lib/docker_compose_deploy/version.rb
|
84
|
+
- template/Vagrantfile
|
85
|
+
- template/config.yml
|
86
|
+
- template/docker-compose.yml
|
87
|
+
- template/sites/config/proxy/nginx.conf
|
88
|
+
- template/ssh_config_overrides
|
89
|
+
homepage: http://www.petekinnecom.net
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.5.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: This helps you deploy a website using docker-compose
|
113
|
+
test_files: []
|
114
|
+
has_rdoc:
|