moby-derp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|