Apache Mesos
docker.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __DOCKER_HPP__
18 #define __DOCKER_HPP__
19 
20 #include <list>
21 #include <map>
22 #include <string>
23 
24 #include <process/future.hpp>
25 #include <process/owned.hpp>
26 #include <process/subprocess.hpp>
27 
28 #include <stout/duration.hpp>
29 #include <stout/json.hpp>
30 #include <stout/none.hpp>
31 #include <stout/nothing.hpp>
32 #include <stout/option.hpp>
33 #include <stout/path.hpp>
34 #include <stout/version.hpp>
35 
36 #include <stout/os/rm.hpp>
37 
38 #include "mesos/resources.hpp"
39 
40 #include "messages/flags.hpp"
41 
42 // OS-specific default prefix to be used for the DOCKER_HOST environment
43 // variable. Note that on Linux, the default prefix is the only prefix
44 // available; only Windows supports multiple prefixes.
45 // TODO(hausdorff): Add support for the Windows `tcp://` prefix as well.
46 #ifdef __WINDOWS__
47 constexpr char DEFAULT_DOCKER_HOST_PREFIX[] = "npipe://";
48 #else
49 constexpr char DEFAULT_DOCKER_HOST_PREFIX[] = "unix://";
50 #endif // __WINDOWS__
51 
52 // Abstraction for working with Docker (modeled on CLI).
53 //
54 // TODO(benh): Make futures returned by functions be discardable.
55 class Docker
56 {
57 public:
58  // Create Docker abstraction and optionally validate docker.
60  const std::string& path,
61  const std::string& socket,
62  bool validate = true,
63  const Option<JSON::Object>& config = None());
64 
65  virtual ~Docker() {}
66 
67  struct Device
68  {
71 
72  struct Access
73  {
74  Access() : read(false), write(false), mknod(false) {}
75 
76  bool read;
77  bool write;
78  bool mknod;
79  } access;
80  };
81 
82  struct PortMapping
83  {
84  uint32_t hostPort;
85  uint32_t containerPort;
87  };
88 
89  class Container
90  {
91  public:
92  static Try<Container> create(
93  const std::string& output);
94 
95  // Returns the docker inspect output.
96  const std::string output;
97 
98  // Returns the ID of the container.
99  const std::string id;
100 
101  // Returns the name of the container.
102  const std::string name;
103 
104  // Returns the pid of the container, or None if the container is
105  // not running.
107 
108  // Returns if the container has already started. This field is
109  // needed since pid is empty when the container terminates.
110  const bool started;
111 
112  // Returns the IPv4 address of the container, or `None()` if no
113  // IPv4 address has been assigned.
115 
116  // Returns the IPv6 address of the container, or `None()` if no
117  // IPv6 address has been assigned.
119 
120  const std::vector<Device> devices;
121 
122  // Returns the DNS nameservers set by "--dns" option.
123  const std::vector<std::string> dns;
124 
125  // Returns the DNS options set by "--dns-option" option.
126  const std::vector<std::string> dnsOptions;
127 
128  // Returns the DNS search domains set by "--dns-search" option.
129  const std::vector<std::string> dnsSearch;
130 
131  private:
132  Container(
133  const std::string& _output,
134  const std::string& _id,
135  const std::string& _name,
136  const Option<pid_t>& _pid,
137  bool _started,
138  const Option<std::string>& _ipAddress,
139  const Option<std::string>& _ip6Address,
140  const std::vector<Device>& _devices,
141  const std::vector<std::string>& _dns,
142  const std::vector<std::string>& _dnsOptions,
143  const std::vector<std::string>& _dnsSearch)
144  : output(_output),
145  id(_id),
146  name(_name),
147  pid(_pid),
148  started(_started),
149  ipAddress(_ipAddress),
150  ip6Address(_ip6Address),
151  devices(_devices),
152  dns(_dns),
153  dnsOptions(_dnsOptions),
154  dnsSearch(_dnsSearch) {}
155  };
156 
157  class Image
158  {
159  public:
160  static Try<Image> create(const JSON::Object& json);
161 
163 
165 
166  private:
167  Image(const Option<std::vector<std::string>>& _entrypoint,
168  const Option<std::map<std::string, std::string>>& _environment)
169  : entrypoint(_entrypoint),
170  environment(_environment) {}
171  };
172 
173  // See https://docs.docker.com/engine/reference/run for a complete
174  // explanation of each option.
176  {
177  public:
178  static Try<RunOptions> create(
179  const mesos::ContainerInfo& containerInfo,
180  const mesos::CommandInfo& commandInfo,
181  const std::string& containerName,
182  const std::string& sandboxDirectory,
183  const std::string& mappedDirectory,
184  const Option<mesos::Resources>& resources = None(),
185  bool enableCfsQuota = false,
186  const Option<std::map<std::string, std::string>>& env = None(),
187  const Option<std::vector<Device>>& devices = None(),
188  const Option<mesos::internal::ContainerDNSInfo>& defaultContainerDNS = None()); // NOLINT(whitespace/line_length)
189 
190  // "--privileged" option.
192 
193  // "--cpu-shares" option.
195 
196  // "--cpu-quota" option.
198 
199  // "--memory" option.
201 
202  // Environment variable overrides. These overrides will be passed
203  // to docker container through "--env-file" option.
204  std::map<std::string, std::string> env;
205 
206  // "--volume" option.
207  std::vector<std::string> volumes;
208 
209  // "--volume-driver" option.
211 
212  // "--network" option.
214 
215  // "--hostname" option.
217 
218  // "--dns" option.
219  std::vector<std::string> dns;
220 
221  // "--dns-search" option.
222  std::vector<std::string> dnsSearch;
223 
224  // "--dns-opt" option.
225  std::vector<std::string> dnsOpt;
226 
227  // Port mappings for "-p" option.
228  std::vector<PortMapping> portMappings;
229 
230  // "--device" option.
231  std::vector<Device> devices;
232 
233  // "--entrypoint" option.
235 
236  // "--name" option.
238 
239  // Additional docker options passed through containerizer.
240  std::vector<std::string> additionalOptions;
241 
242  // "IMAGE[:TAG|@DIGEST]" part of docker run.
243  std::string image;
244 
245  // Arguments for docker run.
246  std::vector<std::string> arguments;
247  };
248 
249  // Performs 'docker run IMAGE'. Returns the exit status of the
250  // container. Note that currently the exit status may correspond
251  // to the exit code from a failure of the docker client or daemon
252  // rather than the container. Docker >= 1.10 [1] uses the following
253  // exit statuses inherited from 'chroot':
254  // 125 if the error is with Docker daemon itself.
255  // 126 if the contained command cannot be invoked.
256  // 127 if the contained command cannot be found.
257  // Exit code of contained command otherwise.
258  //
259  // [1]: https://github.com/docker/docker/pull/14012
261  const RunOptions& options,
262  const process::Subprocess::IO& _stdout =
264  const process::Subprocess::IO& _stderr =
266 
267  // Returns the current docker version.
268  virtual process::Future<Version> version() const;
269 
270  // Performs 'docker stop -t TIMEOUT CONTAINER'. If remove is true then a rm -f
271  // will be called when stop failed, otherwise a failure is returned. The
272  // timeout parameter will be passed through to docker and is the amount of
273  // time for docker to wait after stopping a container before killing it.
274  // A value of zero (the default value) is the same as issuing a
275  // 'docker kill CONTAINER'.
277  const std::string& containerName,
278  const Duration& timeout = Seconds(0),
279  bool remove = false) const;
280 
281  // Performs 'docker kill --signal=<signal> CONTAINER'.
283  const std::string& containerName,
284  int signal) const;
285 
286  // Performs 'docker rm (-f) CONTAINER'.
288  const std::string& containerName,
289  bool force = false) const;
290 
291  // Performs 'docker inspect CONTAINER'. If retryInterval is set,
292  // we will keep retrying inspect until the container is started or
293  // the future is discarded.
295  const std::string& containerName,
296  const Option<Duration>& retryInterval = None()) const;
297 
298  // Performs 'docker ps (-a)'.
300  bool all = false,
301  const Option<std::string>& prefix = None()) const;
302 
304  const std::string& directory,
305  const std::string& image,
306  bool force = false) const;
307 
308  // Validate current docker version is not less than minVersion.
309  virtual Try<Nothing> validateVersion(const Version& minVersion) const;
310 
311  virtual std::string getPath()
312  {
313  return path;
314  }
315 
316 protected:
317  // Uses the specified path to the Docker CLI tool.
318  Docker(const std::string& _path,
319  const std::string& _socket,
320  const Option<JSON::Object>& _config)
321  : path(_path),
322  socket(DEFAULT_DOCKER_HOST_PREFIX + _socket),
323  config(_config) {}
324 
325 private:
326  static process::Future<Version> _version(
327  const std::string& cmd,
328  const process::Subprocess& s);
329 
330  static process::Future<Version> __version(
331  const process::Future<std::string>& output);
332 
333  static process::Future<Nothing> _stop(
334  const Docker& docker,
335  const std::string& containerName,
336  const std::string& cmd,
337  const process::Subprocess& s,
338  bool remove);
339 
340  static void _inspect(
341  const std::string& cmd,
343  const Option<Duration>& retryInterval);
344 
345  static void __inspect(
346  const std::string& cmd,
348  const Option<Duration>& retryInterval,
350  const process::Subprocess& s);
351 
352  static void ___inspect(
353  const std::string& cmd,
355  const Option<Duration>& retryInterval,
356  const process::Future<std::string>& output);
357 
359  const Docker& docker,
360  const std::string& cmd,
361  const process::Subprocess& s,
364 
366  const Docker& docker,
368  const std::string& output);
369 
370  static void inspectBatches(
371  process::Owned<std::list<Docker::Container>> containers,
372  process::Owned<std::vector<std::string>> lines,
373  process::Owned<process::Promise<std::list<Docker::Container>>> promise,
374  const Docker& docker,
375  const Option<std::string>& prefix);
376 
377  static std::list<process::Future<Docker::Container>> createInspectBatch(
378  process::Owned<std::vector<std::string>> lines,
379  const Docker& docker,
380  const Option<std::string>& prefix);
381 
382  static process::Future<Image> _pull(
383  const Docker& docker,
384  const process::Subprocess& s,
385  const std::string& directory,
386  const std::string& image,
387  const std::string& path,
388  const std::string& socket,
389  const Option<JSON::Object>& config,
391 
392  static process::Future<Image> __pull(
393  const Docker& docker,
394  const std::string& directory,
395  const std::string& image,
396  const std::string& path,
397  const std::string& socket,
398  const Option<JSON::Object>& config);
399 
400  static process::Future<Image> ___pull(
401  const Docker& docker,
402  const process::Subprocess& s,
403  const std::string& cmd,
404  const std::string& directory,
405  const std::string& image);
406 
407  static process::Future<Image> ____pull(
408  const std::string& output);
409 
410  static void pullDiscarded(
411  const process::Subprocess& s,
412  const std::string& cmd);
413 
414  const std::string path;
415  const std::string socket;
416  const Option<JSON::Object> config;
417 };
418 
419 #endif // __DOCKER_HPP__
Option< std::vector< std::string > > entrypoint
Definition: docker.hpp:162
Definition: docker.hpp:72
struct Docker::Device::Access access
Option< Error > validate(const std::string &imageDir)
std::string image
Definition: docker.hpp:243
const Option< pid_t > pid
Definition: docker.hpp:106
std::vector< std::string > arguments
Definition: docker.hpp:246
std::vector< std::string > dnsOpt
Definition: docker.hpp:225
virtual process::Future< Version > version() const
Definition: try.hpp:34
Option< Bytes > memory
Definition: docker.hpp:200
Option< uint64_t > cpuShares
Definition: docker.hpp:194
bool privileged
Definition: docker.hpp:191
Option< std::string > network
Definition: docker.hpp:213
uint32_t containerPort
Definition: docker.hpp:85
constexpr const char * prefix
Definition: os.hpp:94
std::vector< Device > devices
Definition: docker.hpp:231
Option< uint64_t > cpuQuota
Definition: docker.hpp:197
Option< std::map< std::string, std::string > > environment
Definition: docker.hpp:164
const std::vector< std::string > dnsSearch
Definition: docker.hpp:129
const bool started
Definition: docker.hpp:110
virtual process::Future< Image > pull(const std::string &directory, const std::string &image, bool force=false) const
constexpr char DEFAULT_DOCKER_HOST_PREFIX[]
Definition: docker.hpp:49
Option< std::string > hostname
Definition: docker.hpp:216
#define STDERR_FILENO
Definition: windows.hpp:161
Definition: duration.hpp:32
std::vector< std::string > dns
Definition: docker.hpp:219
virtual process::Future< Nothing > kill(const std::string &containerName, int signal) const
virtual process::Future< Container > inspect(const std::string &containerName, const Option< Duration > &retryInterval=None()) const
Access()
Definition: docker.hpp:74
Definition: json.hpp:154
Docker(const std::string &_path, const std::string &_socket, const Option< JSON::Object > &_config)
Definition: docker.hpp:318
Definition: docker.hpp:89
Definition: docker.hpp:67
Represents a fork() exec()ed subprocess.
Definition: subprocess.hpp:43
static IO FD(int_fd fd, IO::FDType type=IO::DUPLICATED)
bool write
Definition: docker.hpp:77
const std::vector< std::string > dns
Definition: docker.hpp:123
const Option< std::string > ipAddress
Definition: docker.hpp:114
#define STDOUT_FILENO
Definition: windows.hpp:160
const std::vector< std::string > dnsOptions
Definition: docker.hpp:126
bool mknod
Definition: docker.hpp:78
Represents a POSIX or Windows file system path and offers common path manipulations.
Definition: path.hpp:145
static Try< RunOptions > create(const mesos::ContainerInfo &containerInfo, const mesos::CommandInfo &commandInfo, const std::string &containerName, const std::string &sandboxDirectory, const std::string &mappedDirectory, const Option< mesos::Resources > &resources=None(), bool enableCfsQuota=false, const Option< std::map< std::string, std::string >> &env=None(), const Option< std::vector< Device >> &devices=None(), const Option< mesos::internal::ContainerDNSInfo > &defaultContainerDNS=None())
Definition: duration.hpp:259
Describes how the I/O is redirected for stdin/stdout/stderr.
Definition: subprocess.hpp:61
std::vector< std::string > dnsSearch
Definition: docker.hpp:222
std::vector< std::string > additionalOptions
Definition: docker.hpp:240
void json(JSON::ObjectWriter *writer, const Task &task)
Definition: future.hpp:73
const std::string output
Definition: docker.hpp:96
static Try< process::Owned< Docker > > create(const std::string &path, const std::string &socket, bool validate=true, const Option< JSON::Object > &config=None())
Protocol< PromiseRequest, PromiseResponse > promise
uint32_t hostPort
Definition: docker.hpp:84
std::vector< PortMapping > portMappings
Definition: docker.hpp:228
static Try< Image > create(const JSON::Object &json)
Option< std::string > protocol
Definition: docker.hpp:86
Definition: docker.hpp:55
std::map< std::string, std::string > env
Definition: docker.hpp:204
URI image(const std::string &repository, const std::string &reference, const std::string &registry, const Option< std::string > &scheme=None(), const Option< int > &port=None())
Definition: docker.hpp:30
Definition: none.hpp:27
Option< std::string > volumeDriver
Definition: docker.hpp:210
const std::vector< Device > devices
Definition: docker.hpp:120
Definition: version.hpp:41
virtual Try< Nothing > validateVersion(const Version &minVersion) const
const std::string id
Definition: docker.hpp:99
virtual std::string getPath()
Definition: docker.hpp:311
virtual ~Docker()
Definition: docker.hpp:65
Path hostPath
Definition: docker.hpp:69
Definition: docker.hpp:82
virtual process::Future< std::list< Container > > ps(bool all=false, const Option< std::string > &prefix=None()) const
const std::string name
Definition: docker.hpp:102
bool read
Definition: docker.hpp:76
virtual process::Future< Option< int > > run(const RunOptions &options, const process::Subprocess::IO &_stdout=process::Subprocess::FD(STDOUT_FILENO), const process::Subprocess::IO &_stderr=process::Subprocess::FD(STDERR_FILENO)) const
std::vector< std::string > volumes
Definition: docker.hpp:207
Definition: owned.hpp:35
Option< std::string > entrypoint
Definition: docker.hpp:234
Option< std::string > name
Definition: docker.hpp:237
const Option< std::string > ip6Address
Definition: docker.hpp:118
Definition: docker.hpp:175
static Try< Container > create(const std::string &output)
Path containerPath
Definition: docker.hpp:70
virtual process::Future< Nothing > rm(const std::string &containerName, bool force=false) const
virtual process::Future< Nothing > stop(const std::string &containerName, const Duration &timeout=Seconds(0), bool remove=false) const
Definition: docker.hpp:157
Definition: future.hpp:57