moby-derp 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 +6 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/CONTRIBUTING.md +14 -0
- data/LICENCE +674 -0
- data/README.md +231 -0
- data/bin/moby-derp +56 -0
- data/example.yml +297 -0
- data/lib/freedom_patches/docker/image.rb +23 -0
- data/lib/moby_derp/config_file.rb +33 -0
- data/lib/moby_derp/container.rb +245 -0
- data/lib/moby_derp/container_config.rb +377 -0
- data/lib/moby_derp/error.rb +15 -0
- data/lib/moby_derp/logging_helpers.rb +26 -0
- data/lib/moby_derp/moby_info.rb +12 -0
- data/lib/moby_derp/mount.rb +56 -0
- data/lib/moby_derp/pod.rb +89 -0
- data/lib/moby_derp/pod_config.rb +235 -0
- data/lib/moby_derp/system_config.rb +52 -0
- data/moby-derp.gemspec +39 -0
- data/smoke_tests/minimal.bats +18 -0
- data/smoke_tests/no_file.bats +7 -0
- data/smoke_tests/test_helper.bash +29 -0
- metadata +247 -0
data/README.md
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
This tool is designed to securely manage a group of related containers, known
|
2
|
+
colloquially as a ["pod"](https://kubernetes.io/docs/concepts/workloads/pods/pod/),
|
3
|
+
under the Moby container management system.
|
4
|
+
|
5
|
+
It has no aspirations to be a fully-fledged multi-host container orchestation system;
|
6
|
+
instead, it is simply a means to create and maintain a pod of containers.
|
7
|
+
|
8
|
+
The most common use-case for `moby-derp` is to allow unprivileged users to
|
9
|
+
define a pod, and then allow those users to execute `moby-derp` as a privileged
|
10
|
+
user via `sudo`. Since this removes the need for random users to have direct
|
11
|
+
control over the moby daemon, a lot of potential [privilege escalation
|
12
|
+
attacks](https://fosterelli.co/privilege-escalation-via-docker.html)
|
13
|
+
facilitated by moby's security model are thwarted.
|
14
|
+
|
15
|
+
|
16
|
+
# Installation
|
17
|
+
|
18
|
+
It's a gem:
|
19
|
+
|
20
|
+
gem install moby-derp
|
21
|
+
|
22
|
+
If you're the sturdy type that likes to run from git:
|
23
|
+
|
24
|
+
rake install
|
25
|
+
|
26
|
+
Or, if you've eschewed the convenience of Rubygems entirely, then you
|
27
|
+
presumably know what to do already.
|
28
|
+
|
29
|
+
|
30
|
+
# Usage
|
31
|
+
|
32
|
+
The main interface for `moby-derp` is the command-line tool of the same name.
|
33
|
+
It takes as its sole argument a YAML file containing a whole pile of information
|
34
|
+
about the pod and how you want the containers within it to be run. A very simple
|
35
|
+
example file might look like this:
|
36
|
+
|
37
|
+
publish:
|
38
|
+
- 80:80
|
39
|
+
containers:
|
40
|
+
nginx:
|
41
|
+
image: 'nginx:latest'
|
42
|
+
mounts:
|
43
|
+
- source: nginx
|
44
|
+
target: /etc/nginx
|
45
|
+
- source: content
|
46
|
+
target: /var/www
|
47
|
+
content_puller:
|
48
|
+
image: 'example/content_puller'
|
49
|
+
mounts:
|
50
|
+
- source: content
|
51
|
+
target: /puller
|
52
|
+
|
53
|
+
For full details on exactly what can be done using the pod configuration file,
|
54
|
+
please see [`example.yml`](example.yml), which is a heavily-commented example
|
55
|
+
of every possible configuration option that can be set.
|
56
|
+
|
57
|
+
Once you have a pod config, saved in, say, `my-pod.yml`, you can tell `moby-derp`
|
58
|
+
to run it:
|
59
|
+
|
60
|
+
moby-derp ./my-pod.yml
|
61
|
+
|
62
|
+
Often, however, you won't have the ability to contact the moby daemon directly,
|
63
|
+
so you'll run `moby-derp` via `sudo`:
|
64
|
+
|
65
|
+
sudo moby-derp ./my-pod.yml
|
66
|
+
|
67
|
+
Where this comes in handy is that `sudo` can be configured to restrict the
|
68
|
+
set of commands that a given user is allowed to run. So, for instance, if the
|
69
|
+
user who wants to run this pod is named `bob` on the system, I can put this
|
70
|
+
in my `/etc/sudoers`:
|
71
|
+
|
72
|
+
bob ALL=(root) NOPASSWD: /usr/local/bin/moby-derp */my-pod.yml
|
73
|
+
|
74
|
+
Then `bob` (and *only* `bob`) can run
|
75
|
+
|
76
|
+
sudo moby-derp ./my-pod.yml
|
77
|
+
|
78
|
+
The name of the pod is taken from the name of the file, with any extension
|
79
|
+
removed. This is used as the prefix for the name of all containers in the pod.
|
80
|
+
|
81
|
+
|
82
|
+
## System Configuration
|
83
|
+
|
84
|
+
Some aspects of `moby-derp`'s operation are security-sensitive, and thus shouldn't
|
85
|
+
be able to be modified by the ordinary user. There is a
|
86
|
+
system-wide configuration file for this purpose, by default located at
|
87
|
+
`/etc/moby-derp.yml`.
|
88
|
+
|
89
|
+
Its structure is quite simple. A full example looks like this:
|
90
|
+
|
91
|
+
mount_root: '/srv/docker'
|
92
|
+
port_whitelist:
|
93
|
+
80: web-server
|
94
|
+
443: web-server
|
95
|
+
25: mail-server
|
96
|
+
1337: bobblehead
|
97
|
+
|
98
|
+
The keys are:
|
99
|
+
|
100
|
+
* **`mount_root`**: the directory on disk where all mounts for all pods will
|
101
|
+
be stored. For security, the filesystem on which this location resides
|
102
|
+
should really be mounted `nosuid` and, if you can swing it, even `noexec`.
|
103
|
+
The directory specified by this option must already exist.
|
104
|
+
|
105
|
+
* **`port_whitelist`**: a map of port numbers and the pod which should be
|
106
|
+
allowed to map them. Any port which is not listed here cannot be explicitly
|
107
|
+
mapped by a pod, and only the pod named in the mapping can publish on the
|
108
|
+
specified port.
|
109
|
+
|
110
|
+
If you wish to modify the location of the `moby-derp` system-wide configuration
|
111
|
+
file, you can do so by setting the `MOBY_DERP_SYSTEM_CONFIG_FILE` environment
|
112
|
+
variable. Note, however, that it is a terrible idea to let ordinary users control
|
113
|
+
that environment variable, so if you want to set it, please write a small
|
114
|
+
wrapper script, like this:
|
115
|
+
|
116
|
+
#!/bin/sh
|
117
|
+
|
118
|
+
set -e
|
119
|
+
|
120
|
+
MOBY_DERP_SYSTEM_CONFIG_FILE=/opt/srv/etc/moby-derp/moby-derp.yaml
|
121
|
+
|
122
|
+
exec /usr/local/bin/moby-derp "$@"
|
123
|
+
|
124
|
+
You can also set other relevant environment variables, such as `DOCKER_HOST`,
|
125
|
+
in a like manner, if required.
|
126
|
+
|
127
|
+
|
128
|
+
## Running `moby-derp` as a non-root user
|
129
|
+
|
130
|
+
If you are properly cautious, it is a fine idea to not allow `moby-derp` itself
|
131
|
+
root access to the system. This is possible, although it comes with a few
|
132
|
+
caveats:
|
133
|
+
|
134
|
+
* The `sudoers` config needs to be adjusted appropriately, to specify the
|
135
|
+
user that you want to run `moby-derp` as;
|
136
|
+
|
137
|
+
* The system-wide configuration file needs to be readable by whatever user
|
138
|
+
you run `moby-derp` as;
|
139
|
+
|
140
|
+
* When running `moby-derp`, the user to run it as needs to be specified on
|
141
|
+
the command line, like so:
|
142
|
+
|
143
|
+
sudo -u moby-derper moby-derp ./my-pod.yml
|
144
|
+
|
145
|
+
* The user that runs `moby-derp` must have access to the Docker control socket;
|
146
|
+
by default that means making that user a member of the `docker` group;
|
147
|
+
|
148
|
+
* The user that runs `moby-derp` must have write access to the `mount_root`
|
149
|
+
directory, so it can create pod mount roots.
|
150
|
+
|
151
|
+
|
152
|
+
# Security
|
153
|
+
|
154
|
+
This section discusses the security model and guarantees of `moby-derp`. It
|
155
|
+
isn't necessary to simply use `moby-derp` in most circumstances.
|
156
|
+
|
157
|
+
The fundamental principle of `moby-derp` is that users are given control over
|
158
|
+
a certain portion of the container and filesystem namespace, by virtue of their
|
159
|
+
ability to run `moby-derp` with a specific filename -- and nothing more. The
|
160
|
+
containers that a user can modify, and the portions of the filesystem that they
|
161
|
+
can write files to, is strictly limited by the tool.
|
162
|
+
|
163
|
+
|
164
|
+
## Container namespace
|
165
|
+
|
166
|
+
All containers associated with a pod are named for the filename that is passed
|
167
|
+
to `moby-derp`. This means that, yes, different users need to use different
|
168
|
+
filenames. The benefit of this is that the `sudo` configuration becomes a lot
|
169
|
+
easier to audit -- the pod name is right there.
|
170
|
+
|
171
|
+
This means that no matter a user does, they cannot have any effect on any
|
172
|
+
container which is not named for the pod they're manipulating. There are also
|
173
|
+
safety valves around `moby-derp`-managed containers being labelled as such, so
|
174
|
+
that in the event that someone does inadvertently name a container in such a
|
175
|
+
way that it can be manipulated by another user via `moby-derp`, it should still
|
176
|
+
be safe from tampering.
|
177
|
+
|
178
|
+
|
179
|
+
## Filesystem
|
180
|
+
|
181
|
+
All references to the host side of mounts within the pod are made relative to
|
182
|
+
the pod mount root, which is a subdirectory under the directory specified
|
183
|
+
under the `mount_root` system configuration named for the pod. As one would
|
184
|
+
expect, attempts to use absolute paths, or parent directory references (via
|
185
|
+
`..`) will not be looked upon kindly.
|
186
|
+
|
187
|
+
To prevent attacks around modifying file permissions in the container and then
|
188
|
+
using that on the host to escalate privileges, it is *STRONGLY* recommended
|
189
|
+
that the filesystem which holds the `mount_root` be mounted `nosuid`, and even
|
190
|
+
`noexec` if that isn't going to get in the way of your use-case. You
|
191
|
+
can also use the `userns-remap` feature if that is compatible with your use
|
192
|
+
of Moby.
|
193
|
+
|
194
|
+
|
195
|
+
## Network ports
|
196
|
+
|
197
|
+
By default, `moby-derp` will not allow containers to publish to specific ports
|
198
|
+
on the host. The expectation is that network traffic will, for the most part,
|
199
|
+
rely on direct connection to containers, using either host-based proxies,
|
200
|
+
overlay networks, or new-fangled technologies like IPv6. This prevents
|
201
|
+
misbehaving pods from capturing ports intended for use by other pods. Pods can
|
202
|
+
still publish to ephemeral ports (using the `:containerPort` syntax, or
|
203
|
+
`publish_all: true`) if they wish.
|
204
|
+
|
205
|
+
If a pod *does* need to bind to a specific host port, then that pod/port pair
|
206
|
+
should be whitelisted in the system configuration file.
|
207
|
+
|
208
|
+
|
209
|
+
# Contributing
|
210
|
+
|
211
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
212
|
+
|
213
|
+
|
214
|
+
# Licence
|
215
|
+
|
216
|
+
Unless otherwise stated, everything in this repo is covered by the following
|
217
|
+
copyright notice:
|
218
|
+
|
219
|
+
Copyright (C) 2019 Matt Palmer <matt@hezmatt.org>
|
220
|
+
|
221
|
+
This program is free software: you can redistribute it and/or modify it
|
222
|
+
under the terms of the GNU General Public License version 3, as
|
223
|
+
published by the Free Software Foundation.
|
224
|
+
|
225
|
+
This program is distributed in the hope that it will be useful,
|
226
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
227
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
228
|
+
GNU General Public License for more details.
|
229
|
+
|
230
|
+
You should have received a copy of the GNU General Public License
|
231
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/bin/moby-derp
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "moby_derp/system_config"
|
4
|
+
require "moby_derp/pod_config"
|
5
|
+
require "moby_derp/pod"
|
6
|
+
|
7
|
+
require "docker-api"
|
8
|
+
|
9
|
+
if ARGV.length != 1
|
10
|
+
$stderr.puts "No config file specified"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
logger = Logger.new($stdout)
|
15
|
+
logger.formatter = ->(s, t, p, m) { "#{m}\n" }
|
16
|
+
|
17
|
+
case ENV["MOBY_DERP_LOG_LEVEL"]
|
18
|
+
when /\Adebug|info|warn|error\z/i
|
19
|
+
logger.level = Logger.const_get(ENV["MOBY_DERP_LOG_LEVEL"].upcase.to_sym)
|
20
|
+
when /\Atrace\z/i
|
21
|
+
logger.level = Logger::DEBUG
|
22
|
+
require "tracer"
|
23
|
+
Tracer.add_filter { |_e, _f, _l, _id, _b, klass, *_| klass.to_s =~ /MobyDerp/ }
|
24
|
+
Tracer.on
|
25
|
+
else
|
26
|
+
logger.level = Logger::INFO
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
system_config_file = ENV["MOBY_DERP_SYSTEM_CONFIG_FILE"] || "/etc/moby-derp.conf"
|
31
|
+
system_config = MobyDerp::SystemConfig.new(system_config_file, Docker.info, logger)
|
32
|
+
rescue MobyDerp::ConfigurationError => ex
|
33
|
+
$stderr.puts "There was an error reading the system config file #{system_config_file}: #{ex.message}"
|
34
|
+
exit 1
|
35
|
+
rescue Excon::Error::Socket
|
36
|
+
$stderr.puts "Could not connect to the Moby server. Is it running?"
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
pod_config = MobyDerp::PodConfig.new(ARGV.first, system_config)
|
42
|
+
rescue MobyDerp::ConfigurationError => ex
|
43
|
+
$stderr.puts "There was an error reading the pod config file #{ARGV.first}: #{ex.message}"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
pod = MobyDerp::Pod.new(pod_config)
|
48
|
+
|
49
|
+
begin
|
50
|
+
pod.run
|
51
|
+
rescue MobyDerp::Error => ex
|
52
|
+
$stderr.puts "There was an error derping #{pod.name}: #{ex.message}"
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
|
56
|
+
exit 0
|
data/example.yml
ADDED
@@ -0,0 +1,297 @@
|
|
1
|
+
# This is an example pod specification file for moby-derp. It contains all
|
2
|
+
# the possible configuration options, with comments describing their use.
|
3
|
+
#
|
4
|
+
# The name of a pod spec file is important, because the file name is used as
|
5
|
+
# the name of the pod to manage, with any extension removed. Because of the
|
6
|
+
# limitations on container names imposed by Moby, this file name must, thus,
|
7
|
+
# start with a alphanumeric character, and consist entirely of alphanumeric
|
8
|
+
# characters, underscores, and hyphens.
|
9
|
+
#
|
10
|
+
|
11
|
+
# SECTION 1: CONTAINERS
|
12
|
+
#
|
13
|
+
# This is really what we're all here for, so let's get straight into it.
|
14
|
+
#
|
15
|
+
containers:
|
16
|
+
# The containers section contains a map of container names to the
|
17
|
+
# configuration parameters of that container. Each container's name
|
18
|
+
# must consist entirely of alphanumeric characters, underscores, and
|
19
|
+
# hyphens.
|
20
|
+
#
|
21
|
+
flingle:
|
22
|
+
# The most important parameter for a container -- and, in fact,
|
23
|
+
# the *only* mandatory one -- is the container **image**. The
|
24
|
+
# value given here must either be a symbolic image reference
|
25
|
+
# (name[:tag][@digest]) or a full image ID, including the digest
|
26
|
+
# identifier (`sha256:xyzzy123`).
|
27
|
+
#
|
28
|
+
image: 'moby-derp/flingle:latest'
|
29
|
+
|
30
|
+
# By default, if a symbolic image spec is provided in the `image` option,
|
31
|
+
# `moby-derp` will pull that image and recreate the container if the image
|
32
|
+
# ID has changed from what is currently running. If, for some reason, you
|
33
|
+
# do *not* want this behaviour for a specific container, set this option to
|
34
|
+
# `false`.
|
35
|
+
#
|
36
|
+
# Note that, in all cases, if the image ID underlying a symbolic
|
37
|
+
# image spec changes in the local daemon's image store, the container will
|
38
|
+
# be restarted.
|
39
|
+
#
|
40
|
+
update_image: false
|
41
|
+
|
42
|
+
# Many moby images require a command, or at least command-line
|
43
|
+
# options, in order to run correctly. To do this, set this
|
44
|
+
# key to whatever you need to pass.
|
45
|
+
#
|
46
|
+
# You can specify the command as a string, or as an array of strings if you
|
47
|
+
# want to avoid a layer or two of shell quoting.
|
48
|
+
#
|
49
|
+
command: '--foo=bar --wombat'
|
50
|
+
|
51
|
+
# The 12-factor app concept says that all configuration should be passed
|
52
|
+
# via the environment. If that is your bag, then this section will make
|
53
|
+
# you very happy.
|
54
|
+
#
|
55
|
+
environment:
|
56
|
+
# The environment is specified as a map of variable name to variable
|
57
|
+
# values. For passing big strings, you may want to get familiar with
|
58
|
+
# YAML's many string quoting and escaping modes.
|
59
|
+
#
|
60
|
+
APP_ENV: production
|
61
|
+
# Embedding your private key like this isn't necessarily a particularly
|
62
|
+
# good idea, but as an example of where you might need multiline strings,
|
63
|
+
# it works very well.
|
64
|
+
#
|
65
|
+
PRIVATE_KEY: |
|
66
|
+
-----BEGIN PRIVATE KEY-----
|
67
|
+
AAAAsd...
|
68
|
+
-----END PRIVATE KEY-----
|
69
|
+
|
70
|
+
# Persisting data past the lifetime of a particular container is the job
|
71
|
+
# of mounts. Here you can specify filesystem locations on the host
|
72
|
+
# (relative to the pod's mount root) and where they should be
|
73
|
+
# mounted in the container.
|
74
|
+
#
|
75
|
+
# The list of mounts is an array of hashes, each of which specifies
|
76
|
+
# one mount.
|
77
|
+
#
|
78
|
+
mounts:
|
79
|
+
# The `source` parameter is a *relative* path (relative to the pod's
|
80
|
+
# mount root) on the host's filesystem. Typically it will be a
|
81
|
+
# single descriptive word, but you can delve into subdirectories if
|
82
|
+
# you so choose.
|
83
|
+
#
|
84
|
+
- source: app
|
85
|
+
# The `target` is an absolute path within the container, where the
|
86
|
+
# associated host directory should be mounted.
|
87
|
+
#
|
88
|
+
target: /app
|
89
|
+
|
90
|
+
- source: static-assets
|
91
|
+
target: /app/public
|
92
|
+
|
93
|
+
# By default, mounts are read-write -- that is, if a process in the
|
94
|
+
# container has the relevant permissions, files in the mount can
|
95
|
+
# be modified, created, and deleted. If you absolutely, positively
|
96
|
+
# want to make sure that can't happen, set `readonly: true`, and we'll
|
97
|
+
# tell Moby to make it so.
|
98
|
+
#
|
99
|
+
readonly: true
|
100
|
+
|
101
|
+
# Sometimes you need to add a label to a specific container.
|
102
|
+
# This is how you do that.
|
103
|
+
#
|
104
|
+
labels:
|
105
|
+
# It's very simple: `labelname: labelvalue`.
|
106
|
+
#
|
107
|
+
somelabel: 'Some mighty value'
|
108
|
+
|
109
|
+
# Mark the container's *root* filesystem as read-only. Not *typically*
|
110
|
+
# a good idea.
|
111
|
+
#
|
112
|
+
readonly: true
|
113
|
+
|
114
|
+
# Specify the signal that should be sent to the container in order to
|
115
|
+
# cause it to stop gracefully. Can be specified as a number, or a
|
116
|
+
# string with or without the leading `SIG`.
|
117
|
+
#
|
118
|
+
stop_signal: SIGQUIT
|
119
|
+
|
120
|
+
# How long, in seconds, to wait for the container to gracefully stop
|
121
|
+
# before whacking it with a `SIGKILL`.
|
122
|
+
#
|
123
|
+
stop_timeout: 42
|
124
|
+
|
125
|
+
# Adjust the container's restart policy.
|
126
|
+
#
|
127
|
+
restart: on-failure:42
|
128
|
+
|
129
|
+
# Here you can place limits on your containers, to prevent them
|
130
|
+
# accidentally blowing up the world. Note that, in keeping with
|
131
|
+
# moby-derp's philosophy of limited privilege, you can only reduce
|
132
|
+
# the limits on a container, not raise them above what you would
|
133
|
+
# get by default (a bit like ulimits for non-root users).
|
134
|
+
#
|
135
|
+
limits:
|
136
|
+
# How many CPUs' worth of CPU time to allow this container to
|
137
|
+
# use.
|
138
|
+
#
|
139
|
+
cpus: 1.75
|
140
|
+
|
141
|
+
# A relative "share" of CPU time, calculated as a ratio of the
|
142
|
+
# total CPU shares granted to all cgroups. The default of 1024
|
143
|
+
# is the maximum you can set.
|
144
|
+
#
|
145
|
+
cpu-shares: 72
|
146
|
+
|
147
|
+
# Set memory and swap limits.
|
148
|
+
#
|
149
|
+
# These two settings have complicated inter-relationships. You
|
150
|
+
# definitely want to refer to
|
151
|
+
# https://docs.docker.com/config/containers/resource_constraints/#--memory-swap-details
|
152
|
+
# before using these. You may also want to look at
|
153
|
+
# https://docs.docker.com/install/linux/linux-postinstall/#your-kernel-does-not-support-cgroup-swap-limit-capabilities
|
154
|
+
#
|
155
|
+
memory: 1G
|
156
|
+
memory-swap: 42M
|
157
|
+
|
158
|
+
# The "soft limit" for memory usage -- if your container's memory
|
159
|
+
# usage is above this limit, and the overall system is running low on
|
160
|
+
# memory, this container will be pressured to reduce its memory
|
161
|
+
# usage.
|
162
|
+
#
|
163
|
+
memory-reservation: 100M
|
164
|
+
|
165
|
+
# Increase a container's propensity to have its processes whacked by
|
166
|
+
# the OOM killer, if such a thing becomes necessary. The value must
|
167
|
+
# be in the range 0 to 1000.
|
168
|
+
#
|
169
|
+
oom-score-adj: 42
|
170
|
+
|
171
|
+
# Limit the number of processes this container is allowed to create.
|
172
|
+
#
|
173
|
+
pids: 65535
|
174
|
+
|
175
|
+
# The amount of shared memory the container is allowed to use.
|
176
|
+
#
|
177
|
+
shm-size: 42G
|
178
|
+
|
179
|
+
# Set ulimits.
|
180
|
+
#
|
181
|
+
# All of the below settings are related to ulimits, which are the
|
182
|
+
# old-school, but still surprisingly effective, version of resource
|
183
|
+
# limits, from before we had cgroups. All of the values take the
|
184
|
+
# form `<soft limit>[:<hard limit>]`, and if `<hard limit>` is not
|
185
|
+
# provided, it is set equal to the specified `<soft limit>`. The
|
186
|
+
# soft limit must be less than or equal to the hard limit.
|
187
|
+
#
|
188
|
+
# See `getrlimit`(2) for what each limit means, as well as
|
189
|
+
# https://docs.docker.com/engine/reference/commandline/#set-ulimits-in-container---ulimit
|
190
|
+
# for Moby-specific restrictions and caveats. As an additional
|
191
|
+
# undocumented caveat, if you want to set no limit for a resource,
|
192
|
+
# specify the string "unlimited".
|
193
|
+
#
|
194
|
+
# No value, for hard *or* soft limits, can be set higher than the
|
195
|
+
# hard limits for the `dockerd` process, although you won't know
|
196
|
+
# that you've broken the limits until `moby-derp` tries to start the
|
197
|
+
# container and the wheels fall off.
|
198
|
+
#
|
199
|
+
ulimit-core: 1:2
|
200
|
+
ulimit-cpu: 3:4
|
201
|
+
ulimit-data: 5:6
|
202
|
+
ulimit-fsize: 7:8
|
203
|
+
ulimit-memlock: 9:10
|
204
|
+
ulimit-msgqueue: 11:12
|
205
|
+
ulimit-nofile: 13:14
|
206
|
+
ulimit-rttime: 15:16
|
207
|
+
ulimit-stack: 17:18
|
208
|
+
|
209
|
+
# SECTION 2: POD-LEVEL CONFIGURATION
|
210
|
+
#
|
211
|
+
# The remainder of the configuration items in this file correspond to settings
|
212
|
+
# which apply to the pod -- either defaults for all containers in the pod, or
|
213
|
+
# else settings which only apply to the "root" container in the pod (the container
|
214
|
+
# which holds the networking, IPC, and PID namespaces).
|
215
|
+
|
216
|
+
# Set a custom hostname for the container.
|
217
|
+
#
|
218
|
+
# The default is `<podname>-<host hostname>`, which works surprisingly well
|
219
|
+
# in a majority of cases. It's certainly less wild than the Moby default
|
220
|
+
# of the short container ID.
|
221
|
+
#
|
222
|
+
hostname: bobtown
|
223
|
+
|
224
|
+
# Common environment which will apply to all containers.
|
225
|
+
#
|
226
|
+
# These environment variables will be set for all containers, including the
|
227
|
+
# pod "root" container. Individual containers can override the value for an
|
228
|
+
# environment variable, by setting their own value, but they *cannot* cause
|
229
|
+
# an environment variable to be unset.
|
230
|
+
#
|
231
|
+
common_environment:
|
232
|
+
# As is the case for container-level environment variables, each key/value
|
233
|
+
# pair in the map is one environment variable name to value mapping.
|
234
|
+
#
|
235
|
+
AWESOME: yes
|
236
|
+
|
237
|
+
# Common labels which will apply to all containers.
|
238
|
+
#
|
239
|
+
# These labels will be applied to every container in the pod, including the
|
240
|
+
# pod "root" container. Like common environment variables, an individual
|
241
|
+
# container can override the value of a common label, but cannot cause the
|
242
|
+
# label to be unset entirely.
|
243
|
+
#
|
244
|
+
common_labels:
|
245
|
+
mah_pod: is on fire
|
246
|
+
|
247
|
+
# Labels that *only* apply to the "root" container of the pod.
|
248
|
+
#
|
249
|
+
# Some labels, often those associated with a container's network config
|
250
|
+
# (like service discovery), should only be applied to the pod's "root"
|
251
|
+
# container. Those labels should be defined here.
|
252
|
+
#
|
253
|
+
root_labels:
|
254
|
+
service: over here
|
255
|
+
|
256
|
+
# Common mount definitions that should apply to all containers.
|
257
|
+
#
|
258
|
+
# If you have a mount that every container in the pod should have access
|
259
|
+
# to, you really don't want to have to specify it every time. Instead,
|
260
|
+
# you can put them here. The format is the same as the per-container
|
261
|
+
# `mounts` option.
|
262
|
+
#
|
263
|
+
common_mounts:
|
264
|
+
- source: app
|
265
|
+
target: /app
|
266
|
+
- source: static-assets
|
267
|
+
target: /app/public
|
268
|
+
readonly: true
|
269
|
+
|
270
|
+
# A list of ports in the pod to expose.
|
271
|
+
#
|
272
|
+
# Marking a port as "exposed" interacts with Moby's "publish all" option,
|
273
|
+
# as well as with service advertisement systems.
|
274
|
+
#
|
275
|
+
expose:
|
276
|
+
- 80
|
277
|
+
- 443
|
278
|
+
- 1337
|
279
|
+
|
280
|
+
# A list of port publishing specifications.
|
281
|
+
#
|
282
|
+
# If you wish to use Moby's port forward/proxying mechanisms, you do that by
|
283
|
+
# "publishing" the port(s) you want to use. Note that, to prevent errant pods
|
284
|
+
# from capturing ports they're not supposed to, by default pods can only publish
|
285
|
+
# to ephemeral ports (no `hostPort` specification). If a particular pod
|
286
|
+
# *should* be able to publish a specific host port, it needs to be whitelisted
|
287
|
+
# in the system-wide configuration (see the `port_whitelist` documentation
|
288
|
+
# in the `moby-derp` README).
|
289
|
+
#
|
290
|
+
publish:
|
291
|
+
- :80
|
292
|
+
- :1234-1237
|
293
|
+
|
294
|
+
# If you have a burning desire to have all exposed ports automatically published
|
295
|
+
# to (not-so-)randomly chosen ephemeral ports, you can set this option to `true`.
|
296
|
+
#
|
297
|
+
publish_all: true
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Docker
|
2
|
+
class Image
|
3
|
+
# https://github.com/docker/distribution/blob/master/reference/reference.go
|
4
|
+
# as at 2019-04-23
|
5
|
+
DIGEST_HEX = /[0-9a-fA-F]{32,}/
|
6
|
+
DIGEST_ALGORITHM_COMPONENT = /[A-Za-z][A-Za-z0-9]*/
|
7
|
+
DIGEST_ALGORITHM_SEPARATOR = /[+._-]/
|
8
|
+
DIGEST_ALGORITHM = /#{DIGEST_ALGORITHM_COMPONENT}(#{DIGEST_ALGORITHM_SEPARATOR}#{DIGEST_ALGORITHM_COMPONENT})*/
|
9
|
+
DIGEST = /#{DIGEST_ALGORITHM}:#{DIGEST_HEX}/
|
10
|
+
|
11
|
+
TAG = /[\w][\w.-]{0,127}/
|
12
|
+
|
13
|
+
SEPARATOR = /[_.]|__|[-]*/
|
14
|
+
ALPHANUMERIC = /[a-z0-9]+/
|
15
|
+
PATH_COMPONENT = /#{ALPHANUMERIC}(#{SEPARATOR}#{ALPHANUMERIC})*/
|
16
|
+
PORT_NUMBER = /\d+/
|
17
|
+
DOMAIN_COMPONENT = /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
18
|
+
DOMAIN = /#{DOMAIN_COMPONENT}(\.#{DOMAIN_COMPONENT})*(:#{PORT_NUMBER})?/
|
19
|
+
NAME = /(#{DOMAIN}\/)?#{PATH_COMPONENT}(\/#{PATH_COMPONENT})*/
|
20
|
+
IMAGE_REFERENCE = /\A#{NAME}(:#{TAG})?(@#{DIGEST})?\z/
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative "./error"
|
2
|
+
require_relative "./logging_helpers"
|
3
|
+
|
4
|
+
require "safe_yaml"
|
5
|
+
|
6
|
+
module MobyDerp
|
7
|
+
class ConfigFile
|
8
|
+
include LoggingHelpers
|
9
|
+
|
10
|
+
attr_reader :logger
|
11
|
+
|
12
|
+
def initialize(filename)
|
13
|
+
begin
|
14
|
+
@logger.debug(logloc) { "Reading configuration file #{filename}" }
|
15
|
+
@config = SafeYAML.load(File.read(filename))
|
16
|
+
rescue Errno::ENOENT
|
17
|
+
raise ConfigurationError,
|
18
|
+
"file does not exist"
|
19
|
+
rescue Errno::EPERM
|
20
|
+
raise ConfigurationError,
|
21
|
+
"cannot read file"
|
22
|
+
rescue Psych::SyntaxError => ex
|
23
|
+
raise ConfigurationError,
|
24
|
+
"invalid YAML syntax: #{ex.message}"
|
25
|
+
end
|
26
|
+
|
27
|
+
unless @config.is_a?(Hash)
|
28
|
+
raise ConfigurationError,
|
29
|
+
"invalid file contents -- must be a map"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|