docker-compose 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +43 -31
- data/lib/docker/compose/mapper.rb +4 -11
- data/lib/docker/compose/rake_tasks.rb +48 -63
- data/lib/docker/compose/shell_printer.rb +21 -0
- data/lib/docker/compose/shell_printer/fish.rb +16 -0
- data/lib/docker/compose/shell_printer/posix.rb +32 -0
- data/lib/docker/compose/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04a52fb98e79311b5e3c771d24d41d434ab08e53
|
4
|
+
data.tar.gz: d1a04e25f5164edff5e2651ceed331fd58a20eb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52a9df711b6120701e3359fb30c3b22bc3c87abaa7823724c39e0efb462bc288b091efbce6eb77561b42f0ab112b9ea5568ac856de18ac7511d5a08292d60c30
|
7
|
+
data.tar.gz: ecd93e2c5c33b10acde0b8bd7c15c025676a53ff43f5b5df020e07f103961ccd5833e2096e965bd0766be2f768d0abdcb55b0b0ccab27572411f8f6fa07ec7e4
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
0.6
|
2
|
+
---
|
3
|
+
|
4
|
+
#### Interface-breaking changes
|
5
|
+
|
6
|
+
- Replaced `docker:compose:server` Rake task with more general `docker:compose:host`
|
7
|
+
- Replaced `server_env` option with `host_env`
|
8
|
+
- Replaced `extra_server_env` option with `extra_host_env`
|
9
|
+
- Stopped mapping values in `extra_host_env`; they are now exported verbatim
|
10
|
+
|
11
|
+
#### New features
|
12
|
+
|
13
|
+
Produce `docker:compose:env` output that is compatible with user's login shell.
|
14
|
+
|
15
|
+
0.5
|
16
|
+
---
|
17
|
+
|
18
|
+
Initial public release of prototype. Features work well, but there is no test
|
19
|
+
coverage.
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ In addition to wrapping the CLI, this gem provides an environment-variable mappi
|
|
7
7
|
feature that allows you to export environment variables into your _host_ that point
|
8
8
|
to network services exposed by containers. This allows you to run an application on
|
9
9
|
your host for quicker and easier development, but run all of its architectural
|
10
|
-
dependencies -- database, cache, adjacent
|
10
|
+
dependencies -- database, cache, adjacent services -- in containers. The
|
11
11
|
dependencies can even be running on another machine, e.g. a cloud instance or a
|
12
12
|
container cluster, provided your development machine has TCP connectivity on every
|
13
13
|
port exposed by a container.
|
@@ -62,29 +62,26 @@ end
|
|
62
62
|
```
|
63
63
|
|
64
64
|
Notice that `rake -T` now has a few additional tasks for invoking gem
|
65
|
-
functionality. You can `docker:compose:env`
|
66
|
-
|
67
|
-
`docker:compose:stop` to start and stop containers.
|
65
|
+
functionality. You can `docker:compose:env` print shell exports for
|
66
|
+
host-to-container environment mapping, or you can `docker:compose:host[foo]`.
|
68
67
|
|
69
|
-
|
70
|
-
and stop containers, but the gem provides some env-substitution functionality
|
71
|
-
for your YML files that will be built into docker-compose 1.5 but is not
|
72
|
-
released yet. If your YML contains `${ENV}` references, i.e. in order to
|
73
|
-
point your containers at network services running on the host, then you must
|
74
|
-
invoke docker-compose through Rake in order to peform the substitution.
|
68
|
+
### Hosting a Command
|
75
69
|
|
76
|
-
|
70
|
+
To run a process on your host and allow it to talk to containers, use
|
71
|
+
the `docker:compose:host` task. For example, I could enter a shell
|
72
|
+
with `rake docker:compose:host[bash]`.
|
73
|
+
|
74
|
+
Before "hosting" your command, the Rake task export ssome environment
|
75
|
+
variables that your command can use to discover services running in
|
76
|
+
containers. Your Rakefile specifies which variables your app needs
|
77
|
+
(the `host_env` option) and which container information each variable should
|
78
|
+
map to.
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
allows you to run the app on your host (for easier debugging and code editing)
|
82
|
-
but let it communicate with services running inside containers.
|
80
|
+
By hosting commands, you benefit from easier debugging and code editing of
|
81
|
+
the app you're working on, but still get to rely on containers to provide
|
82
|
+
the companion services your app requires to run.
|
83
83
|
|
84
|
-
|
85
|
-
are actually reachable at; the heuristic works regardless whether you are
|
86
|
-
running "bare" docker daemon on localhost, communicating with a docker-machine
|
87
|
-
instance, or even using a cloud-hosted docker machine!
|
84
|
+
### Mapping container IPs and ports
|
88
85
|
|
89
86
|
As a trivial example, let's say that your `docker-compose.yml` contains one
|
90
87
|
service, the database that your app needs in order to run.
|
@@ -101,30 +98,27 @@ db:
|
|
101
98
|
```
|
102
99
|
|
103
100
|
Your app needs two inputs, `DATABASE_HOST` and `DATABASE_PORT`. You can specify
|
104
|
-
this
|
101
|
+
this with the host_env option of the Rake task:
|
105
102
|
|
106
103
|
```ruby
|
107
104
|
Docker::Compose::RakeTasks.new do |tasks|
|
108
|
-
tasks.
|
109
|
-
'DATABASE_HOST' => 'db:[3306]'
|
110
|
-
'DATABASE_PORT' => '[db]:3306'
|
105
|
+
tasks.host_env = {
|
106
|
+
'DATABASE_HOST' => 'db:[3306]',
|
107
|
+
'DATABASE_PORT' => '[db]:3306',
|
111
108
|
}
|
112
109
|
end
|
113
110
|
```
|
114
111
|
|
115
|
-
(If I had a `DATABASE_URL` input, I could provide a URL such as
|
116
|
-
`mysql://db/myapp_development`; Docker::Compose would parse the URL and replace
|
117
|
-
the hostname and port appropriately.)
|
118
|
-
|
119
112
|
Now, I can run my services, ask Docker::Compose to map the environment values
|
120
113
|
to the actual IP and port that `db` has been published to, and run my app:
|
121
114
|
|
122
115
|
```bash
|
116
|
+
# First, bring up the containers we will be interested in
|
123
117
|
user@machine$ docker-compose up -d
|
124
118
|
|
125
|
-
#
|
126
|
-
# export DATABASE_HOST=127.0.0.1
|
127
|
-
# export DATABASE_PORT=34387
|
119
|
+
# The rake task prints bash code resembling the following:
|
120
|
+
# export DATABASE_HOST='127.0.0.1'
|
121
|
+
# export DATABASE_PORT='34387'
|
128
122
|
# We eval it, which makes the variables available to our shell and to all
|
129
123
|
# subprocesses.
|
130
124
|
user@machine$ eval "$(bundle exec rake docker:compose:env)"
|
@@ -132,6 +126,24 @@ user@machine$ eval "$(bundle exec rake docker:compose:env)"
|
|
132
126
|
user@machine$ bundle exec rackup
|
133
127
|
```
|
134
128
|
|
129
|
+
The `host_env` option also handles substitution of URLs, and arrays of values
|
130
|
+
(which are serialized back to the environment as JSON)
|
131
|
+
For example:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
tasks.host_env = {
|
135
|
+
'DATABASE_URL' => 'mysql://db:3306/myapp_development',
|
136
|
+
'MIXED_FRUIT' => ['db:[3306]', '[db]:3306']
|
137
|
+
}
|
138
|
+
```
|
139
|
+
|
140
|
+
This would result in the following exports:
|
141
|
+
|
142
|
+
```bash
|
143
|
+
export DATABASE_URL='mysql://127.0.0.1:34387/myapp_development'
|
144
|
+
export MIXED_FRUIT='["127.0.0.1", "34387"]'
|
145
|
+
```
|
146
|
+
|
135
147
|
To learn more about mapping, read the class documentation for
|
136
148
|
`Docker::Compose::Mapper`.
|
137
149
|
|
@@ -15,11 +15,10 @@ module Docker::Compose
|
|
15
15
|
# Instantiate a mapper; map some environment variables; yield to caller for
|
16
16
|
# additional processing.
|
17
17
|
#
|
18
|
-
# @param [Boolean] strict
|
19
18
|
# @param [Session] session
|
20
19
|
# @param [NetInfo] net_info
|
21
20
|
# @yield yields with each substituted (key, value) pair
|
22
|
-
def self.map(env,
|
21
|
+
def self.map(env, session:Session.new, net_info:NetInfo.new)
|
23
22
|
# TODO: encapsulate this trickiness better ... inside NetInfo perhaps?
|
24
23
|
docker_host = ENV['DOCKER_HOST']
|
25
24
|
if docker_host.nil? || docker_host =~ /^(\/|unix|file)/
|
@@ -32,7 +31,7 @@ module Docker::Compose
|
|
32
31
|
override_host = net_info.docker_routable_ip
|
33
32
|
end
|
34
33
|
|
35
|
-
mapper = self.new(session, override_host
|
34
|
+
mapper = self.new(session, override_host)
|
36
35
|
env.each_pair do |k, v|
|
37
36
|
begin
|
38
37
|
v = mapper.map(v)
|
@@ -47,13 +46,9 @@ module Docker::Compose
|
|
47
46
|
# @param [Docker::Compose::Session] session
|
48
47
|
# @param [String] override_host forcible address or DNS hostname to use;
|
49
48
|
# leave nil to trust docker-compose output.
|
50
|
-
|
51
|
-
# syntax is passed to #map; if false, simply return unrecognized
|
52
|
-
# values without substituting anything
|
53
|
-
def initialize(session, override_host=nil, strict:true)
|
49
|
+
def initialize(session, override_host=nil)
|
54
50
|
@session = session
|
55
51
|
@override_host = override_host
|
56
|
-
@strict = strict
|
57
52
|
end
|
58
53
|
|
59
54
|
# Substitute service hostnames and ports that appear in a URL or a
|
@@ -133,10 +128,8 @@ module Docker::Compose
|
|
133
128
|
host, port = host_and_port(pair.first, pair.last)
|
134
129
|
return "#{host}:#{port}"
|
135
130
|
end
|
136
|
-
elsif @strict
|
137
|
-
raise BadSubstitution, "Can't understand '#{value}'"
|
138
131
|
else
|
139
|
-
|
132
|
+
raise BadSubstitution, "Can't understand '#{value}'"
|
140
133
|
end
|
141
134
|
end
|
142
135
|
end
|
@@ -5,6 +5,9 @@ require 'shellwords'
|
|
5
5
|
# In case this file is required directly
|
6
6
|
require 'docker/compose'
|
7
7
|
|
8
|
+
# Only used here, so only required here
|
9
|
+
require 'docker/compose/shell_printer'
|
10
|
+
|
8
11
|
module Docker::Compose
|
9
12
|
class RakeTasks < Rake::TaskLib
|
10
13
|
# Set the directory in which docker-compose commands will be run. Default
|
@@ -17,32 +20,33 @@ module Docker::Compose
|
|
17
20
|
# @return [String]
|
18
21
|
attr_accessor :file
|
19
22
|
|
20
|
-
# Provide a mapping of environment variables that should be set in
|
21
|
-
# _host_
|
23
|
+
# Provide a mapping of environment variables that should be set in
|
24
|
+
# _host_ processes, e.g. when running docker:compose:env or
|
25
|
+
# docker:compose:host.
|
26
|
+
#
|
22
27
|
# The values of the environment variables can refer to names of services
|
23
|
-
# and ports defined in the docker-compose file, and this gem will
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
28
|
+
# and ports defined in the docker-compose file, and this gem will substitute
|
29
|
+
# the actual IP and port that the containers are reachable on. This allows
|
30
|
+
# commands invoked via "docker:compose:host" to reach services running
|
31
|
+
# inside containers.
|
27
32
|
#
|
28
33
|
# @see Docker::Compose::Mapper for information about the substitution syntax
|
29
|
-
attr_accessor :
|
30
|
-
|
31
|
-
# Extra environment variables
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# location of a container; they are simply extra environment values that are
|
35
|
-
# useful to change the server's behavior when it runs in cooperation
|
36
|
-
# with containers.
|
34
|
+
attr_accessor :host_env
|
35
|
+
|
36
|
+
# Extra environment variables to set before invoking host processes. These
|
37
|
+
# are set _in addition_ to server_env, but are not substituted in any way
|
38
|
+
# and must not contain any service information.
|
37
39
|
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
attr_accessor :
|
40
|
+
# Extra host env should be disjoint from host_env; if there is overlap
|
41
|
+
# between the two, then extra_host_env will "win."
|
42
|
+
attr_accessor :extra_host_env
|
41
43
|
|
42
|
-
#
|
43
|
-
# This is
|
44
|
-
#
|
45
|
-
|
44
|
+
# Services to bring up with `docker-compose up` before running any hosted
|
45
|
+
# command. This is useful if your `docker-compose.yml` contains a service
|
46
|
+
# definition for the app you will be hosting; if you host the app, you
|
47
|
+
# want to specify all of the _other_ services, but not the app itself, since
|
48
|
+
# that will run on the host.
|
49
|
+
attr_accessor :host_services
|
46
50
|
|
47
51
|
# Namespace to define the rake tasks under. Defaults to "docker:compose'.
|
48
52
|
attr_accessor :rake_namespace
|
@@ -53,14 +57,15 @@ module Docker::Compose
|
|
53
57
|
def initialize
|
54
58
|
self.dir = Rake.application.original_dir
|
55
59
|
self.file = 'docker-compose.yml'
|
56
|
-
self.
|
57
|
-
self.
|
60
|
+
self.host_env = {}
|
61
|
+
self.extra_host_env = {}
|
58
62
|
self.rake_namespace = 'docker:compose'
|
59
63
|
yield self if block_given?
|
60
64
|
|
61
65
|
@shell = Backticks::Runner.new
|
62
66
|
@session = Docker::Compose::Session.new(@shell, dir:dir, file:file)
|
63
67
|
@net_info = Docker::Compose::NetInfo.new
|
68
|
+
@shell_printer = Docker::Compose::ShellPrinter.new
|
64
69
|
|
65
70
|
@shell.interactive = true
|
66
71
|
|
@@ -73,41 +78,22 @@ module Docker::Compose
|
|
73
78
|
task :env do
|
74
79
|
@shell.interactive = false # suppress useless 'port' output
|
75
80
|
|
76
|
-
if
|
77
|
-
|
78
|
-
# environment _and_ print bash export commands to stdout.
|
79
|
-
# Also print usage hints if user invoked rake directly vs.
|
80
|
-
# eval'ing it's output
|
81
|
-
print_usage
|
82
|
-
export_env(print:true)
|
83
|
-
else
|
84
|
-
# This task is a dependency of something else; just export the
|
85
|
-
# environment variables for use in-process by other Rake tasks.
|
86
|
-
export_env(print:false)
|
87
|
-
end
|
81
|
+
print_usage if STDOUT.tty?
|
82
|
+
export_env(print:true)
|
88
83
|
|
89
84
|
@shell.interactive = true
|
90
85
|
end
|
91
86
|
|
92
|
-
desc '
|
93
|
-
task :
|
94
|
-
only = (ENV['ONLY'] || '').split(',').compact.uniq
|
95
|
-
@session.up(*only, detached:true)
|
96
|
-
end
|
97
|
-
|
98
|
-
desc 'Tail logs of all running services'
|
99
|
-
task :logs do
|
100
|
-
@session.logs
|
101
|
-
end
|
87
|
+
desc 'Run command on host, linked to services in containers'
|
88
|
+
task :host, [:command] => ['docker:compose:env'] do |task, args|
|
102
89
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
90
|
+
if self.host_services
|
91
|
+
@session.up(*self.host_services, detached:true)
|
92
|
+
else
|
93
|
+
@session.up(detached:true)
|
94
|
+
end
|
107
95
|
|
108
|
-
|
109
|
-
task :server => ['docker:compose:up', 'docker:compose:env'] do
|
110
|
-
exec(self.server)
|
96
|
+
exec(args[:command])
|
111
97
|
end
|
112
98
|
end
|
113
99
|
end
|
@@ -116,17 +102,14 @@ module Docker::Compose
|
|
116
102
|
# published by docker-compose services. Optionally also print bash export
|
117
103
|
# statements so this information can be made available to a user's shell.
|
118
104
|
private def export_env(print:)
|
119
|
-
Docker::Compose::Mapper.map(self.
|
105
|
+
Docker::Compose::Mapper.map(self.host_env,
|
120
106
|
session:@session,
|
121
107
|
net_info:@net_info) do |k, v|
|
122
108
|
ENV[k] = serialize_for_env(v)
|
123
109
|
print_env(k, ENV[k]) if print
|
124
110
|
end
|
125
111
|
|
126
|
-
|
127
|
-
strict:false,
|
128
|
-
session:@session,
|
129
|
-
net_info:@net_info) do |k, v|
|
112
|
+
self.extra_host_env.each do |k, v|
|
130
113
|
ENV[k] = serialize_for_env(v)
|
131
114
|
print_env(k, ENV[k]) if print
|
132
115
|
end
|
@@ -148,19 +131,21 @@ module Docker::Compose
|
|
148
131
|
end
|
149
132
|
end
|
150
133
|
|
151
|
-
# Print
|
134
|
+
# Print an export or unset statement suitable for user's shell
|
152
135
|
private def print_env(k, v)
|
153
136
|
if v
|
154
|
-
puts
|
137
|
+
puts @shell_printer.export(k, v)
|
155
138
|
else
|
156
|
-
puts
|
139
|
+
puts @shell_printer.unset(k)
|
157
140
|
end
|
158
141
|
end
|
159
142
|
|
143
|
+
|
160
144
|
private def print_usage
|
161
|
-
|
162
|
-
|
163
|
-
puts
|
145
|
+
command = "rake #{rake_namespace}:env"
|
146
|
+
command = "bundle exec " + command if defined?(Bundler)
|
147
|
+
puts @shell_printer.comment('To export these variables to your shell, run:')
|
148
|
+
puts @shell_printer.comment(@shell_printer.eval_output(command))
|
164
149
|
end
|
165
150
|
end
|
166
151
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'etc'
|
2
|
+
|
3
|
+
module Docker::Compose
|
4
|
+
module ShellPrinter
|
5
|
+
def self.new
|
6
|
+
shell = Etc.getpwuid(Process.uid).shell
|
7
|
+
basename = File.basename(shell)
|
8
|
+
|
9
|
+
# Crappy titleize (bash -> Bash)
|
10
|
+
basename[0] = basename[0].upcase
|
11
|
+
|
12
|
+
# Find adapter class named after shell; default to posix if nothing found
|
13
|
+
klass = const_get(basename.to_sym) rescue Posix
|
14
|
+
|
15
|
+
klass.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require_relative 'shell_printer/posix'
|
21
|
+
require_relative 'shell_printer/fish'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Docker::Compose::ShellPrinter
|
2
|
+
# Printer that works with the Friendly Interactive Shell (fish).
|
3
|
+
class Fish < Posix
|
4
|
+
def eval_output(command)
|
5
|
+
format('eval (%s)', command)
|
6
|
+
end
|
7
|
+
|
8
|
+
def export(name, value)
|
9
|
+
format('set -gx %s %s; ', name, single_quoted_escaped(value))
|
10
|
+
end
|
11
|
+
|
12
|
+
def unset(name)
|
13
|
+
format('set -ex %s; ', name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Docker::Compose::ShellPrinter
|
2
|
+
# Printer that works with any POSIX-compliant shell e.g. sh, bash, zsh
|
3
|
+
class Posix
|
4
|
+
def comment(value)
|
5
|
+
format('# %s', value)
|
6
|
+
end
|
7
|
+
|
8
|
+
def eval_output(command)
|
9
|
+
format('eval "$(%s)"', command)
|
10
|
+
end
|
11
|
+
|
12
|
+
def export(name, value)
|
13
|
+
format('export %s=%s', name, single_quoted_escaped(value))
|
14
|
+
end
|
15
|
+
|
16
|
+
def unset(name)
|
17
|
+
format('unset %s', name)
|
18
|
+
end
|
19
|
+
|
20
|
+
protected def single_quoted_escaped(value)
|
21
|
+
# "escape" any occurrences of ' in value by closing the single-quoted
|
22
|
+
# string, concatenating a single backslash-escaped ' character, and reopening
|
23
|
+
# the single-quoted string.
|
24
|
+
#
|
25
|
+
# This relies on the shell's willingness to concatenate adjacent string
|
26
|
+
# literals. Tested under sh, bash and zsh; should work elsewhere.
|
27
|
+
escaped = value.gsub("'") { "'\\''" }
|
28
|
+
|
29
|
+
"'#{escaped}'"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker-compose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04
|
11
|
+
date: 2016-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backticks
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- ".rspec"
|
79
79
|
- ".ruby-version"
|
80
80
|
- ".travis.yml"
|
81
|
+
- CHANGELOG.md
|
81
82
|
- CODE_OF_CONDUCT.md
|
82
83
|
- Gemfile
|
83
84
|
- LICENSE.txt
|
@@ -92,6 +93,9 @@ files:
|
|
92
93
|
- lib/docker/compose/net_info.rb
|
93
94
|
- lib/docker/compose/rake_tasks.rb
|
94
95
|
- lib/docker/compose/session.rb
|
96
|
+
- lib/docker/compose/shell_printer.rb
|
97
|
+
- lib/docker/compose/shell_printer/fish.rb
|
98
|
+
- lib/docker/compose/shell_printer/posix.rb
|
95
99
|
- lib/docker/compose/version.rb
|
96
100
|
homepage: https://github.com/xeger/docker-compose
|
97
101
|
licenses:
|