Add static content for archiving (#3751)
No files matched your search
@@ -1,34 +1,5 @@
|
||||
FROM docs/docker.github.io:docs-base
|
||||
FROM starefossen/github-pages:137
|
||||
|
||||
# docs-base contains: GitHub Pages, nginx, wget, svn, and the docs archives,
|
||||
# running on Alpine. See the contents of docs-base at:
|
||||
# https://github.com/docker/docker.github.io/tree/docs-base
|
||||
COPY . /usr/src/app/
|
||||
|
||||
# First, build non-edge (all of this is duplicated later -- that is on purpose)
|
||||
|
||||
# Copy master into target directory (skipping files / folders in .dockerignore)
|
||||
# These files represent the current docs
|
||||
COPY . md_source
|
||||
|
||||
# Move built html into md_source directory so we can reuse the target directory
|
||||
# to hold the static output.
|
||||
# Pull reference docs from upstream locations, then build the master docs
|
||||
# into static HTML in the "target" directory using Jekyll
|
||||
# then nuke the md_source directory.
|
||||
|
||||
## Branch to pull from, per ref doc
|
||||
## To get master from svn the svn branch needs to be 'trunk'. To get a branch from svn it needs to be 'branches/branchname'
|
||||
|
||||
# Engine
|
||||
ENV ENGINE_SVN_BRANCH="branches/17.05.x"
|
||||
ENV ENGINE_BRANCH="17.05.x"
|
||||
|
||||
# Distribution
|
||||
ENV DISTRIBUTION_SVN_BRANCH="branches/release/2.6"
|
||||
ENV DISTRIBUTION_BRANCH="release/2.6"
|
||||
|
||||
RUN sh md_source/_scripts/fetch-upstream-resources.sh \
|
||||
&& jekyll build -s md_source -d target --config md_source/_config.yml \
|
||||
&& rm -rf target/apidocs/layouts \
|
||||
&& find target -type f -name '*.html' -print0 | xargs -0 sed -i 's#href="https://docs.docker.com/#href="/#g' \
|
||||
&& rm -rf md_source
|
||||
CMD jekyll serve -H 0.0.0.0
|
||||
@@ -120,29 +120,6 @@ else %}{% assign edit_url = "" %}{% endif %} {% break %} {% endif %} {% endfor %
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% if page.noratings != true %}
|
||||
<div style="color:#b9c2cc; text-align: center; margin-top: 150px">
|
||||
<div id="pd_rating_holder_8453675"></div>
|
||||
<script type="text/javascript">
|
||||
PDRTJS_settings_8453675 = {
|
||||
"id": "8453675",
|
||||
"unique_id": "{{ page.path }}",
|
||||
"title": "{{ page.title }}",
|
||||
"permalink": "https://github.com/docker/docker.github.io/blob/master/{{ page.path }}"
|
||||
};
|
||||
(function(d, c, j) {
|
||||
if (!document.getElementById(j)) {
|
||||
var pd = d.createElement(c),
|
||||
s;
|
||||
pd.id = j;
|
||||
pd.src = ('https:' == document.location.protocol) ? 'https://polldaddy.com/js/rating/rating.js' : 'http://i0.poll.fm/js/rating/rating.js';
|
||||
s = document.getElementsByTagName(c)[0];
|
||||
s.parentNode.insertBefore(pd, s);
|
||||
}
|
||||
}(document, 'script', 'pd-rating-js'));
|
||||
</script>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
</main>
|
||||
<nav class="col-nav">
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
build/
|
||||
@@ -1,2 +0,0 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
@@ -1,15 +0,0 @@
|
||||
FROM ubuntu:trusty
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yq ruby ruby-dev build-essential git awscli && \
|
||||
gem install --no-ri --no-rdoc bundler
|
||||
WORKDIR /app
|
||||
ADD Gemfile /app/Gemfile
|
||||
ADD Gemfile.lock /app/Gemfile.lock
|
||||
RUN bundle install
|
||||
ADD . /app
|
||||
|
||||
ENV PATH=$PATH:/app AWS_ACCESS_KEY_ID=**setme** AWS_SECRET_ACCESS_KEY=**setme** BUCKET=**setme**
|
||||
|
||||
EXPOSE 4567
|
||||
CMD ["bundle", "exec", "middleman", "server"]
|
||||
@@ -1,12 +0,0 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# Middleman
|
||||
gem 'middleman', '~>3.3.10'
|
||||
gem 'middleman-gh-pages', '~> 0.0.3'
|
||||
gem 'middleman-syntax', '~> 2.0.0'
|
||||
gem 'middleman-autoprefixer', '~> 2.4.4'
|
||||
gem 'rouge', '~> 1.9.0'
|
||||
gem 'redcarpet', '~> 3.3.2'
|
||||
|
||||
gem 'rake', '~> 10.4.2'
|
||||
gem 'therubyracer', '~> 0.12.1', platforms: :ruby
|
||||
@@ -1,140 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (4.1.11)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 1.1)
|
||||
autoprefixer-rails (5.2.0.1)
|
||||
execjs
|
||||
json
|
||||
celluloid (0.16.0)
|
||||
timers (~> 4.0.0)
|
||||
chunky_png (1.3.4)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.9.1.1)
|
||||
compass (1.0.3)
|
||||
chunky_png (~> 1.2)
|
||||
compass-core (~> 1.0.2)
|
||||
compass-import-once (~> 1.0.5)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9)
|
||||
sass (>= 3.3.13, < 3.5)
|
||||
compass-core (1.0.3)
|
||||
multi_json (~> 1.0)
|
||||
sass (>= 3.3.0, < 3.5)
|
||||
compass-import-once (1.0.5)
|
||||
sass (>= 3.2, < 3.5)
|
||||
erubis (2.7.0)
|
||||
execjs (2.5.2)
|
||||
ffi (1.9.8)
|
||||
haml (4.0.6)
|
||||
tilt
|
||||
hike (1.2.3)
|
||||
hitimes (1.2.2)
|
||||
hooks (0.4.0)
|
||||
uber (~> 0.0.4)
|
||||
i18n (0.7.0)
|
||||
json (1.8.3)
|
||||
kramdown (1.7.0)
|
||||
libv8 (3.16.14.7)
|
||||
listen (2.10.1)
|
||||
celluloid (~> 0.16.0)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9)
|
||||
middleman (3.3.12)
|
||||
coffee-script (~> 2.2)
|
||||
compass (>= 1.0.0, < 2.0.0)
|
||||
compass-import-once (= 1.0.5)
|
||||
execjs (~> 2.0)
|
||||
haml (>= 4.0.5)
|
||||
kramdown (~> 1.2)
|
||||
middleman-core (= 3.3.12)
|
||||
middleman-sprockets (>= 3.1.2)
|
||||
sass (>= 3.4.0, < 4.0)
|
||||
uglifier (~> 2.5)
|
||||
middleman-autoprefixer (2.4.4)
|
||||
autoprefixer-rails (~> 5.2.0)
|
||||
middleman-core (>= 3.3.3)
|
||||
middleman-core (3.3.12)
|
||||
activesupport (~> 4.1.0)
|
||||
bundler (~> 1.1)
|
||||
erubis
|
||||
hooks (~> 0.3)
|
||||
i18n (~> 0.7.0)
|
||||
listen (>= 2.7.9, < 3.0)
|
||||
padrino-helpers (~> 0.12.3)
|
||||
rack (>= 1.4.5, < 2.0)
|
||||
rack-test (~> 0.6.2)
|
||||
thor (>= 0.15.2, < 2.0)
|
||||
tilt (~> 1.4.1, < 2.0)
|
||||
middleman-gh-pages (0.0.3)
|
||||
rake (> 0.9.3)
|
||||
middleman-sprockets (3.4.2)
|
||||
middleman-core (>= 3.3)
|
||||
sprockets (~> 2.12.1)
|
||||
sprockets-helpers (~> 1.1.0)
|
||||
sprockets-sass (~> 1.3.0)
|
||||
middleman-syntax (2.0.0)
|
||||
middleman-core (~> 3.2)
|
||||
rouge (~> 1.0)
|
||||
minitest (5.7.0)
|
||||
multi_json (1.11.1)
|
||||
padrino-helpers (0.12.5)
|
||||
i18n (~> 0.6, >= 0.6.7)
|
||||
padrino-support (= 0.12.5)
|
||||
tilt (~> 1.4.1)
|
||||
padrino-support (0.12.5)
|
||||
activesupport (>= 3.1)
|
||||
rack (1.6.4)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rake (10.4.2)
|
||||
rb-fsevent (0.9.5)
|
||||
rb-inotify (0.9.5)
|
||||
ffi (>= 0.5.0)
|
||||
redcarpet (3.3.2)
|
||||
ref (1.0.5)
|
||||
rouge (1.9.0)
|
||||
sass (3.4.14)
|
||||
sprockets (2.12.3)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-helpers (1.1.0)
|
||||
sprockets (~> 2.0)
|
||||
sprockets-sass (1.3.1)
|
||||
sprockets (~> 2.0)
|
||||
tilt (~> 1.1)
|
||||
therubyracer (0.12.2)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tilt (1.4.1)
|
||||
timers (4.0.1)
|
||||
hitimes
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.0.13)
|
||||
uglifier (2.7.1)
|
||||
execjs (>= 0.3.0)
|
||||
json (>= 1.8.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
middleman (~> 3.3.10)
|
||||
middleman-autoprefixer (~> 2.4.4)
|
||||
middleman-gh-pages (~> 0.0.3)
|
||||
middleman-syntax (~> 2.0.0)
|
||||
rake (~> 10.4.2)
|
||||
redcarpet (~> 3.3.2)
|
||||
rouge (~> 1.9.0)
|
||||
therubyracer (~> 0.12.1)
|
||||
@@ -1,13 +0,0 @@
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
@@ -1,28 +0,0 @@
|
||||
.PHONY: docs build release
|
||||
|
||||
CONTAINER_NAME=api-build
|
||||
export CONTAINER_NAME
|
||||
|
||||
docs: build
|
||||
docker run --rm -it -p 4567:4567 dockercloud/api-docs
|
||||
|
||||
build:
|
||||
git submodule init && git submodule update
|
||||
docker build -t dockercloud/api-docs .
|
||||
|
||||
release: build
|
||||
docker rm -f $(CONTAINER_NAME) || true
|
||||
docker run --name $(CONTAINER_NAME) -it \
|
||||
dockercloud/api-docs middleman build
|
||||
docker cp $(CONTAINER_NAME):/app/build ../
|
||||
rm -r ../docker-cloud
|
||||
mv ../build ../docker-cloud
|
||||
cp ../docker-cloud/index.html ../layouts/single.html
|
||||
# defuse text that looks like a go template
|
||||
# commenting out until we know that we're not using Hugo anywhere & can remove
|
||||
# grep -rl '{ {' ../docker-cloud/* | xargs sed -i~ "s/{ {/{ {/g"
|
||||
#rm source/includes/node.md~
|
||||
#rm source/includes/stack.md~
|
||||
#rm ../source/index.html~
|
||||
#rm ../source/layouts/single.html~
|
||||
docker rm $(CONTAINER_NAME)
|
||||
@@ -1,29 +0,0 @@
|
||||
dockercloud/api-docs
|
||||
====================
|
||||
|
||||
[](https://cloud.docker.com/stack/deploy/)
|
||||
|
||||
If you find a typo or mismatch between the API and this documentation, please send us a pull request!
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
To run it locally:
|
||||
|
||||
```none
|
||||
$ git clone https://github.com/docker/docker.github.io.git
|
||||
$ make release
|
||||
```
|
||||
|
||||
The documentation will be available in http://localhost:8000/
|
||||
|
||||
## Updating the release HTML
|
||||
|
||||
As with the HTML generated by the DTR apidocs, the Docker Cloud documentation
|
||||
needs to be generated and the resulting HTML committed to this repository.
|
||||
|
||||
After merging all PR's, run `make release`. This will place the updated HTML
|
||||
into the `apidocs/docker-cloud` directory.
|
||||
|
||||
Create a new Pull Request and get it merged. - now this repository is ready for
|
||||
the release process using `docker/docs.docker.com`.
|
||||
@@ -1,6 +0,0 @@
|
||||
require 'middleman-gh-pages'
|
||||
require 'rake/clean'
|
||||
|
||||
CLOBBER.include('build')
|
||||
|
||||
task :default => [:build]
|
||||
@@ -1,38 +0,0 @@
|
||||
# Markdown
|
||||
set :markdown_engine, :redcarpet
|
||||
set :markdown,
|
||||
fenced_code_blocks: true,
|
||||
smartypants: true,
|
||||
disable_indented_code_blocks: true,
|
||||
prettify: true,
|
||||
tables: true,
|
||||
with_toc_data: true,
|
||||
no_intra_emphasis: true
|
||||
|
||||
# Assets
|
||||
set :css_dir, 'stylesheets'
|
||||
set :js_dir, 'javascripts'
|
||||
set :images_dir, 'images'
|
||||
set :fonts_dir, 'fonts'
|
||||
|
||||
# Activate the syntax highlighter
|
||||
activate :syntax
|
||||
|
||||
activate :autoprefixer do |config|
|
||||
config.browsers = ['last 2 version', 'Firefox ESR']
|
||||
config.cascade = false
|
||||
config.inline = true
|
||||
end
|
||||
|
||||
# Github pages require relative links
|
||||
activate :relative_assets
|
||||
set :relative_links, true
|
||||
|
||||
# Build Configuration
|
||||
configure :build do
|
||||
activate :minify_css
|
||||
activate :minify_javascript
|
||||
# activate :relative_assets
|
||||
# activate :asset_hash
|
||||
# activate :gzip
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
apidocs:
|
||||
image: tutum/api-docs:latest
|
||||
ports:
|
||||
- "4567:4567"
|
||||
@@ -1,148 +0,0 @@
|
||||
{
|
||||
"IcoMoonType": "selection",
|
||||
"icons": [
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z"
|
||||
],
|
||||
"attrs": [],
|
||||
"isMulticolor": false,
|
||||
"tags": [
|
||||
"exclamation-circle"
|
||||
],
|
||||
"defaultCode": 61546,
|
||||
"grid": 14
|
||||
},
|
||||
"attrs": [],
|
||||
"properties": {
|
||||
"id": 100,
|
||||
"order": 4,
|
||||
"prevSize": 28,
|
||||
"code": 58880,
|
||||
"name": "exclamation-sign",
|
||||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 0
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
|
||||
],
|
||||
"attrs": [],
|
||||
"isMulticolor": false,
|
||||
"tags": [
|
||||
"info-circle"
|
||||
],
|
||||
"defaultCode": 61530,
|
||||
"grid": 14
|
||||
},
|
||||
"attrs": [],
|
||||
"properties": {
|
||||
"id": 85,
|
||||
"order": 3,
|
||||
"name": "info-sign",
|
||||
"prevSize": 28,
|
||||
"code": 58882
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 2
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
|
||||
],
|
||||
"attrs": [],
|
||||
"isMulticolor": false,
|
||||
"tags": [
|
||||
"check-circle"
|
||||
],
|
||||
"defaultCode": 61528,
|
||||
"grid": 14
|
||||
},
|
||||
"attrs": [],
|
||||
"properties": {
|
||||
"id": 83,
|
||||
"order": 9,
|
||||
"prevSize": 28,
|
||||
"code": 58886,
|
||||
"name": "ok-sign"
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 6
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z"
|
||||
],
|
||||
"width": 951,
|
||||
"attrs": [],
|
||||
"isMulticolor": false,
|
||||
"tags": [
|
||||
"search"
|
||||
],
|
||||
"defaultCode": 61442,
|
||||
"grid": 14
|
||||
},
|
||||
"attrs": [],
|
||||
"properties": {
|
||||
"id": 2,
|
||||
"order": 1,
|
||||
"prevSize": 28,
|
||||
"code": 58887,
|
||||
"name": "icon-search"
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 7
|
||||
}
|
||||
],
|
||||
"height": 1024,
|
||||
"metadata": {
|
||||
"name": "slate",
|
||||
"license": "SIL OFL 1.1"
|
||||
},
|
||||
"preferences": {
|
||||
"showGlyphs": true,
|
||||
"showQuickUse": true,
|
||||
"showQuickUse2": true,
|
||||
"showSVGs": true,
|
||||
"fontPref": {
|
||||
"prefix": "icon-",
|
||||
"metadata": {
|
||||
"fontFamily": "slate",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 0,
|
||||
"description": "Based on FontAwesome",
|
||||
"license": "SIL OFL 1.1"
|
||||
},
|
||||
"metrics": {
|
||||
"emSize": 1024,
|
||||
"baseline": 6.25,
|
||||
"whitespace": 50
|
||||
},
|
||||
"resetPoint": 58880,
|
||||
"showSelector": false,
|
||||
"selector": "class",
|
||||
"classSelector": ".icon",
|
||||
"showMetrics": false,
|
||||
"showMetadata": true,
|
||||
"showVersion": true,
|
||||
"ie7": false
|
||||
},
|
||||
"imagePref": {
|
||||
"prefix": "icon-",
|
||||
"png": true,
|
||||
"useClassSelector": true,
|
||||
"color": 4473924,
|
||||
"bgColor": 16777215
|
||||
},
|
||||
"historySize": 100,
|
||||
"showCodes": true,
|
||||
"gridSize": 16,
|
||||
"showLiga": false
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
middleman build
|
||||
aws s3 sync /app/build s3://${AWS_S3_BUCKET}/apidocs/docker-cloud/ --delete --acl public-read --region us-east-1
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="slate" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " d="" horiz-adv-x="512" />
|
||||
<glyph unicode="" d="M438.857 877.714q119.429 0 220.286-58.857t159.714-159.714 58.857-220.286-58.857-220.286-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857zM512 165.143v108.571q0 8-5.143 13.429t-12.571 5.429h-109.714q-7.429 0-13.143-5.714t-5.714-13.143v-108.571q0-7.429 5.714-13.143t13.143-5.714h109.714q7.429 0 12.571 5.429t5.143 13.429zM510.857 361.714l10.286 354.857q0 6.857-5.714 10.286-5.714 4.571-13.714 4.571h-125.714q-8 0-13.714-4.571-5.714-3.429-5.714-10.286l9.714-354.857q0-5.714 5.714-10t13.714-4.286h105.714q8 0 13.429 4.286t6 10z" />
|
||||
<glyph unicode="" d="M585.143 164.571v91.429q0 8-5.143 13.143t-13.143 5.143h-54.857v292.571q0 8-5.143 13.143t-13.143 5.143h-182.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h54.857v-182.857h-54.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h256q8 0 13.143 5.143t5.143 13.143zM512 676.571v91.429q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
<glyph unicode="" d="M733.714 531.428q0 16-10.286 26.286l-52 51.429q-10.857 10.857-25.714 10.857t-25.714-10.857l-233.143-232.571-129.143 129.143q-10.857 10.857-25.714 10.857t-25.714-10.857l-52-51.429q-10.286-10.286-10.286-26.286 0-15.429 10.286-25.714l206.857-206.857q10.857-10.857 25.714-10.857 15.429 0 26.286 10.857l310.286 310.286q10.286 10.286 10.286 25.714zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
<glyph unicode="" d="M658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-29.714-21.714-51.429t-51.429-21.714q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" horiz-adv-x="951" />
|
||||
</font></defs></svg>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 96 B |
@@ -1,28 +0,0 @@
|
||||
# Errors
|
||||
|
||||
|
||||
> API response structure
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Descriptive error message"
|
||||
}
|
||||
```
|
||||
|
||||
The Docker Cloud API uses the following error codes:
|
||||
|
||||
|
||||
Error Code | Meaning
|
||||
---------- | -------
|
||||
400 | Bad Request -- There's a problem in the content of your request. Retrying the same request will fail.
|
||||
401 | Unauthorized -- Your API key is wrong or your account has been deactivated.
|
||||
402 | Payment Required -- You need to provide billing information to perform this request.
|
||||
403 | Forbidden -- Quota limit exceeded. Please contact support to request a quota increase.
|
||||
404 | Not Found -- The requested object cannot be found.
|
||||
405 | Method Not Allowed -- The endpoint requested does not implement the method sent.
|
||||
409 | Conflict -- The object cannot be created or updated because another object exists with the same unique fields
|
||||
415 | Unsupported Media Type -- Make sure you are using `Accept` and `Content-Type` headers as `application/json` and that the data your are `POST`-ing or `PATCH`-ing is in valid JSON format.
|
||||
429 | Too Many Requests -- You are being throttled because of too many requests in a short period of time.
|
||||
500 | Internal Server Error -- There was a server error while processing your request. Try again later, or contact support.
|
||||
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later.
|
||||
504 | Gateway Timeout -- Our API servers are at full capacity. Please try again later.
|
||||
@@ -1,353 +0,0 @@
|
||||
# Actions
|
||||
|
||||
## Action
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "Cluster Create",
|
||||
"end_date": "Wed, 17 Sep 2014 08:26:22 +0000",
|
||||
"ip": "56.78.90.12",
|
||||
"is_user_action": true,
|
||||
"can_be_canceled": false,
|
||||
"location": "New York, USA",
|
||||
"method": "POST",
|
||||
"object": "/api/infra/v1/user_namespace/cluster/eea638f4-b77a-4183-b241-22dbd7866f22/",
|
||||
"path": "/api/infra/v1/user_namespace/cluster/",
|
||||
"resource_uri": "/api/audit/v1/action/6246c558-976c-4df6-ba60-eb1a344a17af/",
|
||||
"start_date": "Wed, 17 Sep 2014 08:26:22 +0000",
|
||||
"state": "Success",
|
||||
"user": "user_namespace",
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/7.0.6 Safari/537.78.2",
|
||||
"uuid": "6246c558-976c-4df6-ba60-eb1a344a17af"
|
||||
}
|
||||
```
|
||||
|
||||
An action represents an API call by a user. Details of the API call such as timestamp, origin IP address, and user agent are logged in the action object.
|
||||
|
||||
Simple API calls that do not require asynchronous execution will return immediately with the appropriate HTTP error code and an action object will be created either in `Success` or `Failed` states. API calls that do require asynchronous execution will return HTTP code `202 Accepted` immediately and create an action object in `In progress` state, which will change to `Success` or `Failed` state depending on the outcome of the operation being performed. In both cases the response will include a `X-DockerCloud-Action-URI` header with the resource URI of the created action.
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
| Attribute | Description |
|
||||
|:----------------|:-----------------------------------------------------------------------------------|
|
||||
| resource_uri | A unique API endpoint that represents the action |
|
||||
| uuid | A unique identifier for the action generated automatically on creation |
|
||||
| object | The API object (resource URI) to which the action applies to |
|
||||
| action | Name of the operation performed/being performed |
|
||||
| method | HTTP method used to access the API |
|
||||
| path | HTTP path of the API accessed |
|
||||
| user | The user authenticated in the request that created the action |
|
||||
| user_agent | The user agent provided by the client when accessing the API endpoint |
|
||||
| start_date | Date and time when the API call was performed and the operation started processing |
|
||||
| end_date | Date and time when the API call finished processing |
|
||||
| state | State of the operation (see table below) |
|
||||
| ip | IP address of the user that performed the API call |
|
||||
| location | Geographic location of the IP address of the user that performed the API call |
|
||||
| is_user_action | If the action has been triggered by the user |
|
||||
| can_be_canceled | If the action can be canceled by the user in the middle of its execution |
|
||||
| can_be_retried | If the action can be retried by the user |
|
||||
|
||||
|
||||
### Action states
|
||||
|
||||
| State | Description |
|
||||
|:------------|:---------------------------------------------------------------------------------------------|
|
||||
| Pending | The action needed asynchronous execution and it is waiting for an in progress action |
|
||||
| In progress | The action needed asynchronous execution and is being performed |
|
||||
| Canceling | The action is being canceled by user request |
|
||||
| Canceled | The action has been canceled |
|
||||
| Success | The action was executed successfully |
|
||||
| Failed | There was an issue when the action was being performed. Check the logs for more information. |
|
||||
|
||||
|
||||
## List all actions
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
actions = dockercloud.Action.list()
|
||||
```
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
actionList, err := dockercloud.ListActions()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(actionList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/audit/v1/action/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud action ls
|
||||
```
|
||||
|
||||
Lists all actions in chronological order. Returns a list of `Action` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/audit/v1/action/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| uuid | Filter by UUID. |
|
||||
| state | Filter by state. Possible values: `In progress`, `Success`, `Failed` |
|
||||
| start_date | Filter by start date. Valid filtering values are `start_date__gte` (after or on the date supplied) and `start_date__lte` (before or on the date supplied) |
|
||||
| end_date | Filter by end date. Valid filtering values are `end_date__gte` (after or on the date supplied) and `end_date__lte` (before or on the date supplied) |
|
||||
| object | Filter by resource URI of the related object. This filter can only be combined with 'include_related' filter |
|
||||
| include_related | There is a parent-child relationship between Docker Cloud objects, described in table `Relationships between Docker Cloud objects`. If set to 'true', will include the actions of the related objects to the object specified in "object" filter parameter. Possible values: 'true' or 'false' |
|
||||
|
||||
|
||||
## Relationships between Docker Cloud objects
|
||||
|
||||
| Object | Relationships |
|
||||
|:-------------|:-------------------------------------------------------------------------------|
|
||||
| Container | Container, service, stack (if any) |
|
||||
| Service | All containers in the service, service, stack (if any) |
|
||||
| Stack | All services in the stack, all containers in every service in the stack, stack |
|
||||
| Node | Node, node cluster (if any) |
|
||||
| Node cluster | All nodes in the cluster, node cluster |
|
||||
|
||||
|
||||
## Get an action by UUID
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
action = dockercloud.Action.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
action, err := dockercloud.GetAction("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(action)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/audit/v1/action/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud action inspect 7eaf7fff
|
||||
```
|
||||
|
||||
|
||||
Get all the details of an specific action
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/audit/v1/action/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------|:-----------------------------------|
|
||||
| uuid | The UUID of the action to retrieve |
|
||||
|
||||
|
||||
## Get the logs of an action
|
||||
|
||||
> Example log line
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "log",
|
||||
"log": "Log line from the action",
|
||||
"timestamp": 1433779324
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
def log_handler(message):
|
||||
print message
|
||||
|
||||
action = dockercloud.Action.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
action.logs(tail=300, follow=True, log_handler=log_handler)
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
c := make(chan dockercloud.Logs)
|
||||
action, err := dockercloud.GetAction("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
go action.GetLogs(c)
|
||||
|
||||
for {
|
||||
log.Println(<-c)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/audit/v1/action/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/logs/ HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud action logs 7eaf7fff-882c-4f3d-9a8f-a22317ac00ce
|
||||
```
|
||||
|
||||
|
||||
Get the logs of the specified action.
|
||||
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **STREAM API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/audit/v1/action/(uuid)/logs/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------|:----------------------------------------|
|
||||
| uuid | The UUID of the action to retrieve logs |
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------|:---------------------------------------------------------------------------|
|
||||
| tail | Number of lines to show from the end of the logs (default: `300`) |
|
||||
| follow | Whether to stream logs or close the connection immediately (default: true) |
|
||||
|
||||
## Cancel an action
|
||||
|
||||
```http
|
||||
POST /api/audit/v1/action/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/cancel/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
action, err := dockercloud.GetAction("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
action, err = action.Cancel()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(action)
|
||||
```
|
||||
|
||||
Cancels an action in Pending or In progress state.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/audit/v1/action/(uuid)/cancel/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------|:---------------------------------|
|
||||
| uuid | The UUID of the action to cancel |
|
||||
|
||||
|
||||
## Retry an action
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
def log_handler(message):
|
||||
print message
|
||||
|
||||
action = dockercloud.Action.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
action.logs(tail=300, follow=True, log_handler=log_handler)
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/audit/v1/action/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/retry/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
action, err := dockercloud.GetAction("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
action, err = action.Retry()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(action)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud action logs 7eaf7fff-882c-4f3d-9a8f-a22317ac00ce
|
||||
```
|
||||
|
||||
Retries an action in Success, Failed or Canceled state.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/audit/v1/action/(uuid)/retry/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|:----------|:--------------------------------|
|
||||
| uuid | The UUID of the action to retry |
|
||||
@@ -1,120 +0,0 @@
|
||||
# Availability Zones
|
||||
|
||||
## Availability Zone
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"available": true,
|
||||
"name": "ap-northeast-1a",
|
||||
"region": "/api/infra/v1/region/az/ap-northeast-1/",
|
||||
"resource_uri": "/api/infra/v1/az/aws/ap-northeast-1/ap-northeast-1a/"
|
||||
}
|
||||
```
|
||||
|
||||
An Availability Zone is an isolated location inside a region. Providers that support availability zones: AWS
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
available | Whether the availability zone is currently available for new node deployments
|
||||
name | An identifier for the availability zone
|
||||
region | The resource URI of the region where the availability zone is allocated
|
||||
resource_uri | A unique API endpoint that represents the zone
|
||||
|
||||
|
||||
## List all availability zones
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
az = dockercloud.AZ.list()
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/az/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
az, err := dockercloud.ListAZ()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(az)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster az
|
||||
```
|
||||
|
||||
Lists all availability zones from all regions of all supported cloud providers. Returns a list of `Availability Zone` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/az/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by availability zone name
|
||||
region | Filter by resource URI of the target region
|
||||
|
||||
|
||||
|
||||
## Get an individual availability zone
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
az = dockercloud.AZ.fetch("aws/sa-east-1/sa-east-1a")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
az, err := dockercloud.GetAZ("aws/sa-east-1/sa-east-1a")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(az)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/az/aws/sa-east-1/sa-east-1a/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Get all the details of a specific availability zone
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/az/(provider.name)/(region.name)/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the availability zone to retrieve
|
||||
provider | The name of the provider
|
||||
region | The name of the region
|
||||
@@ -1,827 +0,0 @@
|
||||
# Containers
|
||||
|
||||
## Container
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"autodestroy": "OFF",
|
||||
"autorestart": "OFF",
|
||||
"bindings": [
|
||||
{
|
||||
"volume": "/api/infra/v1/user_namespace/volume/1863e34d-6a7d-4945-aefc-8f27a4ab1a9e/",
|
||||
"host_path": null,
|
||||
"container_path": "/data",
|
||||
"rewritable": true
|
||||
},
|
||||
{
|
||||
"volume": null,
|
||||
"host_path": "/etc",
|
||||
"container_path": "/etc",
|
||||
"rewritable": true
|
||||
}
|
||||
],
|
||||
"cap_add": [
|
||||
"ALL"
|
||||
],
|
||||
"cap_drop": [
|
||||
"NET_ADMIN",
|
||||
"SYS_ADMIN"
|
||||
],
|
||||
"container_envvars": [
|
||||
{
|
||||
"key": "DB_1_ENV_DEBIAN_FRONTEND",
|
||||
"value": "noninteractive"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_MYSQL_PASS",
|
||||
"value": "**Random**"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_MYSQL_USER",
|
||||
"value": "admin"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_REPLICATION_MASTER",
|
||||
"value": "**False**"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_REPLICATION_PASS",
|
||||
"value": "replica"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_REPLICATION_SLAVE",
|
||||
"value": "**False**"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_ENV_REPLICATION_USER",
|
||||
"value": "replica"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_PORT",
|
||||
"value": "tcp://172.16.0.3:3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_PORT_3306_TCP",
|
||||
"value": "tcp://172.16.0.3:3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_PORT_3306_TCP_ADDR",
|
||||
"value": "172.16.0.3"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_PORT_3306_TCP_PORT",
|
||||
"value": "3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_1_PORT_3306_TCP_PROTO",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_DEBIAN_FRONTEND",
|
||||
"value": "noninteractive"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_MYSQL_PASS",
|
||||
"value": "**Random**"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_MYSQL_USER",
|
||||
"value": "admin"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_REPLICATION_MASTER",
|
||||
"value": "**False**"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_REPLICATION_PASS",
|
||||
"value": "replica"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_REPLICATION_SLAVE",
|
||||
"value": "**False**"
|
||||
},
|
||||
{
|
||||
"key": "DB_ENV_REPLICATION_USER",
|
||||
"value": "replica"
|
||||
},
|
||||
{
|
||||
"key": "DB_PASS",
|
||||
"value": "szVaPz925B7I"
|
||||
},
|
||||
{
|
||||
"key": "DB_PORT",
|
||||
"value": "tcp://172.16.0.3:3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_PORT_3306_TCP",
|
||||
"value": "tcp://172.16.0.3:3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_PORT_3306_TCP_ADDR",
|
||||
"value": "172.16.0.3"
|
||||
},
|
||||
{
|
||||
"key": "DB_PORT_3306_TCP_PORT",
|
||||
"value": "3306"
|
||||
},
|
||||
{
|
||||
"key": "DB_PORT_3306_TCP_PROTO",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"key": "DB_DOCKERCLOUD_API_URL",
|
||||
"value": "https://cloud.docker.com/api/app/v1/user_namespace/service/c0fed1dc-c528-40c9-aa4c-dc00672ebcbf/"
|
||||
}
|
||||
],
|
||||
"container_ports": [
|
||||
{
|
||||
"endpoint_uri": "http://wordpress-stackable-1.admin.cont.dockerapp.io:49153/",
|
||||
"inner_port": 80,
|
||||
"outer_port": 49153,
|
||||
"port_name": "http",
|
||||
"protocol": "tcp",
|
||||
"published": true,
|
||||
"uri_protocol": "http"
|
||||
}
|
||||
],
|
||||
"cpu_shares": 100,
|
||||
"cpuset": "0,1",
|
||||
"cgroup_parent": "m-executor-abcd",
|
||||
"deployed_datetime": "Thu, 16 Oct 2014 12:04:08 +0000",
|
||||
"destroyed_datetime": null,
|
||||
"devices": [
|
||||
"/dev/ttyUSB0:/dev/ttyUSB0"
|
||||
],
|
||||
"dns": [
|
||||
"8.8.8.8"
|
||||
],
|
||||
"dns_search": [
|
||||
"example.com",
|
||||
"c1dd4e1e-1356-411c-8613-e15146633640.local.dockerapp.io"
|
||||
],
|
||||
"domainname": "domainname",
|
||||
"entrypoint": "",
|
||||
"exit_code": null,
|
||||
"exit_code_msg": null,
|
||||
"extra_hosts": [
|
||||
"onehost:50.31.209.229"
|
||||
],
|
||||
"hostname": "hostname",
|
||||
"image_name": "tutum/wordpress-stackable:latest",
|
||||
"labels": {
|
||||
"com.example.description": "Accounting webapp",
|
||||
"com.example.department": "Finance",
|
||||
"com.example.label-with-empty-value": ""
|
||||
},
|
||||
"linked_to_container": [
|
||||
{
|
||||
"endpoints": {
|
||||
"3306/tcp": "tcp://172.16.0.3:3306"
|
||||
},
|
||||
"from_container": "/api/app/v1/user_namespace/container/c1dd4e1e-1356-411c-8613-e15146633640/",
|
||||
"name": "DB_1",
|
||||
"to_container": "/api/app/v1/user_namespace/container/ba434e1e-1234-411c-8613-e15146633640/"
|
||||
}
|
||||
],
|
||||
"link_variables": {
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_HOST": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_NAME": "wordpress",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_PASS": "szVaPz925B7I",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_PORT": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_USER": "admin",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DEBIAN_FRONTEND": "noninteractive",
|
||||
"WORDPRESS_STACKABLE_1_ENV_HOME": "/",
|
||||
"WORDPRESS_STACKABLE_1_ENV_PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"WORDPRESS_STACKABLE_1_PORT": "tcp://172.16.0.2:80",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP": "tcp://172.16.0.2:80",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_ADDR": "172.16.0.2",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_PORT": "80",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_PROTO": "tcp",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_HOST": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_NAME": "wordpress",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_PASS": "szVaPz925B7I",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_PORT": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_USER": "admin",
|
||||
"WORDPRESS_STACKABLE_ENV_DEBIAN_FRONTEND": "noninteractive",
|
||||
"WORDPRESS_STACKABLE_ENV_HOME": "/",
|
||||
"WORDPRESS_STACKABLE_ENV_PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"WORDPRESS_STACKABLE_PORT": "tcp://172.16.0.2:80",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP": "tcp://172.16.0.2:80",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_ADDR": "172.16.0.2",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_PORT": "80",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_PROTO": "tcp"
|
||||
},
|
||||
"mac_address": "02:42:ac:11:65:43",
|
||||
"memory": 1024,
|
||||
"memory_swap": 4096,
|
||||
"name": "wordpress-stackable",
|
||||
"net": "bridge",
|
||||
"node": "/api/infra/v1/user_namespace/node/9691c44e-3155-4ca2-958d-c9571aac0a14/",
|
||||
"pid": "none",
|
||||
"private_ip": "10.7.0.1",
|
||||
"privileged": false,
|
||||
"public_dns": "wordpress-stackable-1.admin.cont.dockerapp.io",
|
||||
"read_only": true,
|
||||
"resource_uri": "/api/app/v1/user_namespace/container/c1dd4e1e-1356-411c-8613-e15146633640/",
|
||||
"roles": ["global"],
|
||||
"run_command": "/run-wordpress.sh",
|
||||
"security_opt": [
|
||||
"label:user:USER",
|
||||
"label:role:ROLE"
|
||||
],
|
||||
"service": "/api/app/v1/user_namespace/service/adeebc1b-1b81-4af0-b8f2-cefffc69d7fb/",
|
||||
"started_datetime": "Thu, 16 Oct 2014 12:04:08 +0000",
|
||||
"state": "Running",
|
||||
"stdin_open": false,
|
||||
"stopped_datetime": null,
|
||||
"synchronized": true,
|
||||
"tty": false,
|
||||
"user": "root",
|
||||
"uuid": "c1dd4e1e-1356-411c-8613-e15146633640",
|
||||
"working_dir": "/app"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
A container is a representation of a Docker container in a node.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
uuid | A unique identifier for the container generated automatically on creation
|
||||
resource_uri | A unique API endpoint that represents the container
|
||||
image_name | The Docker image name and tag of the container
|
||||
bindings | A list of volume bindings that the container has mounted (see table `Container Binding attributes` below)
|
||||
name | A user provided name for the container (inherited from the service)
|
||||
node | The resource URI of the node where this container is running
|
||||
service | The resource URI of the service which this container is part of
|
||||
public_dns | The external FQDN of the container
|
||||
state | The state of the container (see table `Container states` below)
|
||||
synchronized | Flag indicating if the container is synchronized with the current service definition.
|
||||
exit_code | The numeric exit code of the container (if applicable, `null` otherwise)
|
||||
exit_code_msg | A string representation of the exit code of the container (if applicable, `null` otherwise)
|
||||
deployed_datetime | The date and time of the last deployment of the container (if applicable, `null` otherwise)
|
||||
started_datetime | The date and time of the last `start` operation on the container (if applicable, `null` otherwise)
|
||||
stopped_datetime | The date and time of the last `stop` operation on the container (if applicable, `null` otherwise)
|
||||
destroyed_datetime | The date and time of the `terminate` operation on the container (if applicable, `null` otherwise)
|
||||
container_ports | List of published ports of this container (see table `Container Port attributes` below)
|
||||
container_envvars | List of user-defined environment variables set on the containers of the service, which will override the container environment variables (see table `Container Environment Variable attributes` below)
|
||||
labels | Container metadata in form of dictionary
|
||||
working_dir | Working directory for running binaries within a container
|
||||
user | User used on the container on launch
|
||||
hostname | Hostname used on the container on launch
|
||||
domainname | Domainname used on the container on launch
|
||||
mac_address | Ethernet device's MAC address used on the container on launch
|
||||
cgroup_name | Optional parent cgroup for the container.
|
||||
tty | If the container has the tty enable
|
||||
stdin_open | If the container has stdin opened
|
||||
dns | Container custom DNS servers
|
||||
dns_search | Container custom DNS search domain
|
||||
cap_add | Container added capabilities
|
||||
cap_drop | Container dropped capabilities
|
||||
devices | List of container device mappings
|
||||
extra_hosts | List of container hostname mappings
|
||||
secuirty_opt | Labeling scheme of this container
|
||||
entrypoint | Entrypoint used on the container on launch
|
||||
run_command | Run command used on the container on launch
|
||||
cpu_shares | The relative CPU priority of the container (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
cpuset | CPUs in which execution is allowed
|
||||
memory | The memory limit of the container in MB (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
memory_swap | Total memory limit (memory + swap) of the container in MB
|
||||
autorestart | Whether to restart the container automatically if it stops (see [Crash recovery](/docker-cloud/apps/autorestart/) for more information)
|
||||
autodestroy | Whether to terminate the container automatically if it stops (see [Autodestroy](/docker-cloud/apps/auto-destroy/) for more information)
|
||||
roles | List of Docker Cloud roles asigned to this container (see [API roles](/docker-cloud/apps/api-roles/) for more information))
|
||||
linked_to_container | List of IP addresses of the linked containers (see table `Container Link attributes` below and [Service links](/docker-cloud/apps/service-links/) for more information)
|
||||
link_variables | List of environment variables that would be exposed in any container that is linked to this one
|
||||
privileged | Whether the container has Docker's `privileged` flag set or not (see [Runtime privilege](/engine/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration) for more information)
|
||||
read_only | Whether the container filesystem is read-only or not
|
||||
private_ip | IP address of the container on the overlay network. This IP will be reachable from any other container.
|
||||
net | Network mode set on the container (see table `Network Modes` below, [more information](/engine/reference/run/#network-settings))
|
||||
pid | PID (Process) Namespace mode for the container ([more information](/engine/reference/run/#pid-settings-pid))
|
||||
|
||||
|
||||
### Container Binding attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
host_path | The host path of the volume
|
||||
container_path | The container path where the volume is mounted
|
||||
rewritable | `true` is the volume has writable permissions
|
||||
volume | The resource URI of the volume
|
||||
|
||||
|
||||
### Container Port attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
protocol | The protocol of the port, either `tcp` or `udp`
|
||||
inner_port | The published port number inside the container
|
||||
outer_port | The published port number in the node public network interface
|
||||
port_name | Name of the service associated to this port
|
||||
uri_protocol | The protocol to be used in the endpoint for this port (i.e. `http`)
|
||||
endpoint_uri | The URI of the endpoint for this port
|
||||
published | Whether the port has been published in the host public network interface or not. Non-published ports can only be accessed via links.
|
||||
|
||||
|
||||
### Container Environment Variable attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
key | The name of the environment variable
|
||||
value | The value of the environment variable
|
||||
|
||||
|
||||
### Container States
|
||||
|
||||
State | Description
|
||||
----- | -----------
|
||||
Starting | The container is being deployed or started (from Stopped). No actions allowed in this state.
|
||||
Running | The container is deployed and running. Possible actions in this state: `stop`, `terminate`.
|
||||
Stopping | The container is being stopped. No actions allowed in this state.
|
||||
Stopped | The container is stopped. Possible actions in this state: `start`, `terminate`.
|
||||
Terminating | The container is being deleted. No actions allowed in this state.
|
||||
Terminated | The container has been deleted. No actions allowed in this state.
|
||||
|
||||
|
||||
### Network Modes
|
||||
|
||||
Strategy | Description
|
||||
-------- | -----------
|
||||
bridge | Creates a new network stack for the container on the docker bridge.
|
||||
host | Uses the host network stack inside the container.
|
||||
|
||||
|
||||
### Container Link attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
name | The name given to the link
|
||||
from_container | The resource URI of the "client" container
|
||||
to_container | The resource URI of the "server" container being linked
|
||||
endpoints | A dictionary with the endpoints (protocol, IP and port) to be used to reach each of the "server" container exposed ports
|
||||
|
||||
|
||||
## List all containers
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
containers = dockercloud.Container.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
containerList, err := dockercloud.ListContainers()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(containerList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/container/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container ps
|
||||
```
|
||||
|
||||
Lists all current and recently terminated containers. Returns a list of `Container` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]container/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
state | Filter by state. Possible values: `Starting`, `Running`, `Stopping`, `Stopped`, `Terminating`, `Terminated`
|
||||
name | Filter by container name
|
||||
service | Filter by resource URI of the target service.
|
||||
node | Filter by resource URI of the target node.
|
||||
|
||||
## Get an existing container
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockerckoud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(container)
|
||||
```
|
||||
|
||||
|
||||
```http
|
||||
GET /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container inspect 7eaf7fff
|
||||
```
|
||||
|
||||
Get all the details of an specific container
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]container/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to retrieve
|
||||
|
||||
|
||||
## Get the logs of a container
|
||||
|
||||
> Example log line
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "log",
|
||||
"log": "Log line from the container",
|
||||
"streamType": "stdout",
|
||||
"timestamp": 1433779324
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
def log_handler(message):
|
||||
print message
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.logs(tail=300, follow=True, log_handler=log_handler)
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("447ecddc-2890-4ea2-849b-99392e0dd7a6")
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
c := make(chan dockercloud.Logs)
|
||||
|
||||
go container.Logs(c)
|
||||
for {
|
||||
s := <-c
|
||||
log.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/logs/ HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container logs 7eaf7fff
|
||||
```
|
||||
|
||||
Get the logs of the specified container.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **STREAM API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]container/(uuid)/logs/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to retrieve logs
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
tail | Number of lines to show from the end of the logs (default: `300`)
|
||||
follow | Whether to stream logs or close the connection immediately (default: true)
|
||||
service | Filter by service (resource URI)
|
||||
|
||||
|
||||
## Start a container
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.start()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = container.Start(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/start/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container start 7eaf7fff
|
||||
```
|
||||
|
||||
Starts a stopped container.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]container/(uuid)/start/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to start
|
||||
|
||||
|
||||
## Stop a container
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
container = dockerlcoud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.stop()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = container.Stop(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/stop/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container stop 7eaf7fff
|
||||
```
|
||||
|
||||
Stops a running container.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]container/(uuid)/stop/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to stop
|
||||
|
||||
|
||||
|
||||
## Redeploy a container
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.redeploy()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: true) to reuse the existing volumes
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}) to not reuse the existing volumes
|
||||
if err = container.Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/start/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container redeploy 7eaf7fff
|
||||
```
|
||||
|
||||
Redeploys a container.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]container/(uuid)/redeploy/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to redeploy
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
reuse_volumes | Whether to reuse container volumes for this redeploy operation or not (default: `true`).
|
||||
|
||||
|
||||
## Terminate a container
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.delete()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = container.Terminate(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```http
|
||||
DELETE /api/app/v1/container/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud container terminate 7eaf7fff
|
||||
```
|
||||
|
||||
Terminates the specified container. This is not reversible. All data stored in the container will be permanently deleted.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/app/v1/[optional_namespace/]container/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container to terminate
|
||||
|
||||
|
||||
## Execute command inside a container
|
||||
|
||||
```
|
||||
import dockercloud
|
||||
|
||||
def msg_handler(message):
|
||||
print message
|
||||
|
||||
container = dockercloud.Container.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
container.execute("ls", handler=msg_handler)
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
container, err := dockercloud.GetContainer("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
c := make(chan dockercloud.Exec)
|
||||
|
||||
container.Exec("ls", c)
|
||||
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/container/(uuid)/exec/ HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
docker-cloud exec 7eaf7fff ls
|
||||
```
|
||||
|
||||
Executes a command inside the specified running container, creating a bi-directional stream for the process' standard input and output. This endpoint can be connected to using a bi-directional Secure Web Socket `wss://ws.cloud.docker.com/api/app/v1/container/(uuid)/exec/`
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **STREAM API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]container/(uuid)/exec/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the container where the command will be executed
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
command | Command to be executed (default: `sh`)
|
||||
@@ -1,135 +0,0 @@
|
||||
# Docker Cloud Events
|
||||
|
||||
## Docker Cloud Event
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "action",
|
||||
"action": "update",
|
||||
"parents": [
|
||||
"/api/app/v1/user_namespace/container/0b0e3538-88df-4f07-9aed-3a3cc4175076/"
|
||||
],
|
||||
"resource_uri": "/api/app/v1/user_namespace/action/49f0efe8-a704-4a10-b02f-f96344fabadd/",
|
||||
"state": "Success",
|
||||
"uuid": "093ba3bb-08dd-48f0-8f12-4d3b85ef85b3",
|
||||
"datetime": "2016-02-01T16:47:28Z"
|
||||
}
|
||||
```
|
||||
|
||||
Docker Cloud events are generated every time any of the following objects is created or changes state:
|
||||
|
||||
* Stack
|
||||
* Service
|
||||
* Container
|
||||
* Node Cluster
|
||||
* Node
|
||||
* Action
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
| Attribute | Description |
|
||||
|:-------------|:---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| type | Type of object that was created or updated. For possible values, check the [events types](#event-types) table below. |
|
||||
| action | Type of action that was executed on the object. Possible values: `create`, `update` or `delete` |
|
||||
| parents | List of resource URIs (REST API) of the parents of the object, according to the "Parent-child hierarchy" table below |
|
||||
| resource_uri | Resource URI (REST API) of the object that was created or updated. You can do a `GET` operation on this URL to fetch its details |
|
||||
| state | The current state of the object |
|
||||
| uuid | Unique identifier for the event |
|
||||
| datetime | Date and time of the event in ISO 8601 format |
|
||||
|
||||
|
||||
### Event types
|
||||
|
||||
| Type | Description |
|
||||
|:------------|:-----------------------------------------------------------------------------------------------|
|
||||
| stack | Whenever a `Stack` is created or updated |
|
||||
| service | Whenever a `Service` is created or updated |
|
||||
| container | Whenever a `Container` is created or updated |
|
||||
| nodecluster | Whenever a `Node Cluster` is created or updated |
|
||||
| node | Whenever a `Node` is created or updated |
|
||||
| action | Whenever a `Action` is created or updated |
|
||||
| error | Sent when an error occurs on the websocket connection or as part of the authentication process |
|
||||
|
||||
|
||||
### Parent-child hierarchy
|
||||
|
||||
| Object type | Parent types |
|
||||
|:-------------|:----------------------------------------|
|
||||
| Stack | (None) |
|
||||
| Service | Stack |
|
||||
| Container | Service, Stack, Node, Node Cluster |
|
||||
| Node Cluster | (None) |
|
||||
| Node | Node Cluster |
|
||||
| Action | (object to which the action applies to) |
|
||||
|
||||
|
||||
## Listen to new Docker Cloud Events
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
def process_event(event):
|
||||
print event
|
||||
|
||||
events = dockercloud.Events()
|
||||
events.on_message(process_event)
|
||||
events.run_forever()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
// Listens for container events only
|
||||
myFilter := dockercloud.NewStreamFilter(&dockercloud.EventFilter{Type: "container"})
|
||||
|
||||
stream := dockercloud.NewStream(myFilter)
|
||||
|
||||
if err := stream.Connect(); err == nil {
|
||||
go stream.RunForever()
|
||||
} else {
|
||||
log.Print("Connect err: " + err.Error())
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case event := <-stream.MessageChan:
|
||||
log.Println(event)
|
||||
case err := <-stream.ErrorChan:
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/audit/v1/events/ HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud event
|
||||
```
|
||||
|
||||
Listens for new Docker Cloud Events
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **STREAM API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/audit/v1/[optional_namespace/]events/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
type | Filter by type
|
||||
object | Filter by object resource URI
|
||||
parent | Filter by object parents
|
||||
@@ -1,370 +0,0 @@
|
||||
# Nodes
|
||||
|
||||
## Node
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"availability_zone": "/api/infra/v1/az/testing-provider/testing-region/testing-az/",
|
||||
"cpu": 1,
|
||||
"current_num_containers": 4,
|
||||
"deployed_datetime": "Tue, 16 Sep 2014 17:01:15 +0000",
|
||||
"destroyed_datetime": null,
|
||||
"disk": 60,
|
||||
"docker_execdriver": "native-0.2",
|
||||
"docker_graphdriver": "aufs",
|
||||
"docker_version": "1.5.0",
|
||||
"external_fqdn": "fc1a5bb9-user.node.dockerapp.io",
|
||||
"last_seen": "Thu, 25 Sep 2014 13:14:44 +0000",
|
||||
"memory": 1792,
|
||||
"nickname": "fc1a5bb9-user.node.dockerapp.io",
|
||||
"node_cluster": "/api/infra/v1/user_namespace/nodecluster/d787a4b7-d525-4061-97a0-f423e8f1d229/",
|
||||
"node_type": "/api/infra/v1/user_namespace/nodetype/testing-provider/testing-type/",
|
||||
"public_ip": "10.45.2.11",
|
||||
"region": "/api/infra/v1/region/testing-provider/testing-region/",
|
||||
"resource_uri": "/api/infra/v1/user_namespace/node/fc1a5bb9-17f5-4819-b667-8c7cd819e949/",
|
||||
"state": "Deployed",
|
||||
"tags": [
|
||||
{"name": "tag_one"},
|
||||
{"name": "tag-two"}
|
||||
],
|
||||
"tunnel": "https://tunnel01.cloud.docker.com:12345",
|
||||
"uuid": "fc1a5bb9-17f5-4819-b667-8c7cd819e949"
|
||||
}
|
||||
```
|
||||
|
||||
A node is a virtual machine provided by a cloud provider where containers can be deployed.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
availability_zone | The resource URI of the availability zone where the node is deployed, if any
|
||||
uuid | A unique identifier for the node generated automatically on creation
|
||||
resource_uri | A unique API endpoint that represents the node
|
||||
external_fqdn | An automatically generated FQDN for the node. Containers deployed on this node will inherit this FQDN.
|
||||
state | The state of the node. See the below table for a list of possible states.
|
||||
node_cluster | The resource URI of the node cluster to which this node belongs to (if applicable)
|
||||
node_type | The resource URI of the node type used for the node
|
||||
region | The resource URI of the region where the node is deployed
|
||||
docker_execdriver | Docker's execution driver used in the node
|
||||
docker_graphdriver | Docker's storage driver used in the node
|
||||
docker_version | Docker's version used in the node
|
||||
cpu | Node number of CPUs
|
||||
disk | Node storage size in GB
|
||||
memory | Node memory in MB
|
||||
current_num_containers | The actual number of containers deployed in this node
|
||||
last_seen | Date and time of the last time the node was contacted by Docker Cloud
|
||||
public_ip | The public IP allocated to the node
|
||||
tunnel | If the node does not accept incoming connections to port 2375, the address of the reverse tunnel to access the docker daemon, or `null` otherwise
|
||||
deployed_datetime | The date and time when this node cluster was deployed
|
||||
destroyed_datetime | The date and time when this node cluster was terminated (if applicable)
|
||||
tags | List of tags to identify the node when deploying services (see [Tags](/docker-cloud/apps/deploy-tags/) for more information)
|
||||
nickname | A user-friendly name for the node (`external_fqdn` by default)
|
||||
|
||||
|
||||
### Node states
|
||||
|
||||
State | Description
|
||||
----- | -----------
|
||||
Deploying | The node is being deployed in the cloud provider. No actions allowed in this state.
|
||||
Deployed | The node is deployed and provisioned and is ready to deploy containers. Possible actions in this state: `terminate`, `docker-upgrade`.
|
||||
Unreachable | The node is deployed but Docker Cloud cannot connect to the docker daemon. Possible actions in this state: `health-check` and `terminate`.
|
||||
Upgrading | The node docker daemon is being upgraded. No actions allowed in this state.
|
||||
Terminating | The node is being terminated in the cloud provider. No actions allowed in this state.
|
||||
Terminated | The node has been terminated and is no longer present in the cloud provider. No actions allowed in this state.
|
||||
|
||||
|
||||
## List all nodes
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodes = dockercloud.Node.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodeList, err := dockercloud.ListNodes()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodeList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/node/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud node ls
|
||||
```
|
||||
|
||||
Lists all current and recently terminated nodes. Returns a list of `Node` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/[optional_namespace/]node/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
state | Filter by state. Possible values: `Deploying`, `Deployed`, `Unreachable`, `Upgrading`, `Terminating`, `Terminated`
|
||||
node_cluster | Filter by resource URI of the target node cluster
|
||||
node_type | Filter by resource URI of the target node type
|
||||
region | Filter by resource URI of the target region
|
||||
docker_version | Filter by Docker engine version running in the nodes
|
||||
|
||||
|
||||
|
||||
## Get an existing node
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
node = dockercloud.Node.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
node, err := dockercloud.GetNode("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(node)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/node/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud node inspect 7eaf7fff
|
||||
```
|
||||
|
||||
Get all the details of an specific node
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/[optional_namespace/]node/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node to retrieve
|
||||
|
||||
|
||||
## Update a node
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
node = dockercloud.Node.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
node.tags.add(["tag-1"])
|
||||
node.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
node, err := dockercloud.GetNode("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = node.Update(dockercloud.Node{Tags: []string{{Name: "tag-1"}}}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
PATCH /api/infra/v1/node/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
|
||||
{"tags": [{"name": "tag-1"}], "nickname": "dev node"}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud tag add -t tag-1 7eaf7fff
|
||||
docker-cloud tag set -t tag-2 7eaf7fff
|
||||
```
|
||||
|
||||
Names the node with a user-friendly name and/or replaces the old tags for the new list provided.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`PATCH /api/infra/v1/[optional_namespace/]node/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node to retrieve
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
nickname | (optional) A user-friendly name for the node (`external_fqdn` by default)
|
||||
tags | (optional) List of tags the node will have. This operation replaces the user tag list.
|
||||
|
||||
|
||||
## Upgrade Docker Daemon
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
node = dockercloud.Node.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
node.upgrade_docker()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
node, err := dockercloud.GetNode("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = node.Upgrade(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/infra/v1/node/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/docker-upgrade/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud node upgrade 7eaf7fff
|
||||
```
|
||||
|
||||
Upgrades the docker daemon of the node. This will restart your containers on that node. See [Docker upgrade](/docker-cloud/infrastructure/docker-upgrade/) for more information.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/infra/v1/[optional_namespace/]node/(uuid)/docker-upgrade/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node to upgrade
|
||||
|
||||
|
||||
## Perform a health check of a node
|
||||
|
||||
```http
|
||||
POST /api/infra/v1/node/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/health-check/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Tests connectivity between Docker Cloud and the node. Updates the node status to `Deployed` if the check was successful, or to `Unreachable` otherwise.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/infra/v1/[optional_namespace/]node/(uuid)/health-check/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node to perform the health check to
|
||||
|
||||
|
||||
## Terminate a node
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
node = dockercloud.Node.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
node.delete()
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/infra/v1/node/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
node, err := dockercloud.GetNode("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = node.Terminate(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud node rm 7eaf7fff
|
||||
```
|
||||
|
||||
Terminates the specified node.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/infra/v1/[optional_namespace/]node/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node to terminate
|
||||
@@ -1,412 +0,0 @@
|
||||
# Node Clusters
|
||||
|
||||
## Node Cluster
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"current_num_nodes": 1,
|
||||
"deployed_datetime": "Tue, 16 Sep 2014 17:01:15 +0000",
|
||||
"destroyed_datetime": null,
|
||||
"disk": 60,
|
||||
"nickname": "my test cluster",
|
||||
"name": "TestCluster",
|
||||
"node_type": "/api/infra/v1/nodetype/aws/t2.micro/",
|
||||
"nodes": [
|
||||
"/api/infra/v1/user_namespace/node/75d20367-0948-4f10-8ba4-ffb4d16ed3c6/"
|
||||
],
|
||||
"region": "/api/infra/v1/region/aws/us-east-1/",
|
||||
"resource_uri": "/api/infra/v1/user_namespace/nodecluster/5516df0b-721e-4470-b350-741ff22e63a0/",
|
||||
"state": "Deployed",
|
||||
"tags": [
|
||||
{"name": "tag_one"},
|
||||
{"name": "tag-two"},
|
||||
{"name": "tagthree3"}
|
||||
],
|
||||
"target_num_nodes": 2,
|
||||
"uuid": "5516df0b-721e-4470-b350-741ff22e63a0",
|
||||
"provider_options": {
|
||||
"vpc": {
|
||||
"id": "vpc-aa1c70d4",
|
||||
"subnets": ["subnet-aaa7d94f", "subnet-aa15fa64"],
|
||||
"security_groups": ["sg-aa1c70d4"]
|
||||
},
|
||||
"iam": {
|
||||
"instance_profile_name": "my_instance_profile"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A node cluster is a group of nodes that share the same provider, region and/or availability zone, and node type. They are on the same private network.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
uuid | A unique identifier for the node cluster generated automatically on creation
|
||||
resource_uri | A unique API endpoint that represents the node cluster
|
||||
name | A user provided name for the node cluster
|
||||
state | The state of the node cluster. See the below table for a list of possible states.
|
||||
node_type | The resource URI of the node type used for the node cluster
|
||||
disk | The size of the disk where images and containers are stored (in GB)
|
||||
nodes | A list of resource URIs of the `Node` objects on the node cluster
|
||||
region | The resource URI of the `Region` object where the node cluster is deployed
|
||||
target_num_nodes | The desired number of nodes for the node cluster
|
||||
current_num_nodes | The actual number of nodes in the node cluster. This may differ from `target_num_nodes` if the node cluster is being deployed or scaled
|
||||
deployed_datetime | The date and time when this node cluster was deployed
|
||||
destroyed_datetime | The date and time when this node cluster was terminated (if applicable)
|
||||
tags | List of tags to identify the node cluster nodes when deploying services (see [Tags](/docker-cloud/apps/deploy-tags/) for more information)
|
||||
provider_options | Provider-specific extra options for the deployment of the node (see `Provider options` table below for more information)
|
||||
nickname | A user-friendly name for the node cluster (`name` by default)
|
||||
|
||||
|
||||
### Node Cluster states
|
||||
|
||||
State | Description
|
||||
----- | -----------
|
||||
Init | The node cluster has been created and has no deployed containers yet. Possible actions in this state: `deploy`, `terminate`.
|
||||
Deploying | All nodes in the cluster are either deployed or being deployed. No actions allowed in this state.
|
||||
Deployed | All nodes in the cluster are deployed and provisioned. Possible actions in this state: `terminate`.
|
||||
Partly deployed | One or more nodes of the cluster are deployed and running. Possible actions in this state: `terminate`.
|
||||
Scaling | The cluster is either deploying new nodes or terminating existing ones responding to a scaling request. No actions allowed in this state.
|
||||
Terminating | All nodes in the cluster are either being terminated or already terminated. No actions allowed in this state.
|
||||
Terminated | The node cluster and all its nodes have been terminated. No actions allowed in this state.
|
||||
Empty cluster | There are no nodes deployed in this cluster. Possible actions in this state: `terminate`.
|
||||
|
||||
|
||||
### Provider options
|
||||
|
||||
You can specify the following options when using the Amazon Web Services provider:
|
||||
|
||||
* `vpc`: VPC-related options (optional)
|
||||
* `id`: AWS VPC identifier of the target VPC where the nodes of the cluster will be deployed (required)
|
||||
* `subnets`: a list of target subnet identifiers inside selected VPC. If you specify more than one subnet, Docker Cloud will balance among all of them following a high-availability schema (optional)
|
||||
* `security_groups`: the security group that will be applied to every node of the cluster (optional)
|
||||
* `iam`: IAM-related options (optional)
|
||||
* `instance_profile_name`: name of the instance profile (container for instance an IAM role) to attach to every node of the cluster (required)
|
||||
|
||||
|
||||
## List all node clusters
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodeclusters = dockercloud.NodeCluster.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodeclusters, err := dockercloud.ListNodeClusters()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodeclusters)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/nodecluster/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster ls
|
||||
```
|
||||
|
||||
Lists all current and recently terminated node clusters. Returns a list of `NodeCluster` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/[optional_namespace/]nodecluster/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
state | Filter by state. Possible values: `Init`, `Deploying`, `Deployed`, `Partly deployed`, `Scaling`, `Terminating`, `Terminated`, `Empty cluster`
|
||||
name | Filter by node cluster name
|
||||
region | Filter by resource URI of the target region
|
||||
node_type | Filter by resource URI of the target node type
|
||||
|
||||
|
||||
## Create a new node cluster
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
region = dockercloud.Region.fetch("digitalocean/lon1")
|
||||
node_type = dockercloud.NodeType.fetch("digitalocean/1gb")
|
||||
nodecluster = dockercloud.NodeCluster.create(name="my_cluster", node_type=node_type, region=region, disk=60)
|
||||
nodecluster.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodecluster, err := dockercloud.CreateNodeCluster(dockercloud.NodeCreateRequest{Name: "my_cluster", Region: "/api/infra/v1/region/digitalocean/lon1/", NodeType: "/api/infra/v1/nodetype/digitalocean/1gb/", Target_num_nodes: 2})
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodecluster)
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/infra/v1/nodecluster/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"name": "my_cluster", "region": "/api/infra/v1/region/digitalocean/lon1/", "node_type": "/api/infra/v1/nodetype/digitalocean/1gb/", "disk": 60}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster create my_cluster digitalocean lon1 1gb
|
||||
```
|
||||
|
||||
Creates a new node cluster without deploying it.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/infra/v1/[optional_namespace/]nodecluster/`
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | (required) A user provided name for the node cluster
|
||||
node_type | (required) The resource URI of the node type to be used for the node cluster
|
||||
region | (required) The resource URI of the region where the node cluster is to be deployed
|
||||
disk | (optional) The size of the volume to create where images and containers will be stored, in GB (default: `60`). Not available for Digital Ocean. To create Softlayer nodes you must select one of the following sizes (in GBs): 10, 20, 25, 30, 40, 50, 75, 100, 125, 150, 175, 200, 250, 300, 350, 400, 500, 750, 1000, 1500 or 2000
|
||||
nickname | (optional) A user-friendly name for the node cluster (`name` by default)
|
||||
target_num_nodes | (optional) The desired number of nodes for the node cluster (default: `1`)
|
||||
tags | (optional) List of tags of the node cluster to be used when deploying services see [Tags](/docker-cloud/apps/deploy-tags/) for more information) (default: `[]`)
|
||||
provider_options | Provider-specific extra options for the deployment of the node (see table `Provider options` above for more information)
|
||||
|
||||
|
||||
## Get an existing node cluster
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.NodeCluster.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodecluster, err := dockercloud.GetNodeCluster("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodecluster)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/nodecluster/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster inspect 7eaf7fff
|
||||
```
|
||||
|
||||
Get all the details of an specific node cluster
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/[optional_namespace/]nodecluster/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node cluster to retrieve
|
||||
|
||||
## Deploy a node cluster
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodecluster = dockercloud.NodeCluster.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
nodecluster.deploy()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodecluster, err := dockercloud.GetNodeCluster("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = nodecluster.Deploy(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/infra/v1/nodecluster/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/deploy/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Deploys and provisions a recently created node cluster in the specified region and cloud provider.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/infra/v1/[optional_namespace/]nodecluster/(uuid)/deploy/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node cluster to deploy
|
||||
|
||||
## Update an existing node cluster
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodecluster = dockercloud.NodeCluster.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
nodecluster.target_num_nodes = 3
|
||||
nodecluster.tags.add("tag-1")
|
||||
nodecluster.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodecluster, err := dockercloud.GetNodeCluster("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = nodecluster.Update(dockercloud.NodeCreateRequest{Target_num_nodes: 4}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
PATCH /api/infra/v1/nodecluster/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"target_num_nodes": 3, "tags": [{"name": "tag-1"}]}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster scale 7eaf7fff 3
|
||||
docker-cloud tag add -t tag-1 7eaf7fff
|
||||
docker-cloud tag set -t tag-2 7eaf7fff
|
||||
```
|
||||
|
||||
Updates the node cluster details and applies the changes automatically.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`PATCH /api/infra/v1/[optional_namespace/]nodecluster/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node cluster to update
|
||||
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
target_num_nodes | (optional) The number of nodes to scale this node cluster to
|
||||
tags | (optional) List of tags the node cluster (and nodes within the node cluster) will have. This operation replaces the user tag list.
|
||||
## Terminate a node cluster
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodecluster = dockercloud.NodeCluster.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
nodecluster.delete()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodecluster, err := dockercloud.GetNodeCluster("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = nodecluster.Terminate(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/infra/v1/nodecluster/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
dockercloud nodecluster rm 7eaf7fff
|
||||
```
|
||||
|
||||
Terminates all the nodes in a node cluster and the node cluster itself. This is not reversible.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/infra/v1/[optional_namespace/]nodecluster/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the node cluster to terminate
|
||||
@@ -1,137 +0,0 @@
|
||||
# Node Types
|
||||
|
||||
## Node Type
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"availability_zones": [],
|
||||
"available": true,
|
||||
"label": "1GB",
|
||||
"name": "1gb",
|
||||
"provider": "/api/infra/v1/provider/digitalocean/",
|
||||
"regions": [
|
||||
"/api/infra/v1/region/digitalocean/ams1/",
|
||||
"/api/infra/v1/region/digitalocean/sfo1/",
|
||||
"/api/infra/v1/region/digitalocean/nyc2/",
|
||||
"/api/infra/v1/region/digitalocean/ams2/",
|
||||
"/api/infra/v1/region/digitalocean/sgp1/",
|
||||
"/api/infra/v1/region/digitalocean/lon1/",
|
||||
"/api/infra/v1/region/digitalocean/nyc3/",
|
||||
"/api/infra/v1/region/digitalocean/nyc1/"
|
||||
],
|
||||
"resource_uri": "/api/infra/v1/nodetype/digitalocean/1gb/"
|
||||
}
|
||||
```
|
||||
|
||||
A node type is a representation of an instance size supported by a certain cloud provider in a certain region and/or availability zone.
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
resource_uri | A unique API endpoint that represents the node type
|
||||
name | An identifier for the node type
|
||||
label | A user-friendly name for the node type
|
||||
regions | A list of resource URIs of the regions to which this node type can be deployed to
|
||||
availability_zones | A list of resource URIs of the availability zones to which this node type can be deployed to
|
||||
provider | The resource URI of the provider of the node type
|
||||
available | Whether the node type is currently available for new node deployments
|
||||
|
||||
|
||||
## List all node types
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodetypes = dockercloud.NodeType.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodetypeList, err := dockercloud.ListNodeTypes()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodetypeList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/nodetype/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster nodetype
|
||||
```
|
||||
|
||||
Lists all node types of all supported cloud providers. Returns a list of `NodeType` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/nodetype/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by node type name
|
||||
regions | Filter by resource URI of the target regions
|
||||
availability_zones | Filter by resource URI of the target availability zones
|
||||
|
||||
|
||||
## Get an individual node type
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
nodetype = dockercloud.NodeType.fetch("digitalocean/1gb")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
nodetype, err := dockercloud.GetNodeType("digitalocean","1gb")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(nodetype)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/nodetype/digitalocean/1gb/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
|
||||
Get all the details of a specific node type
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/nodetype/(provider.name)/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the node type to retrieve
|
||||
provider.name | The name of the provider of the node type
|
||||
@@ -1,132 +0,0 @@
|
||||
# Providers
|
||||
|
||||
## Provider
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"available": true,
|
||||
"label": "Digital Ocean",
|
||||
"name": "digitalocean",
|
||||
"regions": [
|
||||
"/api/infra/v1/region/digitalocean/ams1/",
|
||||
"/api/infra/v1/region/digitalocean/ams2/",
|
||||
"/api/infra/v1/region/digitalocean/ams3/",
|
||||
"/api/infra/v1/region/digitalocean/lon1/",
|
||||
"/api/infra/v1/region/digitalocean/nyc1/",
|
||||
"/api/infra/v1/region/digitalocean/nyc2/",
|
||||
"/api/infra/v1/region/digitalocean/nyc3/",
|
||||
"/api/infra/v1/region/digitalocean/sfo1/",
|
||||
"/api/infra/v1/region/digitalocean/sgp1/"
|
||||
],
|
||||
"resource_uri": "/api/infra/v1/provider/digitalocean/"
|
||||
}
|
||||
```
|
||||
|
||||
A provider is a representation of a cloud provider supported by Docker Cloud. Providers have one or more regions where nodes are deployed.
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
resource_uri | A unique API endpoint that represents the provider
|
||||
name | A unique identifier for the provider
|
||||
label | A user-friendly name for the provider
|
||||
regions | A list of resource URIs of the regions available in this provider
|
||||
available | Whether the provider is currently available for new node deployments
|
||||
|
||||
|
||||
## List all providers
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
providers = dockercloud.Provider.list()
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/provider/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
providerList, err := dockercloud.ListProviders()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(providerList)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster provider
|
||||
```
|
||||
|
||||
Lists all supported cloud providers. Returns a list of `Provider` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/provider/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by provider name
|
||||
|
||||
|
||||
|
||||
## Get an individual provider
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
provider = dockercloud.Provider.fetch("digitalocean")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
provider, err := dockercloud.GetProvider("digitalocean")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(provider)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/provider/digitalocean/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
|
||||
Get all the details of a specific provider
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/provider/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the provider to retrieve
|
||||
@@ -1,137 +0,0 @@
|
||||
# Regions
|
||||
|
||||
## Region
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"availability_zones": [],
|
||||
"available": true,
|
||||
"label": "Amsterdam 2",
|
||||
"name": "ams2",
|
||||
"node_types": [
|
||||
"/api/infra/v1/nodetype/digitalocean/1gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/2gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/4gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/8gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/16gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/32gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/48gb/",
|
||||
"/api/infra/v1/nodetype/digitalocean/64gb/"
|
||||
],
|
||||
"provider": "/api/infra/v1/provider/digitalocean/",
|
||||
"resource_uri": "/api/infra/v1/region/digitalocean/ams2/"
|
||||
}
|
||||
```
|
||||
|
||||
A region is a representation of an entire or a subset of a data center of a cloud provider. It can contain availability zones (depending on the provider) and one or more node types.
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
resource_uri | A unique API endpoint that represents the region
|
||||
name | An identifier for the region
|
||||
label | A user-friendly name for the region
|
||||
node_types | A list of resource URIs of the node types available in the region
|
||||
availability_zones | A list of resource URIs of the availability zones available in the region
|
||||
provider | The resource URI of the provider of the region
|
||||
available | Whether the region is currently available for new node deployments
|
||||
|
||||
|
||||
## List all regions
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
regions = dockercloud.Region.list()
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/region/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
regionList, err := dockercloud.ListRegions()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(regionList)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud nodecluster region
|
||||
```
|
||||
|
||||
Lists all regions of all supported cloud providers. Returns a list of `Region` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/region/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by region name
|
||||
provider | Filter by resource URI of the target provider
|
||||
|
||||
|
||||
|
||||
## Get an individual region
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
region = dockercloud.Region.fetch("digitalocean/lon1")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
region, err := dockercloud.GetRegion("digitalocean","lon1")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(region)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/region/digitalocean/lon1/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
|
||||
Get all the details of a specific region
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/region/(provider.name)/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the region to retrieve
|
||||
provider.name | The name of the provider of the region
|
||||
@@ -1,87 +0,0 @@
|
||||
# Registries
|
||||
|
||||
## Registry
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "registry-1.docker.io",
|
||||
"is_docker_registry": true,
|
||||
"is_ssl": true,
|
||||
"name": "Docker Hub",
|
||||
"port": 443,
|
||||
"resource_uri": "/api/repo/v1/user_namespace/registry/registry-1.docker.io/"
|
||||
}
|
||||
```
|
||||
|
||||
Represents a registry where repositories are hosted.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
resource_uri | A unique API endpoint that represents the registry
|
||||
name | Human-readable name of the registry
|
||||
host | FQDN of the registry, i.e. `registry-1.docker.io`
|
||||
is_docker_registry | Whether this registry is run by Docker
|
||||
is_ssl | Whether this registry has SSL activated or not
|
||||
port | The port number where the registry is listening to
|
||||
|
||||
|
||||
## List all registries
|
||||
|
||||
```http
|
||||
GET /api/repo/v1/registry/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Lists all current registries. Returns a list of `Registry` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/repo/v1/[optional_namespace/]registry/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
name | Filter by registry name
|
||||
host | Filter by registry host
|
||||
is_docker_registry | Filter by whether the registry is run by Docker or not. Possible values: 'true' or 'false'
|
||||
|
||||
|
||||
## Get an existing registry
|
||||
|
||||
```http
|
||||
GET /api/repo/v1/registry/registry-1.docker.io/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Gets all the details of an specific registry
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/v1/[optional_namespace/]registry/(host)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
host | The host of the registry to retrieve
|
||||
@@ -1,275 +0,0 @@
|
||||
# External Repositories
|
||||
|
||||
## External Repository
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"in_use": false,
|
||||
"name": "my.registry.com/myrepo",
|
||||
"registry": "/api/repo/v1/user_namespace/registry/my.registry.com/",
|
||||
"resource_uri": "/api/repo/v1/user_namespace/repository/my.registry.com/myrepo/",
|
||||
}
|
||||
```
|
||||
|
||||
The `repository` endpoint is used to add and remove existing repositories on third party registries to be used in deployments and builds.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
resource_uri | A unique API endpoint that represents the repository
|
||||
name | Name of the repository, i.e. `my.registry.com/myrepo`
|
||||
in_use | If the image is being used by any of your services
|
||||
registry | Resource URI of the registry where this image is hosted
|
||||
|
||||
|
||||
## List all external repositories
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
repositories = dockercloud.Repository.list()
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/repo/v1/repository/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
repositoriesList, err := dockercloud.ListRepositories()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Pringln(repositoriesList)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud repository ls
|
||||
```
|
||||
|
||||
Lists all added repositories from third party registries. Returns a list of `Repository` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/repo/v1/[optional_namespace/]repository/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by image name
|
||||
registry | Filter by resource URI of the target repository registry
|
||||
|
||||
|
||||
## Add a new external repository
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
repository = dockercloud.Repository.create(name="registry.local/user1/image1", username=username, password=password)
|
||||
repository.save()
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/repo/v1/repository/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"name": "registry.local/user1/image1", "username": "username", "password": "password"}
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
image, err := dockercloud.CreateImage(dockercloud.ImageCreateRequest{
|
||||
Name: "registry.local/user1/image1",
|
||||
Username: "username",
|
||||
Password: "password"
|
||||
})
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud repository register -u username -p password registry.local/user1/image1
|
||||
```
|
||||
|
||||
Adds an existing repository on a third party registry.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/repo/v1/[optional_namespace/]repository/`
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Name of the repository, i.e. 'my.registry.com/myrepo'
|
||||
username | Username to authenticate with the third party registry
|
||||
password | Password to authenticate with the third party registry
|
||||
|
||||
|
||||
## Get an external repository details
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
repository = dockercloud.Repository.fetch("registry.local/user1/image1")
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/repo/v1/repository/registry.local/user1/image1/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
repository, err = dockercloud.GetRepository("registry.local/user1/image1")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(repository)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud repository inspect registry.local/user1/image1
|
||||
```
|
||||
|
||||
Gets all the details of an specific repository
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/repo/v1/[optional_namespace/]repository/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the repository to retrieve
|
||||
|
||||
|
||||
## Update credentials of an external repository
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
repository = dockercloud.Repository.fetch("registry.local/user1/image1")
|
||||
repository.username = "new username"
|
||||
repository.password = "new password"
|
||||
repository.save()
|
||||
```
|
||||
|
||||
```http
|
||||
PATCH /api/repo/v1/repository/registry.local/user1/image1/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"username": "username", "password": "password"}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud repository update -n "new username" -p "new password" registry.local/user1/image1
|
||||
```
|
||||
|
||||
Updates the external repository credentials.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`PATCH /api/repo/v1/[optional_namespace/]repository/(name)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the repository to update
|
||||
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
username | Username to authenticate with the private registry
|
||||
password | Password to authenticate with the private registry
|
||||
|
||||
|
||||
## Remove an external repository
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
repository = dockercloud.Repository.fetch("registry.local/user1/image1")
|
||||
repository.delete()
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/repo/v1/repository/registry.local/user1/image1/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
repository, err = dockercloud.GetRepository("registry.local/user1/image1")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
repository.Remove()
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud repository rm registry.local/user1/image1
|
||||
```
|
||||
|
||||
Removes the external repository from Docker Cloud. It won't remove the repository from the third party registry where it's stored.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/repo/v1/[optional_namespace/]repository/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | The name of the external repository to remove
|
||||
@@ -1,935 +0,0 @@
|
||||
# Services
|
||||
|
||||
## Service
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"autodestroy": "OFF",
|
||||
"autoredeploy": false,
|
||||
"autorestart": "ON_FAILURE",
|
||||
"bindings": [
|
||||
{
|
||||
"host_path": null,
|
||||
"container_path": "/tmp",
|
||||
"rewritable": true,
|
||||
"volumes_from": null
|
||||
},
|
||||
{
|
||||
"host_path": "/etc",
|
||||
"container_path": "/etc",
|
||||
"rewritable": true,
|
||||
"volumes_from": null
|
||||
},
|
||||
{
|
||||
"host_path": null,
|
||||
"container_path": null,
|
||||
"rewritable": true,
|
||||
"volumes_from": "/api/app/v1/user_namespace/service/2f4f54e5-9d3b-4ac1-85ad-a2d4ff25a179/"
|
||||
}
|
||||
],
|
||||
"cap_add": [
|
||||
"ALL"
|
||||
],
|
||||
"cap_drop": [
|
||||
"NET_ADMIN",
|
||||
"SYS_ADMIN"
|
||||
],
|
||||
"container_envvars": [
|
||||
{
|
||||
"key": "DB_PASS",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"container_ports": [
|
||||
{
|
||||
"endpoint_uri": "http://wordpress-stackable.admin.srv.dockerapp.io:80/",
|
||||
"inner_port": 80,
|
||||
"outer_port": 80,
|
||||
"port_name": "http",
|
||||
"protocol": "tcp",
|
||||
"published": true
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
"/api/app/v1/user_namespace/container/6f8ee454-9dc3-4387-80c3-57aac1be3cc6/",
|
||||
"/api/app/v1/user_namespace/container/fdf9c116-7c08-4a60-b0ce-c54ca72c2f25/"
|
||||
],
|
||||
"cpu_shares": 100,
|
||||
"cpuset": "0,1",
|
||||
"cgroup_parent": "m-executor-abcd",
|
||||
"current_num_containers": 2,
|
||||
"deployed_datetime": "Mon, 13 Oct 2014 11:01:43 +0000",
|
||||
"deployment_strategy": "EMPTIEST_NODE",
|
||||
"destroyed_datetime": null,
|
||||
"devices": [
|
||||
"/dev/ttyUSB0:/dev/ttyUSB0"
|
||||
],
|
||||
"dns": [
|
||||
"8.8.8.8"
|
||||
],
|
||||
"dns_search": [
|
||||
"example.com"
|
||||
],
|
||||
"domainname": "domainname",
|
||||
"entrypoint": "",
|
||||
"extra_hosts": [
|
||||
"onehost:50.31.209.229"
|
||||
],
|
||||
"hostname": "hostname",
|
||||
"image_name": "tutum/wordpress-stackable:latest",
|
||||
"nickname": "wordpress-stackable",
|
||||
"labels": {
|
||||
"com.example.description": "Accounting webapp",
|
||||
"com.example.department": "Finance",
|
||||
"com.example.label-with-empty-value": ""
|
||||
},
|
||||
"link_variables": {
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_HOST": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_NAME": "wordpress",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_PASS": "szVaPz925B7I",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_PORT": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DB_USER": "admin",
|
||||
"WORDPRESS_STACKABLE_1_ENV_DEBIAN_FRONTEND": "noninteractive",
|
||||
"WORDPRESS_STACKABLE_1_ENV_HOME": "/",
|
||||
"WORDPRESS_STACKABLE_1_ENV_PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"WORDPRESS_STACKABLE_1_PORT": "tcp://wordpress-stackable-1.admin.cont.dockerapp.io:49153",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP": "tcp://wordpress-stackable-1.admin.cont.dockerapp.io:49153",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_ADDR": "wordpress-stackable-1.admin.cont.dockerapp.io",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_PORT": "49153",
|
||||
"WORDPRESS_STACKABLE_1_PORT_80_TCP_PROTO": "tcp",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DB_HOST": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DB_NAME": "wordpress",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DB_PASS": "szVaPz925B7I",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DB_PORT": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DB_USER": "admin",
|
||||
"WORDPRESS_STACKABLE_2_ENV_DEBIAN_FRONTEND": "noninteractive",
|
||||
"WORDPRESS_STACKABLE_2_ENV_HOME": "/",
|
||||
"WORDPRESS_STACKABLE_2_ENV_PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"WORDPRESS_STACKABLE_2_PORT": "tcp://wordpress-stackable-2.admin.cont.dockerapp.io:49154",
|
||||
"WORDPRESS_STACKABLE_2_PORT_80_TCP": "tcp://wordpress-stackable-2.admin.cont.dockerapp.io:49154",
|
||||
"WORDPRESS_STACKABLE_2_PORT_80_TCP_ADDR": "wordpress-stackable-2.admin.cont.dockerapp.io",
|
||||
"WORDPRESS_STACKABLE_2_PORT_80_TCP_PORT": "49154",
|
||||
"WORDPRESS_STACKABLE_2_PORT_80_TCP_PROTO": "tcp",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_HOST": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_NAME": "wordpress",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_PASS": "szVaPz925B7I",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_PORT": "**LinkMe**",
|
||||
"WORDPRESS_STACKABLE_ENV_DB_USER": "admin",
|
||||
"WORDPRESS_STACKABLE_ENV_DEBIAN_FRONTEND": "noninteractive",
|
||||
"WORDPRESS_STACKABLE_ENV_HOME": "/",
|
||||
"WORDPRESS_STACKABLE_ENV_PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"WORDPRESS_STACKABLE_PORT": "tcp://wordpress-stackable-1.admin.cont.dockerapp.io:49153",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP": "tcp://wordpress-stackable-1.admin.cont.dockerapp.io:49153",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_ADDR": "wordpress-stackable-1.admin.cont.dockerapp.io",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_PORT": "49153",
|
||||
"WORDPRESS_STACKABLE_PORT_80_TCP_PROTO": "tcp",
|
||||
"WORDPRESS_STACKABLE_DOCKERCLOUD_API_URL": "https://cloud.docker.com/api/app/v1/user_namespace/service/adeebc1b-1b81-4af0-b8f2-cefffc69d7fb/"
|
||||
},
|
||||
"linked_from_service": [],
|
||||
"linked_to_service": [
|
||||
{
|
||||
"from_service": "/api/app/v1/user_namespace/service/09cbcf8d-a727-40d9-b420-c8e18b7fa55b/",
|
||||
"name": "DB",
|
||||
"to_service": "/api/app/v1/user_namespace/service/72f175bd-390b-46e3-9463-830aca32ce3e/"
|
||||
}
|
||||
],
|
||||
"mac_address": "02:42:ac:11:65:43",
|
||||
"memory": 2048,
|
||||
"memory_swap": 8192,
|
||||
"name": "wordpress-stackable",
|
||||
"net": "bridge",
|
||||
"privileged": false,
|
||||
"public_dns": "wordpress-stackable.admin.svc.dockerapp.io",
|
||||
"read_only": true,
|
||||
"resource_uri": "/api/app/v1/user_namespace/service/09cbcf8d-a727-40d9-b420-c8e18b7fa55b/",
|
||||
"roles": ["global"],
|
||||
"run_command": "/run-wordpress.sh",
|
||||
"running_num_containers": 1,
|
||||
"security_opt": [
|
||||
],
|
||||
"sequential_deployment": false,
|
||||
"started_datetime": "Mon, 13 Oct 2014 11:01:43 +0000",
|
||||
"state": "Partly running",
|
||||
"stack": "/api/app/v1/user_namespace/stack/46aca402-2109-4a70-a378-760cfed43816/",
|
||||
"stdin_open": false,
|
||||
"stopped_datetime": null,
|
||||
"stopped_num_containers": 0,
|
||||
"synchronized": true,
|
||||
"tags": [
|
||||
{"name": "tag_one"},
|
||||
{"name": "tag-two"},
|
||||
{"name": "tagthree3"}
|
||||
],
|
||||
"target_num_containers": 2,
|
||||
"tty": false,
|
||||
"user": "root",
|
||||
"uuid": "09cbcf8d-a727-40d9-b420-c8e18b7fa55b",
|
||||
"working_dir": "/app"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
A service is a template used to deploy one or more containers.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
uuid | A unique identifier for the service generated automatically on creation
|
||||
resource_uri | A unique API endpoint that represents the service
|
||||
image_name | The Docker image name and tag used for the service containers
|
||||
name | A user provided name for the service. This name will be inherited by the service containers and will be used in endpoint URLs, environment variable names, etc.
|
||||
public_dns | An external FQDN that resolves to all IPs of the nodes where the service containers are running on (as an `A` record with multiple IP entries which will be used by clients in a [round-robin fashion](http://en.wikipedia.org/wiki/Round-robin_DNS)). If the service is not publishing any ports, this FQDN will fail to resolve.
|
||||
state | The state of the service (see table `Service states` below)
|
||||
net | Network mode to set on the containers (see table `Network Modes` below, more information /docker-cloud/apps/service-links/)
|
||||
pid | Set the PID (Process) Namespace mode for the containers ([more information](/engine/reference/run/#pid-settings-pid))
|
||||
synchronized | Flag indicating if the current service definition is synchronized with the current containers.
|
||||
deployed_datetime | The date and time of the last deployment of the service (if applicable, `null` otherwise)
|
||||
started_datetime | The date and time of the last `start` operation on the service (if applicable, `null` otherwise)
|
||||
stopped_datetime | The date and time of the last `stop` operation on the service (if applicable, `null` otherwise)
|
||||
destroyed_datetime | The date and time of the `terminate` operation on the service (if applicable, `null` otherwise)
|
||||
target_num_containers | The requested number of containers to deploy for the service
|
||||
current_num_containers | The actual number of containers deployed for the service
|
||||
running_num_containers | The actual number of containers deployed for the service in `Running` state
|
||||
stopped_num_containers | The actual number of containers deployed for the service in `Stopped` state
|
||||
stack | Resource URIs of the stack that the service belongs to
|
||||
containers | List of resource URIs of the containers launched as part of the service
|
||||
container_ports | List of ports to be published on the containers of this service (see table `Service Port attributes` below)
|
||||
container_envvars | List of user-defined environment variables to set on the containers of the service, which will override the image environment variables (see table `Service Environment Variable attributes` below)
|
||||
labels | Metadata in form of dictionary used for every container of this service
|
||||
working_dir | Working directory for running binaries within a container of this service
|
||||
user | Set the user used on containers of this service (`root` by default)
|
||||
hostname | Set the hostname used on containers of this service
|
||||
domainname | Set the domainname used on containers of this service
|
||||
mac_address | Ethernet device's MAC address used on containers of this service
|
||||
cgroup_name | Optional parent cgroup used on containers of this service.
|
||||
tty | If the containers of this service have the tty enable (`false` by default)
|
||||
stdin_open | If the containers of this service have stdin opened (`false` by default)
|
||||
dns | Custom DNS servers for containers of this service
|
||||
dns_search | Custom DNS search domain for containers of this service
|
||||
cap_add | Added capabilities for containers of this service
|
||||
cap_drop | Dropped capabilities for containers of this service
|
||||
devices | List of device mappings for containers of this service
|
||||
extra_hosts | List of hostname mappings for containers of this service
|
||||
secuirty_opt | Labeling scheme for containers of this service
|
||||
entrypoint | Entrypoint to be set on the containers launched as part of the service, which will override the image entrypoint
|
||||
run_command | Run command to be set on the containers launched as part of the service, which will override the image run command
|
||||
sequential_deployment | Whether the containers for this service should be deployed in sequence, linking each of them to the previous containers (see [Service scaling](/docker-cloud/apps/service-scaling/) for more information)
|
||||
cpu_shares | The relative CPU priority of the containers of the service (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
cpuset | CPUs in which to allow execution
|
||||
memory | The memory limit of the containers of the service in MB (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
memory_swap | Total memory limit (memory + swap) of the containers of the service in MB
|
||||
linked_from_service | A list of services that are linked to this one (see table `Related services attributes` below)
|
||||
linked_to_service | A list of services that the service is linked to (see table `Related services attributes` below)
|
||||
bindings | A list of volume bindings that the service has mounted (see table `Service binding attributes` below)
|
||||
autorestart | Whether to restart the containers of the service automatically if they stop (see [Crash recovery](/docker-cloud/apps/autorestart/) for more information)
|
||||
autodestroy | Whether to terminate the containers of the service automatically if they stop (see [Autodestroy](/docker-cloud/apps/auto-destroy/) for more information)
|
||||
roles | List of Docker Cloud roles assigned to this service (see [Service links](/docker-cloud/apps/service-links/) for more information)
|
||||
link_variables | List of environment variables that would be exposed in the containers if they are linked to this service
|
||||
privileged | Whether to start the containers with Docker's `privileged` flag set or not, which allows containers to access all devices on the host among other things (see [Runtime privilege](/engine/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration) for more information)
|
||||
read_only | Whether the filesystem of every service container is read-only or not (`false` by default)
|
||||
deployment_strategy | Container distribution among nodes (see table `Deployment strategies` below and [Deployment strategies](/docker-cloud/infrastructure/deployment-strategies/) for more information)
|
||||
tags | List of tags to be used to deploy the service (see [Tags](/docker-cloud/apps/deploy-tags/) for more information)
|
||||
autoredeploy | Whether to redeploy the containers of the service when its image is updated in Docker Cloud registry (see [Docker Cloud's private registry](/docker-cloud/apps/auto-redeploy/) for more information)
|
||||
nickname | A user-friendly name for the service (`name` by default)
|
||||
|
||||
|
||||
### Service binding attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
host_path | The host path of the volume
|
||||
container_path | The container path where the volume is mounted
|
||||
rewritable | `true` is the volume has writable permissions
|
||||
volumes_from | The resource URI of the service
|
||||
|
||||
|
||||
### Service Port attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
protocol | The protocol of the port, either `tcp` or `udp`
|
||||
inner_port | The published port number inside the container
|
||||
outer_port | The published port number in the node public network interface
|
||||
port_name | Name of the service associated to this port
|
||||
endpoint_uri | The URI of the service endpoint for this port
|
||||
published | Whether the port has been published in the host public network interface or not. Non-published ports can only be accessed via links.
|
||||
|
||||
|
||||
### Service Environment Variable attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
key | The name of the environment variable
|
||||
value | The value of the environment variable
|
||||
|
||||
|
||||
### Related services attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
name | The link name
|
||||
from_service | The resource URI of the origin of the link
|
||||
to_service | The resource URI of the target of the link
|
||||
|
||||
|
||||
### Service states
|
||||
|
||||
State | Description
|
||||
----- | -----------
|
||||
Not running | The service has been created and has no deployed containers yet. Possible actions in this state: `start`, `terminate`.
|
||||
Starting | All containers for the service are either starting or already running. No actions allowed in this state.
|
||||
Running | All containers for the service are deployed and running. Possible actions in this state: `stop`, `redeploy`, `terminate`.
|
||||
Partly running | One or more containers of the service are deployed and running. Possible actions in this state: `stop`, `redeploy`, `terminate`.
|
||||
Scaling | The service is either deploying new containers or destroying existing ones responding to a scaling request. No actions allowed in this state.
|
||||
Redeploying | The service is redeploying all its containers with the updated configuration. No actions allowed in this state.
|
||||
Stopping | All containers for the service are either stopping or already stopped. No actions allowed in this state.
|
||||
Stopped | All containers for the service are stopped. Possible actions in this state: `start`, `redeploy`, `terminate`.
|
||||
Terminating | All containers for the service are either being terminated or already terminated. No actions allowed in this state.
|
||||
Terminated | The service and all its containers have been terminated. No actions allowed in this state.
|
||||
|
||||
|
||||
### Deployment strategies
|
||||
|
||||
Strategy | Description
|
||||
-------- | -----------
|
||||
EMPTIEST_NODE | It will deploy containers to the node with the lower total amount of running containers (default).
|
||||
HIGH_AVAILABILITY | It will deploy containers to the node with the lower amount of running containers of the same service.
|
||||
EVERY_NODE | It will deploy one container on every node. The service won't be able to scale manually. New containers will be deployed to new nodes automatically.
|
||||
|
||||
|
||||
### Network Modes
|
||||
|
||||
Strategy | Description
|
||||
-------- | -----------
|
||||
bridge | Creates a new network stack for the container on the docker bridge.
|
||||
host | Uses the host network stack inside the container.
|
||||
|
||||
## List all services
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
services = dockercloud.Service.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
serviceList, err := dockercloud.ListServices()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(serviceList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service ps
|
||||
```
|
||||
|
||||
Lists all current and recently terminated services. Returns a list of `Service` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]service/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
state | Filter by state. Possible values: `Not running`, `Starting`, `Running`, `Partly running`, `Scaling`, `Redeploying`, `Stopping`, `Stopped`, `Terminating`, `Terminated`
|
||||
name | Filter by service name
|
||||
stack | Filter by resource URI of the target stack.
|
||||
|
||||
## Create a new service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.create(image="tutum/hello-world", name="my-new-app", target_num_containers=2)
|
||||
service.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.CreateService(dockercloud.ServiceCreateRequest{Image: "tutum/hello-world", Name: "my-new-app", Target_num_containers: 2})
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(service)
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"image": "tutum/hello-world", "name": "my-new-app", "target_num_containers": 2}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service create -t 2 --name my-new-app tutum/hello-world
|
||||
```
|
||||
|
||||
Creates a new service without starting it.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/`
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
image | (required) The image used to deploy this service in docker format, i.e. `tutum/hello-world`
|
||||
name | (optional) A human-readable name for the service, i.e. `my-hello-world-app` (default: `image` without namespace)
|
||||
target_num_containers | (optional) The number of containers to run for this service initially (default: 1)
|
||||
run_command | (optional) The command used to start the containers of this service, overriding the value specified in the image, i.e. `/run.sh` (default: `null`)
|
||||
entrypoint | (optional) The command prefix used to start the containers of this service, overriding the value specified in the image, i.e. `/usr/sbin/sshd` (default: `null`)
|
||||
container_ports | (optional) An array of objects with port information to be published in the containers for this service, which will be added to the image port information, i.e. `[{"protocol": "tcp", "inner_port": 80, "outer_port": 80}]` (default: `[]`) (See table `Service Port attributes` below)
|
||||
container_envvars | (optional) An array of objects with environment variables to be added in the service containers on launch (overriding any image-defined environment variables), i.e. `[{"key": "DB_PASSWORD", "value": "mypass"}]` (default: `[]`) (See table `Service Environment Variable attributes` below)
|
||||
linked_to_service | (optional) An array of service resource URIs to link this service to, including the link name, i.e. `[{"to_service": "/api/app/v1/service/80ff1635-2d56-478d-a97f-9b59c720e513/", "name": "db"}]` (default: `[]`) (See table `Related services attributes` below)
|
||||
bindings | (optional) An array of bindings this service has to mount, i.e. `[{"volumes_from": "/api/app/v1/service/80ff1635-2d56-478d-a97f-9b59c720e513/", "rewritable": true}]` (default: `[]`) (See table `Related bindings attributes` below)
|
||||
autorestart | (optional) Whether the containers for this service should be restarted if they stop, i.e. `ALWAYS` (default: `OFF`, possible values: `OFF`, `ON_FAILURE`, `ALWAYS`) (see [Crash recovery](/docker-cloud/apps/autorestart/) for more information)
|
||||
autodestroy | (optional) Whether the containers should be terminated if they stop, i.e. `OFF` (default: `OFF`, possible values: `OFF`, `ON_SUCCESS`, `ALWAYS`) (see [Autodestroy](/docker-cloud/apps/auto-destroy/) for more information)
|
||||
sequential_deployment | (optional) Whether the containers should be launched and scaled in sequence, i.e. `true` (default: `false`) (see [Service scaling](/docker-cloud/apps/service-scaling/) for more information)
|
||||
roles | (optional) A list of Docker Cloud API roles to grant the service, i.e. `["global"]` (default: `[]`, possible values: `global`) (see [Service links](/docker-cloud/apps/service-links/) for more information)
|
||||
privileged | (optional) Whether to start the containers with Docker's `privileged` flag set or not, i.e. `false` (default: `false`) (see [Runtime privilege](/engine/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration) for more information)
|
||||
deployment_strategy | (optional) Container distribution among nodes (default: `EMPTIEST_NODE`, see table `Deployment strategies` above and [Deployment strategies](/docker-cloud/infrastructure/deployment-strategies/) for more information)
|
||||
tags | (optional) A list of tags to be used to deploy the service (see [Tags](/docker-cloud/apps/deploy-tags/) for more information) (default: `[]`)
|
||||
autoredeploy | (optional) Whether to redeploy the containers of the service when its image is updated in Docker Cloud registry (default: `false`) (see [Docker Cloud's private registry](/docker-cloud/apps/auto-redeploy/) for more information)
|
||||
net | (optional) Set the network mode to the containers (default: `bridge`, possible values: `bridge`, `host`)
|
||||
pid | (optional) Set the PID (Process) Namespace mode for the containers (default: `none` value, possible values: `none`, `host`)
|
||||
working_dir | (optional) Working directory for running binaries within a container of this service (default: `/`)
|
||||
nickname | (optional) A user-friendly name for the service (`name` by default)
|
||||
|
||||
|
||||
### Related bindings attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
host_path | (optional) The host path of the volume
|
||||
container_path | (required if `volumes_from` is omitted) The container path where the volume is mounted
|
||||
rewritable | (optional) `true` is the volume has writable permissions (default: `true`)
|
||||
volumes_from | (required if `container_path` is omitted) The resource URI of the service
|
||||
|
||||
|
||||
### Service Port attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
protocol | (required) The protocol of the port, either `tcp` or `udp`
|
||||
inner_port | (required) The port number inside the container to be published
|
||||
outer_port | (optional) The port number in the node public network interface to be published (default: dynamic allocation if `published` is `true`)
|
||||
published | (optional) Whether to publish the port in the host public network interface or not. Non-published ports can only be accessed via links. (default: `false`)
|
||||
|
||||
|
||||
### Service Environment Variable attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
key | (required) The name of the environment variable
|
||||
value | (required) The value of the environment variable
|
||||
|
||||
|
||||
### Related services attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
to_service | (required) The resource URI of the target of the link
|
||||
name | (optional) The link name
|
||||
|
||||
|
||||
## Get an existing service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(service)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service inspect 7eaf7fff
|
||||
```
|
||||
|
||||
Get all the details of an specific service
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]service/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to retrieve
|
||||
|
||||
|
||||
## Get the logs of a service
|
||||
|
||||
> Example log line
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "log",
|
||||
"source": "wordpress-stackable-1",
|
||||
"log": "Log line from the container indicated by 'source'",
|
||||
"streamType": "stdout",
|
||||
"timestamp": 1433779324
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
def log_handler(message):
|
||||
print message
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.logs(tail=300, follow=True, log_handler=log_handler)
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
c := make(chan Logs)
|
||||
|
||||
go service.Logs(c)
|
||||
for {
|
||||
s := <-c
|
||||
log.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/logs/ HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service logs 7eaf7fff
|
||||
```
|
||||
|
||||
Get the aggregated logs of all the containers of the service.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **STREAM API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]service/(uuid)/logs/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to retrieve logs
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
tail | Number of lines to show from the end of the logs (default: `300`)
|
||||
follow | Whether to stream logs or close the connection immediately (default: true)
|
||||
|
||||
|
||||
## Update an existing service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.target_num_containers = 3
|
||||
service.tags.append({"name":"tag-1"})
|
||||
service.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = service.Update(dockercloud.ServiceCreateRequest{Target_num_containers: 3}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
PATCH /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"autorestart": "ON_FAILURE", "autodestroy": "OFF", "container_envvars": [{"key": "DB_PASSWORD", "value": "mypass"}],
|
||||
"container_ports": [{"protocol": "tcp", "inner_port": 80, "outer_port": 80}], "cpu_shares": 512,
|
||||
"entrypoint": "/usr/sbin/sshd", "image": "tutum/hello-world",
|
||||
"linked_to_service": [{"to_service": "/api/app/v1/service/80ff1635-2d56-478d-a97f-9b59c720e513/", "name": "db"}],
|
||||
"memory": 2048, "privileged": True, "roles": ["global"], "run_command": "/run.sh", "sequential_deployment": False,
|
||||
"tags": [{"name": "tag-1"}], "target_num_containers": 3, "autoredeploy": False}
|
||||
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service scale 7eaf7fff 3
|
||||
docker-cloud tag add -t tag-1 7eaf7fff
|
||||
docker-cloud tag set -t tag-2 7eaf7fff
|
||||
```
|
||||
|
||||
Updates the service details.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`PATCH /api/app/v1/[optional_namespace/]service/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to update
|
||||
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
autorestart | (optional) Whether the containers for this service should be restarted if they stop, i.e. `ALWAYS` (possible values: `OFF`, `ON_FAILURE`, `ALWAYS`) (see [Crash recovery](/docker-cloud/apps/autorestart/) for more information)
|
||||
autodestroy | (optional) Whether the containers should be terminated if they stop, i.e. `OFF` (possible values: `OFF`, `ON_SUCCESS`, `ALWAYS`) (see [Autodestroy](/docker-cloud/apps/auto-destroy/) for more information)
|
||||
container_envvars | (optional) An array of objects with environment variables to be added in the service containers on launch (overriding any image-defined environment variables), i.e. `[{"key": "DB_PASSWORD", "value": "mypass"}]` (See table `Service Environment Variable attributes`)
|
||||
container_ports | (optional) An array of objects with port information to be published in the containers for this service, which will be added to the image port information, i.e. `[{"protocol": "tcp", "inner_port": 80, "outer_port": 80}]` (See table `Service Port attributes`)
|
||||
cpu_shares | (optional) The relative CPU priority of the containers the service describes (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
entrypoint | (optional) The command prefix used to start the containers of this service, overriding the value specified in the image, i.e. `/usr/sbin/sshd`
|
||||
image | (optional) The image used to deploy this service in docker format, i.e. `tutum/hello-world`, `tutum/ubuntu:5.6`. If no tag is indicated, it will be set to `latest` by default
|
||||
linked_to_service | (optional) An array of service resource URIs to link this service to, including the link name, i.e. `[{"to_service": "/api/app/v1/service/80ff1635-2d56-478d-a97f-9b59c720e513/", "name": "db"}]` (See table `Related services attributes` below)
|
||||
memory | (optional) The memory limit of the containers of the service in MB (see [Runtime Constraints on CPU and Memory](/engine/reference/run/#runtime-constraints-on-cpu-and-memory) for more information)
|
||||
privileged | (optional) Whether to start the containers with Docker's `privileged` flag set or not, i.e. `false` (see [Runtime privilege](/engine/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration) for more information)
|
||||
roles | (optional) A list of Docker Cloud API roles to grant the service, i.e. `["global"]` (possible values: `global`) (see [Service links](/docker-cloud/apps/service-links/) for more information)
|
||||
run_command | (optional) The command used to start the containers of this service, overriding the value specified in the image, i.e. `/run.sh`
|
||||
sequential_deployment | (optional) Whether the containers should be launched and scaled in sequence, i.e. `true` (see [Service scaling](/docker-cloud/apps/service-scaling/) for more information)
|
||||
tags | (optional) List of new tags the service will have. This operation replaces the tag list
|
||||
target_num_containers | (optional) The number of containers to scale this service to
|
||||
deployment_strategy | (optional) Container distribution among nodes. A service cannot be updated to or from a deployment strategy of `EVERY_NODE`. (See table `Deployment strategies` above and [Deployment strategies](/docker-cloud/infrastructure/deployment-strategies/) for more information)
|
||||
autoredeploy | Whether to redeploy the containers of the service when its image is updated in Docker Cloud registry (see [Docker Cloud's private registry](/docker-cloud/apps/auto-redeploy/) for more information)
|
||||
net | (optional) Set the network mode to the containers (default: `bridge`, possible values: `bridge`, `host`)
|
||||
pid | (optional) Set the PID (Process) Namespace mode for the containers (default: `none` value, possible values: `none`, `host`)
|
||||
working_dir | (optional) Working directory for running binaries within a container of this service (default: `/`)
|
||||
nickname | (optional) A user-friendly name for the service (`name` by default)
|
||||
|
||||
|
||||
## Start a service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.start()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = service.Start(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/start/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service start 7eaf7fff
|
||||
```
|
||||
|
||||
Starts all containers in a stopped or partly running service.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/start/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to start
|
||||
|
||||
|
||||
## Stop a service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.stop()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = service.Stop(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/stop/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service stop 7eaf7fff
|
||||
```
|
||||
|
||||
Stops all containers in a running or partly running service.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/stop/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to stop
|
||||
|
||||
|
||||
## Scale a service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.target_num_containers = 3
|
||||
service.save()
|
||||
service.scale()
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/scale/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service scale 7eaf7fff-882c-4f3d-9a8f-a22317ac00ce 3
|
||||
```
|
||||
|
||||
Scales the service to its current `target_num_containers` field.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/scale/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to scale
|
||||
|
||||
|
||||
## Redeploy a service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.redeploy()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: true}) to reuse the existing volumes
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}) to not reuse the existing volumes
|
||||
if err = service.Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/redeploy/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service redeploy 7eaf7fff
|
||||
```
|
||||
|
||||
Redeploys all containers in the service with the current service configuration.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/redeploy/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to redeploy
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
reuse_volumes | Whether to reuse container volumes for this redeploy operation or not (default: `true`).
|
||||
|
||||
|
||||
## Terminate a service
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
service.delete()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = service.Terminate(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/app/v1/service/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud service terminate 7eaf7fff
|
||||
```
|
||||
|
||||
Terminate all the containers in a service and the service itself. This is not reversible. All the data stored in all containers of the service will be permanently deleted.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/app/v1/[optional_namespace/]service/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service to terminate
|
||||
@@ -1,570 +0,0 @@
|
||||
# Stacks
|
||||
|
||||
## Stack
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"deployed_datetime": "Mon, 13 Oct 2014 11:01:43 +0000",
|
||||
"destroyed_datetime": null,
|
||||
"nickname": "deployment stack",
|
||||
"name": "dockercloud-app",
|
||||
"resource_uri": "/api/app/v1/user_namespace/stack/7fe7ec85-58be-4904-81da-de2219098d7c/",
|
||||
"services": [
|
||||
"/api/app/v1/user_namespace/service/09cbcf8d-a727-40d9-b420-c8e18b7fa55b/"
|
||||
],
|
||||
"state": "Running",
|
||||
"synchronized": true,
|
||||
"uuid": "09cbcf8d-a727-40d9-b420-c8e18b7fa55b"
|
||||
}
|
||||
```
|
||||
|
||||
A stack is a logical grouping of closely related services, that may be linked with one another.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
uuid | A unique identifier for the stack generated automatically on creation
|
||||
resource_uri | A unique API endpoint that represents the stack
|
||||
name | A user provided name for the stack.
|
||||
state | The state of the stack (see table `Stack states` below)
|
||||
synchronized | Flag indicating if the current stack definition is synchronized with their services.
|
||||
services | List of service resource URIs belonging to the stack
|
||||
deployed_datetime | The date and time of the last deployment of the stack (if applicable, `null` otherwise)
|
||||
destroyed_datetime | The date and time of the `terminate` operation on the stack (if applicable, `null` otherwise)
|
||||
nickname | A user-friendly name for the stack (`name` by default)
|
||||
|
||||
|
||||
### Stack states
|
||||
|
||||
State | Description
|
||||
----- | -----------
|
||||
Not Running | The stack has been created and has no deployed services yet. Possible actions in this state: `start`, `terminate`.
|
||||
Starting | All services for the stack are either starting or already running. No actions allowed in this state.
|
||||
Running | All services for the service are deployed and running. Possible actions in this state: `redeploy`, `terminate`.
|
||||
Partly running | One or more services of the stack are deployed and running. Possible actions in this state: `redeploy`, `terminate`.
|
||||
Stopping | All services for the stack are either stopping or already stopped. No actions allowed in this state.
|
||||
Stopped | All services for the service are stopped. Possible actions in this state: `start`, `redeploy`, `terminate`.
|
||||
Redeploying | The stack is redeploying all its services with the updated configuration. No actions allowed in this state.
|
||||
Terminating | All services for the stack are either being terminated or already terminated. No actions allowed in this state.
|
||||
Terminated | The stack and all its services have been terminated. No actions allowed in this state.
|
||||
|
||||
|
||||
## List all stacks
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stacks = dockercloud.Stack.list()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stackList, err := dockercloud.ListStacks()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(stackList)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/stack/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack ls
|
||||
```
|
||||
|
||||
Lists all current and recently terminated stacks. Returns a list of `Stack` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]stack/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | Filter by UUID
|
||||
name | Filter by stack name
|
||||
|
||||
|
||||
## Create a new stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.create(name="my-new-stack", services=[{"name": "hello-word", "image": "tutum/hello-world", "target_num_containers": 2}])
|
||||
stack.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.CreateStack(dockercloud.StackCreateRequest{Name: "my-new-stack", Services: []dockercloud.ServiceCreateRequest{{Image: "tutum/hello-world", Name: "test", Target_num_containers: 2}}})
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(stack)
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/stack/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "my-new-stack",
|
||||
"services": [
|
||||
{
|
||||
"name": "hello-word",
|
||||
"image": "tutum/hello-world",
|
||||
"target_num_containers": 2,
|
||||
"linked_to_service": [
|
||||
{
|
||||
"to_service": "database",
|
||||
"name": "DB"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "database",
|
||||
"image": "tutum/mysql"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack create --name hello-world -f docker-compose.yml
|
||||
```
|
||||
|
||||
Creates a new stack without starting it. Note that the JSON syntax is abstracted by both, the Docker Cloud CLI and our UI, in order to use [Stack YAML files](/docker-cloud/apps/stack-yaml-reference/).
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]stack/`
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | (required) A human-readable name for the stack, i.e. `my-hello-world-stack`
|
||||
nickname | (optional) A user-friendly name for the stack (`name` by default)
|
||||
services | (optional) List of services belonging to the stack. Each service accepts the same parameters as a [Create new service](#create-a-new-service) operation (default: `[]`) plus the ability to refer "links" and "volumes-from" by the name of another service in the stack (see example).
|
||||
|
||||
|
||||
## Export an existing stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
stack.export()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = stack.Export(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/export/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack export 46aca402
|
||||
```
|
||||
|
||||
Get a JSON representation of the stack following the [Stack YAML representation](/docker-cloud/apps/stacks/).
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]stack/(uuid)/export/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to retrieve
|
||||
|
||||
|
||||
|
||||
## Get an existing stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(stack)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack inspect 46aca402-2109-4a70-a378-760cfed43816
|
||||
```
|
||||
|
||||
Get all the details of an specific stack
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]stack/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to retrieve
|
||||
|
||||
|
||||
|
||||
## Update an existing stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
stack.services = {"services": [{"name": "hello-word", "image": "tutum/hello-world", "target_num_containers": 2}]}
|
||||
stack.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = stack.Update(dockercloud.StackCreateRequest{Services: []dockercloud.ServiceCreateRequest{{Name: "hello-world", Image: "tutum/hello-world", Target_num_containers: 2}}}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
PATCH /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"services": [
|
||||
{
|
||||
"name": "hello-word",
|
||||
"image": "tutum/hello-world",
|
||||
"target_num_containers": 3,
|
||||
"linked_to_service": [
|
||||
{
|
||||
"to_service": "database",
|
||||
"name": "DB"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "database",
|
||||
"image": "tutum/mysql"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack update -f docker-compose.yml 46aca402
|
||||
```
|
||||
|
||||
Updates the details of every service in the stack.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`PATCH /api/app/v1/[optional_namespace/]stack/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to update
|
||||
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
services | (optional) List of services belonging to the stack. Each service accepts the same parameters as a [Update an existing service](#update-an-existing-service) operation (default: `[]`) plus the ability to refer "links" and "volumes-from" by the name of another service in the stack (see example).
|
||||
|
||||
|
||||
|
||||
## Stop a stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
stack.stop()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = stack.Stop(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/stop/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack stop 46aca402-2109-4a70-a378-760cfed43816
|
||||
```
|
||||
|
||||
Stops the services in the stack.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]stack/(uuid)/stop/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to stop
|
||||
|
||||
|
||||
## Start a stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch()
|
||||
stack.start()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = stack.Start(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/start/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack start 46aca402
|
||||
```
|
||||
|
||||
Starts the services in the stack.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]stack/(uuid)/start/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to start
|
||||
|
||||
|
||||
## Redeploy a stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
stack.redeploy()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: true}) to reuse the existing volumes
|
||||
//Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}) to not reuse the existing volumes
|
||||
if err = stack.Redeploy(dockercloud.ReuseVolumesOption{Reuse: false}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/redeploy/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack redeploy 46aca402
|
||||
```
|
||||
|
||||
Redeploys all the services in the stack.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]stack/(uuid)/redeploy/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to redeploy
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
reuse_volumes | Whether to reuse container volumes for this redeploy operation or not (default: `true`).
|
||||
|
||||
|
||||
## Terminate a stack
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
stack = dockercloud.Stack.fetch("46aca402-2109-4a70-a378-760cfed43816")
|
||||
stack.delete()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
stack, err := dockercloud.GetStack("46aca402-2109-4a70-a378-760cfed43816")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err = stack.Terminate(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/app/v1/stack/46aca402-2109-4a70-a378-760cfed43816/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud stack terminate 46aca402
|
||||
```
|
||||
|
||||
Terminate all the services in a the stack and the stack itself.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/app/v1/[optional_namespace/]stack/(uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the stack to terminate
|
||||
@@ -1,52 +0,0 @@
|
||||
# Tags
|
||||
|
||||
## Tag
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "byon=false",
|
||||
"origin": "tutum"
|
||||
}
|
||||
```
|
||||
|
||||
Tags are used to target the deployment of services to a specific set of nodes. [Learn more](/docker-cloud/apps/deploy-tags/)
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
name | Name of the tag
|
||||
origin | Possible values: `user`, `tutum`
|
||||
|
||||
|
||||
## List all node tags
|
||||
|
||||
```http
|
||||
GET /api/infra/v1/tag/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```
|
||||
docker-cloud tag ls 7eaf7fff-882c
|
||||
```
|
||||
|
||||
Lists all tags used by all nodes. Returns a list of `Tag` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/infra/v1/tag/`
|
||||
|
||||
### Query Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | Filter by name
|
||||
origin | Filter by origin. Possible values: `user`, `tutum`
|
||||
@@ -1,301 +0,0 @@
|
||||
# Triggers
|
||||
|
||||
## Service triggers
|
||||
|
||||
> Example
|
||||
|
||||
```json
|
||||
{
|
||||
"url": "/api/app/v1/user_namespace/service/82d4a246-52d8-468d-903d-9da9ef05ff28/trigger/0224815a-c156-44e4-92d7-997c69354438/call/",
|
||||
"operation": "REDEPLOY",
|
||||
"name": "docker_trigger",
|
||||
"resource_uri": "/api/app/v1/user_namespace/service/82d4a246-52d8-468d-903d-9da9ef05ff28/trigger/0224815a-c156-44e4-92d7-997c69354438/"
|
||||
}
|
||||
```
|
||||
|
||||
Triggers are URLs that will start a redeploy of the service whenever a `POST` request is sent to them. They require no authorization headers, so they should be treated as access tokens. Triggers can be revoked if they are leaked or no longer used for security purposes. See [Triggers](/docker-cloud/apps/triggers/) for more information.
|
||||
|
||||
This is a [namespaced endpoint](#namespaced-endpoints).
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
Attribute | Description
|
||||
--------- | -----------
|
||||
url | Address to be used to call the trigger with a `POST` request
|
||||
name | A user provided name for the trigger
|
||||
operation | The operation that the trigger call performs (see table `Operations` below)
|
||||
resource_uri | A unique API endpoint that represents the trigger
|
||||
|
||||
|
||||
### Operations
|
||||
|
||||
Operation | Description
|
||||
--------- | -----------
|
||||
REDEPLOY | Performs a `redeploy` service operation.
|
||||
SCALEUP | Performs a `scale up` service operation.
|
||||
|
||||
|
||||
|
||||
## List all triggers
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch('61a29874-9134-48f9-b460-f37d4bec4826')
|
||||
trigger = dockercloud.Trigger.fetch(service)
|
||||
trigger.list()
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("61a29874-9134-48f9-b460-f37d4bec4826")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
trigger, err := service.ListTriggers()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(trigger)
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud trigger list 61a29874-9134-48f9-b460-f37d4bec4826
|
||||
```
|
||||
|
||||
Lists all current triggers the service has associated to. Returns a list of `Service Trigger` objects.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]service/(uuid)/trigger/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service the triggers are associated to
|
||||
|
||||
|
||||
## Create a new trigger
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch('61a29874-9134-48f9-b460-f37d4bec4826')
|
||||
trigger = dockercloud.Trigger.fetch(service)
|
||||
trigger.add(name="mytrigger_name", operation="REDEPLOY")
|
||||
trigger.save()
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("61a29874-9134-48f9-b460-f37d4bec4826")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
trigger, err := service.CreateTrigger(dockercloud.TriggerCreateRequest{Name: "test-trigger", Operation: "REDEPLOY"})
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(trigger)
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{"name": "mytrigger_name", "operation": "REDEPLOY"}
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud trigger create --name mytrigger_name --operation REDEPLOY 61a29874-9134-48f9-b460-f37d4bec4826
|
||||
```
|
||||
|
||||
Creates a new service trigger.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/trigger/`
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
name | (optional) A user provided name for the trigger
|
||||
operation | (optional) The operation to be performed by the trigger (default: "REDEPLOY")
|
||||
|
||||
## Get an existing trigger
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch('61a29874-9134-48f9-b460-f37d4bec4826')
|
||||
trigger = dockercloud.Trigger.fetch(service)
|
||||
```
|
||||
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("61a29874-9134-48f9-b460-f37d4bec4826")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
trigger, err := service.GetTrigger("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println(trigger)
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Get all the details of an specific trigger
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`GET /api/app/v1/[optional_namespace/]service/(uuid)/trigger/(trigger_uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the service the triggers are associated to
|
||||
trigger_uuid | The UUID of the trigger to retrieve
|
||||
|
||||
## Delete a trigger
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch('61a29874-9134-48f9-b460-f37d4bec4826')
|
||||
trigger = dockercloud.Trigger.fetch(service)
|
||||
trigger.delete("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("61a29874-9134-48f9-b460-f37d4bec4826")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
service.DeleteTrigger("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```http
|
||||
DELETE /api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-cloud trigger rm 61a29874-9134-48f9-b460-f37d4bec4826 7eaf7fff-882c-4f3d-9a8f-a22317ac00ce
|
||||
```
|
||||
|
||||
Deletes specific trigger. It will be no longer available to be called.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`DELETE /api/app/v1/[optional_namespace/]service/(uuid)/trigger/(trigger_uuid)/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the associated service
|
||||
trigger_uuid | The UUID of the trigger to delete
|
||||
|
||||
|
||||
## Call a trigger
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
|
||||
service = dockercloud.Service.fetch('61a29874-9134-48f9-b460-f37d4bec4826')
|
||||
trigger = dockercloud.Trigger.fetch(service)
|
||||
trigger.call("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
service, err := dockercloud.GetService("61a29874-9134-48f9-b460-f37d4bec4826")
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
service.CallTrigger("7eaf7fff-882c-4f3d-9a8f-a22317ac00ce")
|
||||
```
|
||||
|
||||
```http
|
||||
POST /api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/call/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
Executes the trigger. For `SCALEUP` triggers, the number of containers to scale up can be passed at the end of the trigger call url, for example `/api/app/v1/service/61a29874-9134-48f9-b460-f37d4bec4826/trigger/7eaf7fff-882c-4f3d-9a8f-a22317ac00ce/call/3/`.
|
||||
|
||||
### Endpoint Type
|
||||
|
||||
Available in Docker Cloud's **REST API**
|
||||
|
||||
### HTTP Request
|
||||
|
||||
`POST /api/app/v1/[optional_namespace/]service/(uuid)/trigger/(trigger_uuid)/call/`
|
||||
|
||||
### Path Parameters
|
||||
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
uuid | The UUID of the associated service
|
||||
trigger_uuid | The UUID of the trigger to call
|
||||
@@ -1,164 +0,0 @@
|
||||
---
|
||||
title: Docker Cloud API reference
|
||||
|
||||
language_tabs:
|
||||
- http
|
||||
- go
|
||||
- python
|
||||
- shell: CLI
|
||||
|
||||
toc_footers:
|
||||
|
||||
includes:
|
||||
- action
|
||||
- provider
|
||||
- region
|
||||
- availabilityzone
|
||||
- nodetype
|
||||
- nodecluster
|
||||
- node
|
||||
- registry
|
||||
- repository
|
||||
- stack
|
||||
- service
|
||||
- container
|
||||
- triggers
|
||||
- dockercloud-events
|
||||
- errors
|
||||
|
||||
search: true
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Docker Cloud currently offers a **HTTP REST API** and a **Websocket Stream API** which are used by both the [Web UI](https://cloud.docker.com/) and the [CLI](https://github.com/moby/mobycloud-cli). This API documentation contains all API operations currently supported in the platform and provides examples of how to execute them using our Command Line Interface (CLI), [Python SDK](https://github.com/docker/python-dockercloud) and [Go SDK](https://github.com/docker/go-dockercloud).
|
||||
|
||||
# Authentication
|
||||
|
||||
In order to be able to make requests to the Docker Cloud API, you should first obtain an ApiKey for your account. For this, log into Docker Cloud, click on the menu on the upper right corner of the screen, select **Account info** and then select **API keys**.
|
||||
|
||||
## REST API
|
||||
|
||||
```python
|
||||
import dockercloud
|
||||
dockercloud.user = "username"
|
||||
dockercloud.apikey = "apikey"
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/docker/go-dockercloud/dockercloud"
|
||||
|
||||
dockercloud.User = "username"
|
||||
dockercloud.ApiKey = "apikey"
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/app/v1/service/ HTTP/1.1
|
||||
Host: cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
```shell
|
||||
export DOCKERCLOUD_USER=username
|
||||
export DOCKERCLOUD_APIKEY=apikey
|
||||
```
|
||||
|
||||
> Make sure to replace `username` with your username and `apikey` with your API key.
|
||||
|
||||
The Docker Cloud REST API is reachable through the following hostname:
|
||||
|
||||
`https://cloud.docker.com/`
|
||||
|
||||
All requests should be sent to this endpoint using `Basic` authentication using your API key as password:
|
||||
|
||||
`Authorization: Basic dXNlcm5hbWU6YXBpa2V5`
|
||||
|
||||
HTTP responses are given in JSON format, so the following `Accept` header is required for every API call:
|
||||
|
||||
`Accept: application/json`
|
||||
|
||||
### Namespaced endpoints
|
||||
|
||||
Endpoints that are labeled as "namespaced" allow the users to operate over
|
||||
different namespaces, for example over an individual user namespace, or the
|
||||
namespace of an organization the user is a member of. A namespace identifies the
|
||||
owner of the resource.
|
||||
|
||||
The namespace is optional. If left blank, it defaults to the authenticated user
|
||||
in the request. The namespace is set before the resource in the URL schema:
|
||||
`https://cloud.docker.com/api/<subsystem>/<version>/(optional_namespace/)<resource>/`
|
||||
|
||||
Examples:
|
||||
|
||||
- The user `exampleuser` wants to operate on the node cluster list endpoint in their own namespace. They can use either of the following urls:
|
||||
- https://cloud.docker.com/api/infra/v1/nodecluster/ (namespace omitted, so will use the user authenticated in the request)
|
||||
- https://cloud.docker.com/api/infra/v1/exampleuser/nodecluster/
|
||||
- The user wants to operate on the node cluster list endpoint in an organization called `exampleorg` (which they have permission to see):
|
||||
- https://cloud.docker.com/api/infra/v1/exampleorg/nodecluster/
|
||||
|
||||
### Namespaced endpoints in the docker-cloud CLI
|
||||
|
||||
If you are using namespaces with the `docker-cloud` CLI, set them by changing
|
||||
the value of the `DOCKERCLOUD_NAMESPACE` environment variable. You can either
|
||||
set this globally, or specify it before each CLI command. To learn more, see the
|
||||
[Docker Cloud CLI README](https://github.com/moby/mobycloud-cli#namespace).
|
||||
|
||||
## Stream API
|
||||
|
||||
```python
|
||||
import websocket
|
||||
import base64
|
||||
|
||||
header = "Authorization: Basic %s" % base64.b64encode("%s:%s" % (username, password))
|
||||
ws = websocket.WebSocketApp('wss://ws.cloud.docker.com/v1/events', header=[header])
|
||||
```
|
||||
|
||||
```go
|
||||
import "github.com/gorilla/websocket"
|
||||
import "encoding/base64"
|
||||
|
||||
var StreamUrl = "wss://ws.cloud.docker.com:443/v1/events"
|
||||
|
||||
sEnc := base64.StdEncoding.EncodeToString([]byte(User + ":" + ApiKey))
|
||||
header := http.Header{}
|
||||
header.Add("Authorization", fmt.Sprintf("Basic %s", sEnc))
|
||||
|
||||
var Dialer websocket.Dialer
|
||||
ws, _, err := Dialer.Dial(url, header)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
```http
|
||||
GET /api/audit/v1/events HTTP/1.1
|
||||
Host: ws.cloud.docker.com
|
||||
Authorization: Basic dXNlcm5hbWU6YXBpa2V5
|
||||
Connection: Upgrade
|
||||
Upgrade: websocket
|
||||
```
|
||||
|
||||
```shell
|
||||
export DOCKERCLOUD_USER=username
|
||||
export DOCKERCLOUD_APIKEY=apikey
|
||||
```
|
||||
|
||||
> Make sure to replace `username` with your username and `apikey` with your API key.
|
||||
|
||||
The Docker Cloud Stream API is reachable through the following hostname:
|
||||
|
||||
`wss://ws.cloud.docker.com/`
|
||||
|
||||
The Stream API requires the same authentication mechanism as the REST API:
|
||||
|
||||
`Authorization: Basic dXNlcm5hbWU6YXBpa2V5`
|
||||
|
||||
|
||||
## API roles
|
||||
|
||||
> The CLI and the SDKs will detect this environment variable and automatically use it
|
||||
|
||||
If you give an [API role](/docker-cloud/apps/api-roles/) to a container, the environment variable `DOCKERCLOUD_AUTH` inside the container will have the contents of the `Authorization` header that you can use to authenticate against the REST or Stream APIs:
|
||||
|
||||
`curl -H "Authorization: $DOCKERCLOUD_AUTH" https://cloud.docker.com/api/app/v1/service/`
|
||||
@@ -1,4 +0,0 @@
|
||||
//= require ./lib/_energize
|
||||
//= require ./app/_lang
|
||||
//= require ./app/_search
|
||||
//= require ./app/_toc
|
||||
@@ -1,3 +0,0 @@
|
||||
//= require ./lib/_energize
|
||||
//= require ./app/_lang
|
||||
//= require ./app/_toc
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
var languages = [];
|
||||
|
||||
global.setupLanguages = setupLanguages;
|
||||
global.activateLanguage = activateLanguage;
|
||||
|
||||
function activateLanguage(language) {
|
||||
if (!language) return;
|
||||
if (language === "") return;
|
||||
|
||||
$(".lang-selector a").removeClass('active');
|
||||
$(".lang-selector a[data-language-name='" + language + "']").addClass('active');
|
||||
for (var i=0; i < languages.length; i++) {
|
||||
$(".highlight." + languages[i]).hide();
|
||||
}
|
||||
$(".highlight." + language).show();
|
||||
|
||||
global.toc.calculateHeights();
|
||||
|
||||
// scroll to the new location of the position
|
||||
if ($(window.location.hash).get(0)) {
|
||||
$(window.location.hash).get(0).scrollIntoView(true);
|
||||
}
|
||||
}
|
||||
|
||||
// parseURL and stringifyURL are from https://github.com/sindresorhus/query-string
|
||||
// MIT licensed
|
||||
// https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license
|
||||
function parseURL(str) {
|
||||
if (typeof str !== 'string') {
|
||||
return {};
|
||||
}
|
||||
|
||||
str = str.trim().replace(/^(\?|#|&)/, '');
|
||||
|
||||
if (!str) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return str.split('&').reduce(function (ret, param) {
|
||||
var parts = param.replace(/\+/g, ' ').split('=');
|
||||
var key = parts[0];
|
||||
var val = parts[1];
|
||||
|
||||
key = decodeURIComponent(key);
|
||||
// missing `=` should be `null`:
|
||||
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
|
||||
val = val === undefined ? null : decodeURIComponent(val);
|
||||
|
||||
if (!ret.hasOwnProperty(key)) {
|
||||
ret[key] = val;
|
||||
} else if (Array.isArray(ret[key])) {
|
||||
ret[key].push(val);
|
||||
} else {
|
||||
ret[key] = [ret[key], val];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}, {});
|
||||
};
|
||||
|
||||
function stringifyURL(obj) {
|
||||
return obj ? Object.keys(obj).sort().map(function (key) {
|
||||
var val = obj[key];
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
return val.sort().map(function (val2) {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
|
||||
}).join('&');
|
||||
}
|
||||
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
|
||||
}).join('&') : '';
|
||||
};
|
||||
|
||||
// gets the language set in the query string
|
||||
function getLanguageFromQueryString() {
|
||||
if (location.search.length >= 1) {
|
||||
var language = parseURL(location.search).language
|
||||
if (language) {
|
||||
return language;
|
||||
} else if (jQuery.inArray(location.search.substr(1), languages) != -1) {
|
||||
return location.search.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns a new query string with the new language in it
|
||||
function generateNewQueryString(language) {
|
||||
var url = parseURL(location.search);
|
||||
if (url.language) {
|
||||
url.language = language;
|
||||
return stringifyURL(url);
|
||||
}
|
||||
return language;
|
||||
}
|
||||
|
||||
// if a button is clicked, add the state to the history
|
||||
function pushURL(language) {
|
||||
if (!history) { return; }
|
||||
var hash = window.location.hash;
|
||||
if (hash) {
|
||||
hash = hash.replace(/^#+/, '');
|
||||
}
|
||||
history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash);
|
||||
|
||||
// save language as next default
|
||||
localStorage.setItem("language", language);
|
||||
}
|
||||
|
||||
function setupLanguages(l) {
|
||||
var defaultLanguage = localStorage.getItem("language");
|
||||
|
||||
languages = l;
|
||||
|
||||
var presetLanguage = getLanguageFromQueryString();
|
||||
if (presetLanguage) {
|
||||
// the language is in the URL, so use that language!
|
||||
activateLanguage(presetLanguage);
|
||||
|
||||
localStorage.setItem("language", presetLanguage);
|
||||
} else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) {
|
||||
// the language was the last selected one saved in localstorage, so use that language!
|
||||
activateLanguage(defaultLanguage);
|
||||
} else {
|
||||
// no language selected, so use the default
|
||||
activateLanguage(languages[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// if we click on a language tab, activate that language
|
||||
$(function() {
|
||||
$(".lang-selector a").on("click", function() {
|
||||
var language = $(this).data("language-name");
|
||||
pushURL(language);
|
||||
activateLanguage(language);
|
||||
return false;
|
||||
});
|
||||
window.onpopstate = function() {
|
||||
activateLanguage(getLanguageFromQueryString());
|
||||
};
|
||||
});
|
||||
})(window);
|
||||
@@ -1,74 +0,0 @@
|
||||
//= require ../lib/_lunr
|
||||
//= require ../lib/_jquery.highlight
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var content, searchResults;
|
||||
var highlightOpts = { element: 'span', className: 'search-highlight' };
|
||||
|
||||
var index = new lunr.Index();
|
||||
|
||||
index.ref('id');
|
||||
index.field('title', { boost: 10 });
|
||||
index.field('body');
|
||||
index.pipeline.add(lunr.trimmer, lunr.stopWordFilter);
|
||||
|
||||
$(populate);
|
||||
$(bind);
|
||||
|
||||
function populate() {
|
||||
$('h1, h2').each(function() {
|
||||
var title = $(this);
|
||||
var body = title.nextUntil('h1, h2');
|
||||
index.add({
|
||||
id: title.prop('id'),
|
||||
title: title.text(),
|
||||
body: body.text()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bind() {
|
||||
content = $('.content');
|
||||
searchResults = $('.search-results');
|
||||
|
||||
$('#input-search').on('keyup', search);
|
||||
}
|
||||
|
||||
function search(event) {
|
||||
unhighlight();
|
||||
searchResults.addClass('visible');
|
||||
|
||||
// ESC clears the field
|
||||
if (event.keyCode === 27) this.value = '';
|
||||
|
||||
if (this.value) {
|
||||
var results = index.search(this.value).filter(function(r) {
|
||||
return r.score > 0.0001;
|
||||
});
|
||||
|
||||
if (results.length) {
|
||||
searchResults.empty();
|
||||
$.each(results, function (index, result) {
|
||||
var elem = document.getElementById(result.ref);
|
||||
searchResults.append("<li><a href='#" + result.ref + "'>" + $(elem).text() + "</a></li>");
|
||||
});
|
||||
highlight.call(this);
|
||||
} else {
|
||||
searchResults.html('<li></li>');
|
||||
$('.search-results li').text('No Results Found for "' + this.value + '"');
|
||||
}
|
||||
} else {
|
||||
unhighlight();
|
||||
searchResults.removeClass('visible');
|
||||
}
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
if (this.value) content.highlight(this.value, highlightOpts);
|
||||
}
|
||||
|
||||
function unhighlight() {
|
||||
content.unhighlight(highlightOpts);
|
||||
}
|
||||
})();
|
||||
@@ -1,55 +0,0 @@
|
||||
//= require ../lib/_jquery_ui
|
||||
//= require ../lib/_jquery.tocify
|
||||
//= require ../lib/_imagesloaded.min
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
var closeToc = function() {
|
||||
$(".tocify-wrapper").removeClass('open');
|
||||
$("#nav-button").removeClass('open');
|
||||
};
|
||||
|
||||
var makeToc = function() {
|
||||
global.toc = $("#toc").tocify({
|
||||
selectors: 'h1, h2',
|
||||
extendPage: false,
|
||||
theme: 'none',
|
||||
smoothScroll: false,
|
||||
showEffectSpeed: 0,
|
||||
hideEffectSpeed: 180,
|
||||
ignoreSelector: '.toc-ignore',
|
||||
highlightOffset: 60,
|
||||
scrollTo: -1,
|
||||
scrollHistory: true,
|
||||
hashGenerator: function (text, element) {
|
||||
return element.prop('id');
|
||||
}
|
||||
}).data('toc-tocify');
|
||||
|
||||
$("#nav-button").click(function() {
|
||||
$(".tocify-wrapper").toggleClass('open');
|
||||
$("#nav-button").toggleClass('open');
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".page-wrapper").click(closeToc);
|
||||
$(".tocify-item").click(closeToc);
|
||||
};
|
||||
|
||||
// Hack to make already open sections to start opened,
|
||||
// instead of displaying an ugly animation
|
||||
function animate() {
|
||||
setTimeout(function() {
|
||||
toc.setOption('showEffectSpeed', 180);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
makeToc();
|
||||
animate();
|
||||
$('.content').imagesLoaded( function() {
|
||||
global.toc.calculateHeights();
|
||||
});
|
||||
});
|
||||
})(window);
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/**
|
||||
* energize.js v0.1.0
|
||||
*
|
||||
* Speeds up click events on mobile devices.
|
||||
* https://github.com/davidcalhoun/energize.js
|
||||
*/
|
||||
|
||||
(function() { // Sandbox
|
||||
/**
|
||||
* Don't add to non-touch devices, which don't need to be sped up
|
||||
*/
|
||||
if(!('ontouchstart' in window)) return;
|
||||
|
||||
var lastClick = {},
|
||||
isThresholdReached, touchstart, touchmove, touchend,
|
||||
click, closest;
|
||||
|
||||
/**
|
||||
* isThresholdReached
|
||||
*
|
||||
* Compare touchstart with touchend xy coordinates,
|
||||
* and only fire simulated click event if the coordinates
|
||||
* are nearby. (don't want clicking to be confused with a swipe)
|
||||
*/
|
||||
isThresholdReached = function(startXY, xy) {
|
||||
return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5;
|
||||
};
|
||||
|
||||
/**
|
||||
* touchstart
|
||||
*
|
||||
* Save xy coordinates when the user starts touching the screen
|
||||
*/
|
||||
touchstart = function(e) {
|
||||
this.startXY = [e.touches[0].clientX, e.touches[0].clientY];
|
||||
this.threshold = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* touchmove
|
||||
*
|
||||
* Check if the user is scrolling past the threshold.
|
||||
* Have to check here because touchend will not always fire
|
||||
* on some tested devices (Kindle Fire?)
|
||||
*/
|
||||
touchmove = function(e) {
|
||||
// NOOP if the threshold has already been reached
|
||||
if(this.threshold) return false;
|
||||
|
||||
this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]);
|
||||
};
|
||||
|
||||
/**
|
||||
* touchend
|
||||
*
|
||||
* If the user didn't scroll past the threshold between
|
||||
* touchstart and touchend, fire a simulated click.
|
||||
*
|
||||
* (This will fire before a native click)
|
||||
*/
|
||||
touchend = function(e) {
|
||||
// Don't fire a click if the user scrolled past the threshold
|
||||
if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and fire a click event on the target element
|
||||
* https://developer.mozilla.org/en/DOM/event.initMouseEvent
|
||||
*/
|
||||
var touch = e.changedTouches[0],
|
||||
evt = document.createEvent('MouseEvents');
|
||||
evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
|
||||
evt.simulated = true; // distinguish from a normal (nonsimulated) click
|
||||
e.target.dispatchEvent(evt);
|
||||
};
|
||||
|
||||
/**
|
||||
* click
|
||||
*
|
||||
* Because we've already fired a click event in touchend,
|
||||
* we need to listed for all native click events here
|
||||
* and suppress them as necessary.
|
||||
*/
|
||||
click = function(e) {
|
||||
/**
|
||||
* Prevent ghost clicks by only allowing clicks we created
|
||||
* in the click event we fired (look for e.simulated)
|
||||
*/
|
||||
var time = Date.now(),
|
||||
timeDiff = time - lastClick.time,
|
||||
x = e.clientX,
|
||||
y = e.clientY,
|
||||
xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)],
|
||||
target = closest(e.target, 'A') || e.target, // needed for standalone apps
|
||||
nodeName = target.nodeName,
|
||||
isLink = nodeName === 'A',
|
||||
standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href");
|
||||
|
||||
lastClick.time = time;
|
||||
lastClick.x = x;
|
||||
lastClick.y = y;
|
||||
|
||||
/**
|
||||
* Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire),
|
||||
* so we have to add more logic to determine the time of the last click. Not perfect...
|
||||
*
|
||||
* Older, simpler check: if((!e.simulated) || standAlone)
|
||||
*/
|
||||
if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if(!standAlone) return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special logic for standalone web apps
|
||||
* See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window
|
||||
*/
|
||||
if(standAlone) {
|
||||
window.location = target.getAttribute("href");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an energize-focus class to the targeted link (mimics :focus behavior)
|
||||
* TODO: test and/or remove? Does this work?
|
||||
*/
|
||||
if(!target || !target.classList) return;
|
||||
target.classList.add("energize-focus");
|
||||
window.setTimeout(function(){
|
||||
target.classList.remove("energize-focus");
|
||||
}, 150);
|
||||
};
|
||||
|
||||
/**
|
||||
* closest
|
||||
* @param {HTMLElement} node current node to start searching from.
|
||||
* @param {string} tagName the (uppercase) name of the tag you're looking for.
|
||||
*
|
||||
* Find the closest ancestor tag of a given node.
|
||||
*
|
||||
* Starts at node and goes up the DOM tree looking for a
|
||||
* matching nodeName, continuing until hitting document.body
|
||||
*/
|
||||
closest = function(node, tagName){
|
||||
var curNode = node;
|
||||
|
||||
while(curNode !== document.body) { // go up the dom until we find the tag we're after
|
||||
if(!curNode || curNode.nodeName === tagName) { return curNode; } // found
|
||||
curNode = curNode.parentNode; // not found, so keep going up
|
||||
}
|
||||
|
||||
return null; // not found
|
||||
};
|
||||
|
||||
/**
|
||||
* Add all delegated event listeners
|
||||
*
|
||||
* All the events we care about bubble up to document,
|
||||
* so we can take advantage of event delegation.
|
||||
*
|
||||
* Note: no need to wait for DOMContentLoaded here
|
||||
*/
|
||||
document.addEventListener('touchstart', touchstart, false);
|
||||
document.addEventListener('touchmove', touchmove, false);
|
||||
document.addEventListener('touchend', touchend, false);
|
||||
document.addEventListener('click', click, true); // TODO: why does this use capture?
|
||||
|
||||
})();
|
||||
@@ -1,7 +0,0 @@
|
||||
/*!
|
||||
* imagesLoaded PACKAGED v3.1.8
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
(function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("wolfy87-eventemitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(window,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function f(e){this.img=e}function c(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);var i=n.nodeType;if(i&&(1===i||9===i||11===i))for(var r=n.querySelectorAll("img"),o=0,s=r.length;s>o;o++){var f=r[o];this.addImage(f)}}},s.prototype.addImage=function(e){var t=new f(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm"Line truncated
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* jQuery Highlight plugin
|
||||
*
|
||||
* Based on highlight v3 by Johann Burkard
|
||||
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
|
||||
*
|
||||
* Code a little bit refactored and cleaned (in my humble opinion).
|
||||
* Most important changes:
|
||||
* - has an option to highlight only entire words (wordsOnly - false by default),
|
||||
* - has an option to be case sensitive (caseSensitive - false by default)
|
||||
* - highlight element tag and class names can be specified in options
|
||||
*
|
||||
* Usage:
|
||||
* // wrap every occurrance of text 'lorem' in content
|
||||
* // with <span class='highlight'> (default options)
|
||||
* $('#content').highlight('lorem');
|
||||
*
|
||||
* // search for and highlight more terms at once
|
||||
* // so you can save some time on traversing DOM
|
||||
* $('#content').highlight(['lorem', 'ipsum']);
|
||||
* $('#content').highlight('lorem ipsum');
|
||||
*
|
||||
* // search only for entire word 'lorem'
|
||||
* $('#content').highlight('lorem', { wordsOnly: true });
|
||||
*
|
||||
* // don't ignore case during search of term 'lorem'
|
||||
* $('#content').highlight('lorem', { caseSensitive: true });
|
||||
*
|
||||
* // wrap every occurrance of term 'ipsum' in content
|
||||
* // with <em class='important'>
|
||||
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
|
||||
*
|
||||
* // remove default highlight
|
||||
* $('#content').unhighlight();
|
||||
*
|
||||
* // remove custom highlight
|
||||
* $('#content').unhighlight({ element: 'em', className: 'important' });
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2009 Bartek Szopka
|
||||
*
|
||||
* Licensed under MIT license.
|
||||
*
|
||||
*/
|
||||
|
||||
jQuery.extend({
|
||||
highlight: function (node, re, nodeName, className) {
|
||||
if (node.nodeType === 3) {
|
||||
var match = node.data.match(re);
|
||||
if (match) {
|
||||
var highlight = document.createElement(nodeName || 'span');
|
||||
highlight.className = className || 'highlight';
|
||||
var wordNode = node.splitText(match.index);
|
||||
wordNode.splitText(match[0].length);
|
||||
var wordClone = wordNode.cloneNode(true);
|
||||
highlight.appendChild(wordClone);
|
||||
wordNode.parentNode.replaceChild(highlight, wordNode);
|
||||
return 1; //skip added node in parent
|
||||
}
|
||||
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
|
||||
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
|
||||
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.fn.unhighlight = function (options) {
|
||||
var settings = { className: 'highlight', element: 'span' };
|
||||
jQuery.extend(settings, options);
|
||||
|
||||
return this.find(settings.element + "." + settings.className).each(function () {
|
||||
var parent = this.parentNode;
|
||||
parent.replaceChild(this.firstChild, this);
|
||||
parent.normalize();
|
||||
}).end();
|
||||
};
|
||||
|
||||
jQuery.fn.highlight = function (words, options) {
|
||||
var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
|
||||
jQuery.extend(settings, options);
|
||||
|
||||
if (words.constructor === String) {
|
||||
words = [words];
|
||||
}
|
||||
words = jQuery.grep(words, function(word, i){
|
||||
return word != '';
|
||||
});
|
||||
words = jQuery.map(words, function(word, i) {
|
||||
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
});
|
||||
if (words.length == 0) { return this; };
|
||||
|
||||
var flag = settings.caseSensitive ? "" : "i";
|
||||
var pattern = "(" + words.join("|") + ")";
|
||||
if (settings.wordsOnly) {
|
||||
pattern = "\\b" + pattern + "\\b";
|
||||
}
|
||||
var re = new RegExp(pattern, flag);
|
||||
|
||||
return this.each(function () {
|
||||
jQuery.highlight(this, re, settings.element, settings.className);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,566 +0,0 @@
|
||||
/*! jQuery UI - v1.11.3 - 2015-02-12
|
||||
* http://jqueryui.com
|
||||
* Includes: widget.js
|
||||
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
|
||||
|
||||
(function( factory ) {
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define([ "jquery" ], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( $ ) {
|
||||
/*!
|
||||
* jQuery UI Widget 1.11.3
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://api.jqueryui.com/jQuery.widget/
|
||||
*/
|
||||
|
||||
|
||||
var widget_uuid = 0,
|
||||
widget_slice = Array.prototype.slice;
|
||||
|
||||
$.cleanData = (function( orig ) {
|
||||
return function( elems ) {
|
||||
var events, elem, i;
|
||||
for ( i = 0; (elem = elems[i]) != null; i++ ) {
|
||||
try {
|
||||
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
|
||||
// http://bugs.jquery.com/ticket/8235
|
||||
} catch ( e ) {}
|
||||
}
|
||||
orig( elems );
|
||||
};
|
||||
})( $.cleanData );
|
||||
|
||||
$.widget = function( name, base, prototype ) {
|
||||
var fullName, existingConstructor, constructor, basePrototype,
|
||||
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||
proxiedPrototype = {},
|
||||
namespace = name.split( "." )[ 0 ];
|
||||
|
||||
name = name.split( "." )[ 1 ];
|
||||
fullName = namespace + "-" + name;
|
||||
|
||||
if ( !prototype ) {
|
||||
prototype = base;
|
||||
base = $.Widget;
|
||||
}
|
||||
|
||||
// create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
$[ namespace ] = $[ namespace ] || {};
|
||||
existingConstructor = $[ namespace ][ name ];
|
||||
constructor = $[ namespace ][ name ] = function( options, element ) {
|
||||
// allow instantiation without "new" keyword
|
||||
if ( !this._createWidget ) {
|
||||
return new constructor( options, element );
|
||||
}
|
||||
|
||||
// allow instantiation without initializing for simple inheritance
|
||||
// must use "new" keyword (the code above always passes args)
|
||||
if ( arguments.length ) {
|
||||
this._createWidget( options, element );
|
||||
}
|
||||
};
|
||||
// extend with the existing constructor to carry over any static properties
|
||||
$.extend( constructor, existingConstructor, {
|
||||
version: prototype.version,
|
||||
// copy the object used to create the prototype in case we need to
|
||||
// redefine the widget later
|
||||
_proto: $.extend( {}, prototype ),
|
||||
// track widgets that inherit from this widget in case this widget is
|
||||
// redefined after a widget inherits from it
|
||||
_childConstructors: []
|
||||
});
|
||||
|
||||
basePrototype = new base();
|
||||
// we need to make the options hash a property directly on the new instance
|
||||
// otherwise we'll modify the options hash on the prototype that we're
|
||||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
proxiedPrototype[ prop ] = (function() {
|
||||
var _super = function() {
|
||||
return base.prototype[ prop ].apply( this, arguments );
|
||||
},
|
||||
_superApply = function( args ) {
|
||||
return base.prototype[ prop ].apply( this, args );
|
||||
};
|
||||
return function() {
|
||||
var __super = this._super,
|
||||
__superApply = this._superApply,
|
||||
returnValue;
|
||||
|
||||
this._super = _super;
|
||||
this._superApply = _superApply;
|
||||
|
||||
returnValue = value.apply( this, arguments );
|
||||
|
||||
this._super = __super;
|
||||
this._superApply = __superApply;
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
})();
|
||||
});
|
||||
constructor.prototype = $.widget.extend( basePrototype, {
|
||||
// TODO: remove support for widgetEventPrefix
|
||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||
// don't prefix for widgets that aren't DOM-based
|
||||
widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
|
||||
}, proxiedPrototype, {
|
||||
constructor: constructor,
|
||||
namespace: namespace,
|
||||
widgetName: name,
|
||||
widgetFullName: fullName
|
||||
});
|
||||
|
||||
// If this widget is being redefined then we need to find all widgets that
|
||||
// are inheriting from it and redefine all of them so that they inherit from
|
||||
// the new version of this widget. We're essentially trying to replace one
|
||||
// level in the prototype chain.
|
||||
if ( existingConstructor ) {
|
||||
$.each( existingConstructor._childConstructors, function( i, child ) {
|
||||
var childPrototype = child.prototype;
|
||||
|
||||
// redefine the child widget using the same prototype that was
|
||||
// originally used, but inherit from the new version of the base
|
||||
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
|
||||
});
|
||||
// remove the list of existing child constructors from the old constructor
|
||||
// so the old child constructors can be garbage collected
|
||||
delete existingConstructor._childConstructors;
|
||||
} else {
|
||||
base._childConstructors.push( constructor );
|
||||
}
|
||||
|
||||
$.widget.bridge( name, constructor );
|
||||
|
||||
return constructor;
|
||||
};
|
||||
|
||||
$.widget.extend = function( target ) {
|
||||
var input = widget_slice.call( arguments, 1 ),
|
||||
inputIndex = 0,
|
||||
inputLength = input.length,
|
||||
key,
|
||||
value;
|
||||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
||||
$.widget.extend( {}, target[ key ], value ) :
|
||||
// Don't extend strings, arrays, etc. with objects
|
||||
$.widget.extend( {}, value );
|
||||
// Copy everything else by reference
|
||||
} else {
|
||||
target[ key ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
$.widget.bridge = function( name, object ) {
|
||||
var fullName = object.prototype.widgetFullName || name;
|
||||
$.fn[ name ] = function( options ) {
|
||||
var isMethodCall = typeof options === "string",
|
||||
args = widget_slice.call( arguments, 1 ),
|
||||
returnValue = this;
|
||||
|
||||
if ( isMethodCall ) {
|
||||
this.each(function() {
|
||||
var methodValue,
|
||||
instance = $.data( this, fullName );
|
||||
if ( options === "instance" ) {
|
||||
returnValue = instance;
|
||||
return false;
|
||||
}
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on " + name + " prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
|
||||
}
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
// Allow multiple hashes to be passed on init
|
||||
if ( args.length ) {
|
||||
options = $.widget.extend.apply( null, [ options ].concat(args) );
|
||||
}
|
||||
|
||||
this.each(function() {
|
||||
var instance = $.data( this, fullName );
|
||||
if ( instance ) {
|
||||
instance.option( options || {} );
|
||||
if ( instance._init ) {
|
||||
instance._init();
|
||||
}
|
||||
} else {
|
||||
$.data( this, fullName, new object( options, this ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
};
|
||||
|
||||
$.Widget = function( /* options, element */ ) {};
|
||||
$.Widget._childConstructors = [];
|
||||
|
||||
$.Widget.prototype = {
|
||||
widgetName: "widget",
|
||||
widgetEventPrefix: "",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
disabled: false,
|
||||
|
||||
// callbacks
|
||||
create: null
|
||||
},
|
||||
_createWidget: function( options, element ) {
|
||||
element = $( element || this.defaultElement || this )[ 0 ];
|
||||
this.element = $( element );
|
||||
this.uuid = widget_uuid++;
|
||||
this.eventNamespace = "." + this.widgetName + this.uuid;
|
||||
|
||||
this.bindings = $();
|
||||
this.hoverable = $();
|
||||
this.focusable = $();
|
||||
|
||||
if ( element !== this ) {
|
||||
$.data( element, this.widgetFullName, this );
|
||||
this._on( true, this.element, {
|
||||
remove: function( event ) {
|
||||
if ( event.target === element ) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.document = $( element.style ?
|
||||
// element within the document
|
||||
element.ownerDocument :
|
||||
// element is window or document
|
||||
element.document || element );
|
||||
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
|
||||
}
|
||||
|
||||
this.options = $.widget.extend( {},
|
||||
this.options,
|
||||
this._getCreateOptions(),
|
||||
options );
|
||||
|
||||
this._create();
|
||||
this._trigger( "create", null, this._getCreateEventData() );
|
||||
this._init();
|
||||
},
|
||||
_getCreateOptions: $.noop,
|
||||
_getCreateEventData: $.noop,
|
||||
_create: $.noop,
|
||||
_init: $.noop,
|
||||
|
||||
destroy: function() {
|
||||
this._destroy();
|
||||
// we can probably remove the unbind calls in 2.0
|
||||
// all event bindings should go through this._on()
|
||||
this.element
|
||||
.unbind( this.eventNamespace )
|
||||
.removeData( this.widgetFullName )
|
||||
// support: jquery <1.6.3
|
||||
// http://bugs.jquery.com/ticket/9413
|
||||
.removeData( $.camelCase( this.widgetFullName ) );
|
||||
this.widget()
|
||||
.unbind( this.eventNamespace )
|
||||
.removeAttr( "aria-disabled" )
|
||||
.removeClass(
|
||||
this.widgetFullName + "-disabled " +
|
||||
"ui-state-disabled" );
|
||||
|
||||
// clean up events and states
|
||||
this.bindings.unbind( this.eventNamespace );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
},
|
||||
_destroy: $.noop,
|
||||
|
||||
widget: function() {
|
||||
return this.element;
|
||||
},
|
||||
|
||||
option: function( key, value ) {
|
||||
var options = key,
|
||||
parts,
|
||||
curOption,
|
||||
i;
|
||||
|
||||
if ( arguments.length === 0 ) {
|
||||
// don't return a reference to the internal hash
|
||||
return $.widget.extend( {}, this.options );
|
||||
}
|
||||
|
||||
if ( typeof key === "string" ) {
|
||||
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
||||
options = {};
|
||||
parts = key.split( "." );
|
||||
key = parts.shift();
|
||||
if ( parts.length ) {
|
||||
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
||||
for ( i = 0; i < parts.length - 1; i++ ) {
|
||||
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
||||
curOption = curOption[ parts[ i ] ];
|
||||
}
|
||||
key = parts.pop();
|
||||
if ( arguments.length === 1 ) {
|
||||
return curOption[ key ] === undefined ? null : curOption[ key ];
|
||||
}
|
||||
curOption[ key ] = value;
|
||||
} else {
|
||||
if ( arguments.length === 1 ) {
|
||||
return this.options[ key ] === undefined ? null : this.options[ key ];
|
||||
}
|
||||
options[ key ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._setOptions( options );
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOptions: function( options ) {
|
||||
var key;
|
||||
|
||||
for ( key in options ) {
|
||||
this._setOption( key, options[ key ] );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
this.options[ key ] = value;
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this.widget()
|
||||
.toggleClass( this.widgetFullName + "-disabled", !!value );
|
||||
|
||||
// If the widget is becoming disabled, then nothing is interactive
|
||||
if ( value ) {
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
return this._setOptions({ disabled: false });
|
||||
},
|
||||
disable: function() {
|
||||
return this._setOptions({ disabled: true });
|
||||
},
|
||||
|
||||
_on: function( suppressDisabledCheck, element, handlers ) {
|
||||
var delegateElement,
|
||||
instance = this;
|
||||
|
||||
// no suppressDisabledCheck flag, shuffle arguments
|
||||
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
||||
handlers = element;
|
||||
element = suppressDisabledCheck;
|
||||
suppressDisabledCheck = false;
|
||||
}
|
||||
|
||||
// no element argument, shuffle and use this.element
|
||||
if ( !handlers ) {
|
||||
handlers = element;
|
||||
element = this.element;
|
||||
delegateElement = this.widget();
|
||||
} else {
|
||||
element = delegateElement = $( element );
|
||||
this.bindings = this.bindings.add( element );
|
||||
}
|
||||
|
||||
$.each( handlers, function( event, handler ) {
|
||||
function handlerProxy() {
|
||||
// allow widgets to customize the disabled handling
|
||||
// - disabled as an array instead of boolean
|
||||
// - disabled class as method for disabling individual parts
|
||||
if ( !suppressDisabledCheck &&
|
||||
( instance.options.disabled === true ||
|
||||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
||||
return;
|
||||
}
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
|
||||
// copy the guid so direct unbinding works
|
||||
if ( typeof handler !== "string" ) {
|
||||
handlerProxy.guid = handler.guid =
|
||||
handler.guid || handlerProxy.guid || $.guid++;
|
||||
}
|
||||
|
||||
var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
|
||||
eventName = match[1] + instance.eventNamespace,
|
||||
selector = match[2];
|
||||
if ( selector ) {
|
||||
delegateElement.delegate( selector, eventName, handlerProxy );
|
||||
} else {
|
||||
element.bind( eventName, handlerProxy );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_off: function( element, eventName ) {
|
||||
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
|
||||
this.eventNamespace;
|
||||
element.unbind( eventName ).undelegate( eventName );
|
||||
|
||||
// Clear the stack to avoid memory leaks (#10056)
|
||||
this.bindings = $( this.bindings.not( element ).get() );
|
||||
this.focusable = $( this.focusable.not( element ).get() );
|
||||
this.hoverable = $( this.hoverable.not( element ).get() );
|
||||
},
|
||||
|
||||
_delay: function( handler, delay ) {
|
||||
function handlerProxy() {
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
var instance = this;
|
||||
return setTimeout( handlerProxy, delay || 0 );
|
||||
},
|
||||
|
||||
_hoverable: function( element ) {
|
||||
this.hoverable = this.hoverable.add( element );
|
||||
this._on( element, {
|
||||
mouseenter: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-hover" );
|
||||
},
|
||||
mouseleave: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_focusable: function( element ) {
|
||||
this.focusable = this.focusable.add( element );
|
||||
this._on( element, {
|
||||
focusin: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-focus" );
|
||||
},
|
||||
focusout: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-focus" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_trigger: function( type, event, data ) {
|
||||
var prop, orig,
|
||||
callback = this.options[ type ];
|
||||
|
||||
data = data || {};
|
||||
event = $.Event( event );
|
||||
event.type = ( type === this.widgetEventPrefix ?
|
||||
type :
|
||||
this.widgetEventPrefix + type ).toLowerCase();
|
||||
// the original event may come from any element
|
||||
// so we need to reset the target on the new event
|
||||
event.target = this.element[ 0 ];
|
||||
|
||||
// copy original event properties over to the new event
|
||||
orig = event.originalEvent;
|
||||
if ( orig ) {
|
||||
for ( prop in orig ) {
|
||||
if ( !( prop in event ) ) {
|
||||
event[ prop ] = orig[ prop ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
};
|
||||
|
||||
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
||||
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
||||
if ( typeof options === "string" ) {
|
||||
options = { effect: options };
|
||||
}
|
||||
var hasOptions,
|
||||
effectName = !options ?
|
||||
method :
|
||||
options === true || typeof options === "number" ?
|
||||
defaultEffect :
|
||||
options.effect || defaultEffect;
|
||||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
}
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
options.complete = callback;
|
||||
if ( options.delay ) {
|
||||
element.delay( options.delay );
|
||||
}
|
||||
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
||||
element[ method ]( options );
|
||||
} else if ( effectName !== method && element[ effectName ] ) {
|
||||
element[ effectName ]( options.duration, options.easing, callback );
|
||||
} else {
|
||||
element.queue(function( next ) {
|
||||
$( this )[ method ]();
|
||||
if ( callback ) {
|
||||
callback.call( element[ 0 ] );
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var widget = $.widget;
|
||||
|
||||
|
||||
|
||||
}));
|
||||
@@ -1,108 +0,0 @@
|
||||
<%#
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
%>
|
||||
<% language_tabs = current_page.data.language_tabs %>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title><%= current_page.data.title || "API Documentation" %></title>
|
||||
|
||||
<%= stylesheet_link_tag :screen, media: :screen %>
|
||||
<%= stylesheet_link_tag :print, media: :print %>
|
||||
<script type="text/javascript">
|
||||
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="4.0.0";
|
||||
analytics.load("IWj9D0UpZHZdZUZX9jl98PcpBFWBnBMy");
|
||||
analytics.page();
|
||||
}}();
|
||||
</script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<% if current_page.data.search %>
|
||||
<%= javascript_include_tag "all" %>
|
||||
<% else %>
|
||||
<%= javascript_include_tag "all_nosearch" %>
|
||||
<% end %>
|
||||
|
||||
<% if language_tabs %>
|
||||
<script>
|
||||
$(function() {
|
||||
setupLanguages(<%= language_tabs.map{ |lang| lang.is_a?(Hash) ? lang.keys.first : lang }.to_json %>);
|
||||
});
|
||||
</script>
|
||||
<% end %>
|
||||
</head>
|
||||
|
||||
<body class="<%= page_classes %>">
|
||||
<a href="#" id="nav-button">
|
||||
<span>
|
||||
NAV
|
||||
<%= image_tag('navbar.png') %>
|
||||
</span>
|
||||
</a>
|
||||
<div class="tocify-wrapper">
|
||||
<%= image_tag "logo.png" %>
|
||||
<% if language_tabs %>
|
||||
<div class="lang-selector">
|
||||
<% language_tabs.each do |lang| %>
|
||||
<% if lang.is_a? Hash %>
|
||||
<a href="#" data-language-name="<%= lang.keys.first %>"><%= lang.values.first %></a>
|
||||
<% else %>
|
||||
<a href="#" data-language-name="<%= lang %>"><%= lang %></a>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if current_page.data.search %>
|
||||
<div class="search">
|
||||
<input type="text" class="search" id="input-search" placeholder="Search">
|
||||
</div>
|
||||
<ul class="search-results"></ul>
|
||||
<% end %>
|
||||
<div id="toc">
|
||||
</div>
|
||||
<% if current_page.data.toc_footers %>
|
||||
<ul class="toc-footer">
|
||||
<% current_page.data.toc_footers.each do |footer| %>
|
||||
<li><%= footer %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="page-wrapper">
|
||||
<div class="dark-box"></div>
|
||||
<div class="content">
|
||||
<%= yield %>
|
||||
<% current_page.data.includes && current_page.data.includes.each do |include| %>
|
||||
<%= partial "includes/#{include}" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="dark-box">
|
||||
<% if language_tabs %>
|
||||
<div class="lang-selector">
|
||||
<% language_tabs.each do |lang| %>
|
||||
<% if lang.is_a? Hash %>
|
||||
<a href="#" data-language-name="<%= lang.keys.first %>"><%= lang.values.first %></a>
|
||||
<% else %>
|
||||
<a href="#" data-language-name="<%= lang %>"><%= lang %></a>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,38 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'slate';
|
||||
src:font-url('slate.eot?-syv14m');
|
||||
src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'),
|
||||
font-url('slate.woff2?-syv14m') format('woff2'),
|
||||
font-url('slate.woff?-syv14m') format('woff'),
|
||||
font-url('slate.ttf?-syv14m') format('truetype'),
|
||||
font-url('slate.svg?-syv14m#slate') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
%icon {
|
||||
font-family: 'slate';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
%icon-exclamation-sign {
|
||||
@extend %icon;
|
||||
content: "\e600";
|
||||
}
|
||||
%icon-info-sign {
|
||||
@extend %icon;
|
||||
content: "\e602";
|
||||
}
|
||||
%icon-ok-sign {
|
||||
@extend %icon;
|
||||
content: "\e606";
|
||||
}
|
||||
%icon-search {
|
||||
@extend %icon;
|
||||
content: "\e607";
|
||||
}
|
||||
@@ -1,427 +0,0 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
@import 'variables';
|
||||
|
||||
<%= Rouge::Themes::Base16::Monokai.render(:scope => '.highlight') %>
|
||||
|
||||
.highlight .c, .highlight .cm, .highlight .c1, .highlight .cs {
|
||||
color: #909090;
|
||||
}
|
||||
|
||||
.highlight, .highlight .w {
|
||||
background-color: $code-bg;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CUSTOMIZE SLATE
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Use these settings to help adjust the appearance of Slate
|
||||
|
||||
|
||||
// BACKGROUND COLORS
|
||||
////////////////////
|
||||
$nav-bg: #393939;
|
||||
$examples-bg: #393939;
|
||||
$code-bg: #292929;
|
||||
$code-annotation-bg: #1c1c1c;
|
||||
$nav-subitem-bg: #262626;
|
||||
$nav-active-bg: #2467af;
|
||||
$lang-select-border: #000;
|
||||
$lang-select-bg: #222;
|
||||
$lang-select-active-bg: $examples-bg; // feel free to change this to blue or something
|
||||
$lang-select-pressed-bg: #111; // color of language tab bg when mouse is pressed
|
||||
$main-bg: #eaf2f6;
|
||||
$aside-notice-bg: #8fbcd4;
|
||||
$aside-warning-bg: #c97a7e;
|
||||
$aside-success-bg: #6ac174;
|
||||
$search-notice-bg: #c97a7e;
|
||||
|
||||
|
||||
// TEXT COLORS
|
||||
////////////////////
|
||||
$main-text: #333; // main content text color
|
||||
$nav-text: #fff;
|
||||
$nav-active-text: #fff;
|
||||
$lang-select-text: #fff; // color of unselected language tab text
|
||||
$lang-select-active-text: #fff; // color of selected language tab text
|
||||
$lang-select-pressed-text: #fff; // color of language tab text when mouse is pressed
|
||||
|
||||
|
||||
// SIZES
|
||||
////////////////////
|
||||
$nav-width: 230px; // width of the navbar
|
||||
$examples-width: 50%; // portion of the screen taken up by code examples
|
||||
$logo-margin: 20px; // margin between nav items and logo, ignored if search is active
|
||||
$main-padding: 28px; // padding to left and right of content & examples
|
||||
$nav-padding: 15px; // padding to left and right of navbar
|
||||
$nav-v-padding: 10px; // padding used vertically around search boxes and results
|
||||
$nav-indent: 10px; // extra padding for ToC subitems
|
||||
$code-annotation-padding: 13px; // padding inside code annotations
|
||||
$h1-margin-bottom: 21px; // padding under the largest header tags
|
||||
$tablet-width: 930px; // min width before reverting to tablet size
|
||||
$phone-width: $tablet-width - $nav-width; // min width before reverting to mobile size
|
||||
|
||||
|
||||
// FONTS
|
||||
////////////////////
|
||||
%default-font {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei","微软雅黑", STXihei, "华文细黑", sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
%header-font {
|
||||
@extend %default-font;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
%code-font {
|
||||
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
// OTHER
|
||||
////////////////////
|
||||
$nav-active-shadow: #000;
|
||||
$nav-footer-border-color: #666;
|
||||
$nav-embossed-border-top: #000;
|
||||
$nav-embossed-border-bottom: #939393;
|
||||
$main-embossed-text-shadow: 0px 1px 0px #fff;
|
||||
$search-box-border-color: #666;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// INTERNAL
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These settings are probably best left alone.
|
||||
|
||||
%break-words {
|
||||
word-break: break-all;
|
||||
|
||||
/* Non standard for webkit */
|
||||
word-break: break-word;
|
||||
|
||||
hyphens: auto;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
@charset "utf-8";
|
||||
@import 'normalize';
|
||||
@import 'compass';
|
||||
@import 'variables';
|
||||
@import 'icon-font';
|
||||
|
||||
/*
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
$print-color: #999;
|
||||
$print-color-light: #ccc;
|
||||
$print-font-size: 12px;
|
||||
|
||||
body {
|
||||
@extend %default-font;
|
||||
}
|
||||
|
||||
.tocify, .toc-footer, .lang-selector, .search, #nav-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tocify-wrapper>img {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 12px;
|
||||
|
||||
pre, code {
|
||||
@extend %code-font;
|
||||
@extend %break-words;
|
||||
border: 1px solid $print-color;
|
||||
border-radius: 5px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1.3em;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid $print-color;
|
||||
tr {
|
||||
border-bottom: 1px solid $print-color;
|
||||
}
|
||||
td,th {
|
||||
padding: 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend %header-font;
|
||||
font-size: 2.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: $h1-margin-bottom;
|
||||
border: 2px solid $print-color-light;
|
||||
border-width: 2px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@extend %header-font;
|
||||
font-size: 1.8em;
|
||||
margin-top: 2em;
|
||||
border-top: 2px solid $print-color-light;
|
||||
padding-top: 0.8em;
|
||||
}
|
||||
|
||||
h1+h2, h1+div+h2 {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h3, h4 {
|
||||
@extend %header-font;
|
||||
font-size: 0.8em;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.8em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h5, h6 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
aside {
|
||||
padding: 1em;
|
||||
border: 1px solid $print-color-light;
|
||||
border-radius: 5px;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
aside:before {
|
||||
vertical-align: middle;
|
||||
padding-right: 0.5em;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
aside.notice:before {
|
||||
@extend %icon-info-sign;
|
||||
}
|
||||
|
||||
aside.warning:before {
|
||||
@extend %icon-exclamation-sign;
|
||||
}
|
||||
|
||||
aside.success:before {
|
||||
@extend %icon-ok-sign;
|
||||
}
|
||||
}
|
||||
@@ -1,620 +0,0 @@
|
||||
@charset "utf-8";
|
||||
@import 'normalize';
|
||||
@import 'compass';
|
||||
@import 'variables';
|
||||
@import 'syntax';
|
||||
@import 'icon-font';
|
||||
|
||||
/*
|
||||
Copyright 2008-2013 Concur Technologies, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GENERAL STUFF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
html, body {
|
||||
color: $main-text;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
@extend %default-font;
|
||||
background-color: $main-bg;
|
||||
height: 100%;
|
||||
-webkit-text-size-adjust: none; /* Never autoresize text */
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TABLE OF CONTENTS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#toc > ul > li > a > span {
|
||||
float: right;
|
||||
background-color: #2484FF;
|
||||
border-radius: 40px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
@mixin embossed-bg {
|
||||
background:
|
||||
linear-gradient(to bottom, rgba(#000, 0.2), rgba(#000, 0) 8px),
|
||||
linear-gradient(to top, rgba(#000, 0.2), rgba(#000, 0) 8px),
|
||||
linear-gradient(to bottom, rgba($nav-embossed-border-top, 1), rgba($nav-embossed-border-top, 0) 1.5px),
|
||||
linear-gradient(to top, rgba($nav-embossed-border-bottom, 1), rgba($nav-embossed-border-bottom, 0) 1.5px),
|
||||
$nav-subitem-bg;
|
||||
}
|
||||
|
||||
.tocify-wrapper {
|
||||
transition: left 0.3s ease-in-out;
|
||||
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: fixed;
|
||||
z-index: 30;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: $nav-width;
|
||||
background-color: $nav-bg;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
|
||||
// language selector for mobile devices
|
||||
.lang-selector {
|
||||
display: none;
|
||||
a {
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
// This is the logo at the top of the ToC
|
||||
&>img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&>.search {
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
background: $nav-bg;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: $search-box-border-color;
|
||||
padding: 6px 0 6px 20px;
|
||||
box-sizing: border-box;
|
||||
margin: $nav-v-padding $nav-padding;
|
||||
width: $nav-width - 30;
|
||||
outline: none;
|
||||
color: $nav-text;
|
||||
border-radius: 0; /* ios has a default border radius */
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: $nav-padding;
|
||||
color: $nav-text;
|
||||
@extend %icon-search;
|
||||
}
|
||||
}
|
||||
|
||||
img+.tocify {
|
||||
margin-top: $logo-margin;
|
||||
}
|
||||
|
||||
.search-results {
|
||||
margin-top: 0;
|
||||
box-sizing: border-box;
|
||||
height: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
transition-property: height, margin;
|
||||
transition-duration: 180ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
&.visible {
|
||||
height: 30%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
@include embossed-bg;
|
||||
|
||||
li {
|
||||
margin: 1em $nav-padding;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $nav-text;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tocify-item>a, .toc-footer li {
|
||||
padding: 0 $nav-padding 0 $nav-padding;
|
||||
display: block;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// The Table of Contents is composed of multiple nested
|
||||
// unordered lists. These styles remove the default
|
||||
// styling of an unordered list because it is ugly.
|
||||
ul, li {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
li {
|
||||
color: $nav-text;
|
||||
transition-property: background;
|
||||
transition-timing-function: linear;
|
||||
transition-duration: 230ms;
|
||||
}
|
||||
|
||||
// This is the currently selected ToC entry
|
||||
.tocify-focus {
|
||||
box-shadow: 0px 1px 0px $nav-active-shadow;
|
||||
background-color: $nav-active-bg;
|
||||
color: $nav-active-text;
|
||||
}
|
||||
|
||||
// Subheaders are the submenus that slide open
|
||||
// in the table of contents.
|
||||
.tocify-subheader {
|
||||
display: none; // tocify will override this when needed
|
||||
background-color: $nav-subitem-bg;
|
||||
font-weight: 500;
|
||||
.tocify-item>a {
|
||||
padding-left: $nav-padding + $nav-indent;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
// for embossed look:
|
||||
@include embossed-bg;
|
||||
&>li:last-child {
|
||||
box-shadow: none; // otherwise it'll overflow out of the subheader
|
||||
}
|
||||
}
|
||||
|
||||
.toc-footer {
|
||||
padding: 1em 0;
|
||||
margin-top: 1em;
|
||||
border-top: 1px dashed $nav-footer-border-color;
|
||||
|
||||
li,a {
|
||||
color: $nav-text;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
li {
|
||||
font-size: 0.8em;
|
||||
line-height: 1.7;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// button to show navigation on mobile devices
|
||||
#nav-button {
|
||||
span {
|
||||
display: block;
|
||||
$side-pad: $main-padding / 2 - 8px;
|
||||
padding: $side-pad $side-pad $side-pad;
|
||||
background-color: rgba($main-bg, 0.7);
|
||||
transform-origin: 0 0;
|
||||
transform: rotate(-90deg) translate(-100%, 0);
|
||||
border-radius: 0 0 0 5px;
|
||||
}
|
||||
padding: 0 1.5em 5em 0; // increase touch size area
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
opacity: 0.7;
|
||||
line-height: 16px;
|
||||
img {
|
||||
height: 16px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
transition: left 0.3s ease-in-out;
|
||||
|
||||
&:hover { opacity: 1; }
|
||||
&.open {left: $nav-width}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PAGE LAYOUT AND CODE SAMPLE BACKGROUND
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
.page-wrapper {
|
||||
margin-left: $nav-width;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: $main-bg;
|
||||
min-height: 100%;
|
||||
|
||||
padding-bottom: 1px; // prevent margin overflow
|
||||
|
||||
// The dark box is what gives the code samples their dark background.
|
||||
// It sits essentially under the actual content block, which has a
|
||||
// transparent background.
|
||||
// I know, it's hackish, but it's the simplist way to make the left
|
||||
// half of the content always this background color.
|
||||
.dark-box {
|
||||
width: $examples-width;
|
||||
background-color: $examples-bg;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.lang-selector {
|
||||
position: fixed;
|
||||
z-index: 50;
|
||||
border-bottom: 5px solid $lang-select-active-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.lang-selector {
|
||||
background-color: $lang-select-bg;
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
a {
|
||||
display: block;
|
||||
float:left;
|
||||
color: $lang-select-text;
|
||||
text-decoration: none;
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
outline: 0;
|
||||
|
||||
&:active, &:focus {
|
||||
background-color: $lang-select-pressed-bg;
|
||||
color: $lang-select-pressed-text;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $lang-select-active-bg;
|
||||
color: $lang-select-active-text;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CONTENT STYLES
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This is all the stuff with the light background in the left half of the page
|
||||
|
||||
.content {
|
||||
// to place content above the dark box
|
||||
position: relative;
|
||||
z-index: 30;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
&>h1, &>h2, &>h3, &>h4, &>h5, &>h6, &>p, &>table, &>ul, &>ol, &>aside, &>dl {
|
||||
margin-right: $examples-width;
|
||||
padding: 0 $main-padding;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
@include text-shadow($main-embossed-text-shadow);
|
||||
|
||||
@extend %left-col;
|
||||
}
|
||||
|
||||
&>ul, &>ol {
|
||||
padding-left: $main-padding + 15px;
|
||||
}
|
||||
|
||||
// the div is the tocify hidden div for placeholding stuff
|
||||
&>h1, &>h2, &>div {
|
||||
clear:both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend %header-font;
|
||||
font-size: 30px;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin-bottom: $h1-margin-bottom;
|
||||
margin-top: 2em;
|
||||
border-top: 1px solid #ddd;
|
||||
background-image: linear-gradient(to bottom, #fff, #f9f9f9);
|
||||
}
|
||||
|
||||
h1:first-child, div:first-child + h1 {
|
||||
border-top-width: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@extend %header-font;
|
||||
font-size: 20px;
|
||||
margin-top: 4em;
|
||||
margin-bottom: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
padding-top: 1.2em;
|
||||
padding-bottom: 1.2em;
|
||||
background-image: linear-gradient(to bottom, rgba(#fff, 0.4), rgba(#fff, 0));
|
||||
}
|
||||
|
||||
// h2s right after h1s should bump right up
|
||||
// against the h1s.
|
||||
h1 + h2, h1 + div + h2 {
|
||||
margin-top: $h1-margin-bottom * -1;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 {
|
||||
@extend %header-font;
|
||||
font-size: 15px;
|
||||
margin-top: 2.5em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
h4, h5, h6 {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 2em 0;
|
||||
border-top: 2px solid $examples-bg;
|
||||
border-bottom: 2px solid $main-bg;
|
||||
}
|
||||
|
||||
table {
|
||||
margin-bottom: 1em;
|
||||
overflow: auto;
|
||||
th,td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
tr:last-child {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
tr:nth-child(odd)>td {
|
||||
background-color: lighten($main-bg,4.2%);
|
||||
}
|
||||
|
||||
tr:nth-child(even)>td {
|
||||
background-color: lighten($main-bg,2.4%);
|
||||
}
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
p, li, dt, dd {
|
||||
line-height: 1.6;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
@extend %break-words;
|
||||
@extend %code-font;
|
||||
}
|
||||
|
||||
pre>code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
aside {
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
@include text-shadow(0 1px 0 lighten($aside-notice-bg, 15%));
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
background: $aside-notice-bg;
|
||||
line-height: 1.6;
|
||||
|
||||
&.warning {
|
||||
background-color: $aside-warning-bg;
|
||||
@include text-shadow(0 1px 0 lighten($aside-warning-bg, 15%));
|
||||
}
|
||||
|
||||
&.success {
|
||||
background-color: $aside-success-bg;
|
||||
@include text-shadow(0 1px 0 lighten($aside-success-bg, 15%));
|
||||
}
|
||||
}
|
||||
|
||||
aside:before {
|
||||
vertical-align: middle;
|
||||
padding-right: 0.5em;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
aside.notice:before {
|
||||
@extend %icon-info-sign;
|
||||
}
|
||||
|
||||
aside.warning:before {
|
||||
@extend %icon-exclamation-sign;
|
||||
}
|
||||
|
||||
aside.success:before {
|
||||
@extend %icon-ok-sign;
|
||||
}
|
||||
|
||||
.search-highlight {
|
||||
padding: 2px;
|
||||
margin: -2px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #F7E633;
|
||||
@include text-shadow(1px 1px 0 #666);
|
||||
background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CODE SAMPLE STYLES
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This is all the stuff that appears in the right half of the page
|
||||
|
||||
.content {
|
||||
pre, blockquote {
|
||||
background-color: $code-bg;
|
||||
color: #fff;
|
||||
|
||||
padding: 2em $main-padding;
|
||||
margin: 0;
|
||||
width: $examples-width;
|
||||
|
||||
float:right;
|
||||
clear:right;
|
||||
|
||||
box-sizing: border-box;
|
||||
@include text-shadow(0px 1px 2px rgba(0,0,0,0.4));
|
||||
|
||||
@extend %right-col;
|
||||
|
||||
&>p { margin: 0; }
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-bottom: dashed 1px #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
@extend %code-font;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
&>p {
|
||||
background-color: $code-annotation-bg;
|
||||
border-radius: 5px;
|
||||
padding: $code-annotation-padding;
|
||||
color: #ccc;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #404040;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RESPONSIVE DESIGN
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These are the styles for phones and tablets
|
||||
// There are also a couple styles disperesed
|
||||
|
||||
@media (max-width: $tablet-width) {
|
||||
.tocify-wrapper {
|
||||
left: -$nav-width;
|
||||
|
||||
&.open {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.page-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#nav-button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tocify-wrapper .tocify-item > a {
|
||||
padding-top: 0.3em;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $phone-width) {
|
||||
.dark-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
%left-col {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.tocify-wrapper .lang-selector {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.page-wrapper .lang-selector {
|
||||
display: none;
|
||||
}
|
||||
|
||||
%right-col {
|
||||
width: auto;
|
||||
float: none;
|
||||
}
|
||||
|
||||
%right-col + %left-col {
|
||||
margin-top: $main-padding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
---
|
||||
title: "Engine API version history"
|
||||
description: "Documentation of changes that have been made to Engine API."
|
||||
keywords: "API, Docker, rcli, REST, documentation"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
## v1.27 API changes
|
||||
|
||||
[Docker Engine API v1.27](https://docs.docker.com/engine/api/v1.27/) documentation
|
||||
|
||||
* `GET /containers/(id or name)/stats` now includes an `online_cpus` field in both `precpu_stats` and `cpu_stats`. If this field is `nil` then for compatibility with older daemons the length of the corresponding `cpu_usage.percpu_usage` array should be used.
|
||||
|
||||
## v1.26 API changes
|
||||
|
||||
[Docker Engine API v1.26](https://docs.docker.com/engine/api/v1.26/) documentation
|
||||
|
||||
* `POST /plugins/(plugin name)/upgrade` upgrade a plugin.
|
||||
|
||||
## v1.25 API changes
|
||||
|
||||
[Docker Engine API v1.25](https://docs.docker.com/engine/api/v1.25/) documentation
|
||||
|
||||
* The API version is now required in all API calls. Instead of just requesting, for example, the URL `/containers/json`, you must now request `/v1.25/containers/json`.
|
||||
* `GET /version` now returns `MinAPIVersion`.
|
||||
* `POST /build` accepts `networkmode` parameter to specify network used during build.
|
||||
* `GET /images/(name)/json` now returns `OsVersion` if populated
|
||||
* `GET /info` now returns `Isolation`.
|
||||
* `POST /containers/create` now takes `AutoRemove` in HostConfig, to enable auto-removal of the container on daemon side when the container's process exits.
|
||||
* `GET /containers/json` and `GET /containers/(id or name)/json` now return `"removing"` as a value for the `State.Status` field if the container is being removed. Previously, "exited" was returned as status.
|
||||
* `GET /containers/json` now accepts `removing` as a valid value for the `status` filter.
|
||||
* `GET /containers/json` now supports filtering containers by `health` status.
|
||||
* `DELETE /volumes/(name)` now accepts a `force` query parameter to force removal of volumes that were already removed out of band by the volume driver plugin.
|
||||
* `POST /containers/create/` and `POST /containers/(name)/update` now validates restart policies.
|
||||
* `POST /containers/create` now validates IPAMConfig in NetworkingConfig, and returns error for invalid IPv4 and IPv6 addresses (`--ip` and `--ip6` in `docker create/run`).
|
||||
* `POST /containers/create` now takes a `Mounts` field in `HostConfig` which replaces `Binds`, `Volumes`, and `Tmpfs`. *note*: `Binds`, `Volumes`, and `Tmpfs` are still available and can be combined with `Mounts`.
|
||||
* `POST /build` now performs a preliminary validation of the `Dockerfile` before starting the build, and returns an error if the syntax is incorrect. Note that this change is _unversioned_ and applied to all API versions.
|
||||
* `POST /build` accepts `cachefrom` parameter to specify images used for build cache.
|
||||
* `GET /networks/` endpoint now correctly returns a list of *all* networks,
|
||||
instead of the default network if a trailing slash is provided, but no `name`
|
||||
or `id`.
|
||||
* `DELETE /containers/(name)` endpoint now returns an error of `removal of container name is already in progress` with status code of 400, when container name is in a state of removal in progress.
|
||||
* `GET /containers/json` now supports a `is-task` filter to filter
|
||||
containers that are tasks (part of a service in swarm mode).
|
||||
* `POST /containers/create` now takes `StopTimeout` field.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept `Monitor` and `MaxFailureRatio` parameters, which control the response to failures during service updates.
|
||||
* `POST /services/(id or name)/update` now accepts a `ForceUpdate` parameter inside the `TaskTemplate`, which causes the service to be updated even if there are no changes which would ordinarily trigger an update.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now return a `Warnings` array.
|
||||
* `GET /networks/(name)` now returns field `Created` in response to show network created time.
|
||||
* `POST /containers/(id or name)/exec` now accepts an `Env` field, which holds a list of environment variables to be set in the context of the command execution.
|
||||
* `GET /volumes`, `GET /volumes/(name)`, and `POST /volumes/create` now return the `Options` field which holds the driver specific options to use for when creating the volume.
|
||||
* `GET /exec/(id)/json` now returns `Pid`, which is the system pid for the exec'd process.
|
||||
* `POST /containers/prune` prunes stopped containers.
|
||||
* `POST /images/prune` prunes unused images.
|
||||
* `POST /volumes/prune` prunes unused volumes.
|
||||
* `POST /networks/prune` prunes unused networks.
|
||||
* Every API response now includes a `Docker-Experimental` header specifying if experimental features are enabled (value can be `true` or `false`).
|
||||
* Every API response now includes a `API-Version` header specifying the default API version of the server.
|
||||
* The `hostConfig` option now accepts the fields `CpuRealtimePeriod` and `CpuRtRuntime` to allocate cpu runtime to rt tasks when `CONFIG_RT_GROUP_SCHED` is enabled in the kernel.
|
||||
* The `SecurityOptions` field within the `GET /info` response now includes `userns` if user namespaces are enabled in the daemon.
|
||||
* `GET /nodes` and `GET /node/(id or name)` now return `Addr` as part of a node's `Status`, which is the address that that node connects to the manager from.
|
||||
* The `HostConfig` field now includes `NanoCPUs` that represents CPU quota in units of 10<sup>-9</sup> CPUs.
|
||||
* `GET /info` now returns more structured information about security options.
|
||||
* The `HostConfig` field now includes `CpuCount` that represents the number of CPUs available for execution by the container. Windows daemon only.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept the `TTY` parameter, which allocate a pseudo-TTY in container.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept the `DNSConfig` parameter, which specifies DNS related configurations in resolver configuration file (resolv.conf) through `Nameservers`, `Search`, and `Options`.
|
||||
* `GET /networks/(id or name)` now includes IP and name of all peers nodes for swarm mode overlay networks.
|
||||
* `GET /plugins` list plugins.
|
||||
* `POST /plugins/pull?name=<plugin name>` pulls a plugin.
|
||||
* `GET /plugins/(plugin name)` inspect a plugin.
|
||||
* `POST /plugins/(plugin name)/set` configure a plugin.
|
||||
* `POST /plugins/(plugin name)/enable` enable a plugin.
|
||||
* `POST /plugins/(plugin name)/disable` disable a plugin.
|
||||
* `POST /plugins/(plugin name)/push` push a plugin.
|
||||
* `POST /plugins/create?name=(plugin name)` create a plugin.
|
||||
* `DELETE /plugins/(plugin name)` delete a plugin.
|
||||
* `POST /node/(id or name)/update` now accepts both `id` or `name` to identify the node to update.
|
||||
* `GET /images/json` now support a `reference` filter.
|
||||
* `GET /secrets` returns information on the secrets.
|
||||
* `POST /secrets/create` creates a secret.
|
||||
* `DELETE /secrets/{id}` removes the secret `id`.
|
||||
* `GET /secrets/{id}` returns information on the secret `id`.
|
||||
* `POST /secrets/{id}/update` updates the secret `id`.
|
||||
* `POST /services/(id or name)/update` now accepts service name or prefix of service id as a parameter.
|
||||
|
||||
## v1.24 API changes
|
||||
|
||||
[Docker Engine API v1.24](v1.24.md) documentation
|
||||
|
||||
* `POST /containers/create` now takes `StorageOpt` field.
|
||||
* `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported.
|
||||
* `GET /info` no longer returns the `ExecutionDriver` property. This property was no longer used after integration
|
||||
with ContainerD in Docker 1.11.
|
||||
* `GET /networks` now supports filtering by `label` and `driver`.
|
||||
* `GET /containers/json` now supports filtering containers by `network` name or id.
|
||||
* `POST /containers/create` now takes `IOMaximumBandwidth` and `IOMaximumIOps` fields. Windows daemon only.
|
||||
* `POST /containers/create` now returns an HTTP 400 "bad parameter" message
|
||||
if no command is specified (instead of an HTTP 500 "server error")
|
||||
* `GET /images/search` now takes a `filters` query parameter.
|
||||
* `GET /events` now supports a `reload` event that is emitted when the daemon configuration is reloaded.
|
||||
* `GET /events` now supports filtering by daemon name or ID.
|
||||
* `GET /events` now supports a `detach` event that is emitted on detaching from container process.
|
||||
* `GET /events` now supports an `exec_detach ` event that is emitted on detaching from exec process.
|
||||
* `GET /images/json` now supports filters `since` and `before`.
|
||||
* `POST /containers/(id or name)/start` no longer accepts a `HostConfig`.
|
||||
* `POST /images/(name)/tag` no longer has a `force` query parameter.
|
||||
* `GET /images/search` now supports maximum returned search results `limit`.
|
||||
* `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version.
|
||||
* API errors are now returned as JSON instead of plain text.
|
||||
* `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container.
|
||||
* `POST /containers/<container ID>/exec` and `POST /exec/<exec ID>/start`
|
||||
no longer expects a "Container" field to be present. This property was not used
|
||||
and is no longer sent by the docker client.
|
||||
* `POST /containers/create/` now validates the hostname (should be a valid RFC 1123 hostname).
|
||||
* `POST /containers/create/` `HostConfig.PidMode` field now accepts `container:<name|id>`,
|
||||
to have the container join the PID namespace of an existing container.
|
||||
|
||||
## v1.23 API changes
|
||||
|
||||
[Docker Engine API v1.23](v1.23.md) documentation
|
||||
|
||||
* `GET /containers/json` returns the state of the container, one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`.
|
||||
* `GET /containers/json` returns the mount points for the container.
|
||||
* `GET /networks/(name)` now returns an `Internal` field showing whether the network is internal or not.
|
||||
* `GET /networks/(name)` now returns an `EnableIPv6` field showing whether the network has ipv6 enabled or not.
|
||||
* `POST /containers/(name)/update` now supports updating container's restart policy.
|
||||
* `POST /networks/create` now supports enabling ipv6 on the network by setting the `EnableIPv6` field (doing this with a label will no longer work).
|
||||
* `GET /info` now returns `CgroupDriver` field showing what cgroup driver the daemon is using; `cgroupfs` or `systemd`.
|
||||
* `GET /info` now returns `KernelMemory` field, showing if "kernel memory limit" is supported.
|
||||
* `POST /containers/create` now takes `PidsLimit` field, if the kernel is >= 4.3 and the pids cgroup is supported.
|
||||
* `GET /containers/(id or name)/stats` now returns `pids_stats`, if the kernel is >= 4.3 and the pids cgroup is supported.
|
||||
* `POST /containers/create` now allows you to override usernamespaces remapping and use privileged options for the container.
|
||||
* `POST /containers/create` now allows specifying `nocopy` for named volumes, which disables automatic copying from the container path to the volume.
|
||||
* `POST /auth` now returns an `IdentityToken` when supported by a registry.
|
||||
* `POST /containers/create` with both `Hostname` and `Domainname` fields specified will result in the container's hostname being set to `Hostname`, rather than `Hostname.Domainname`.
|
||||
* `GET /volumes` now supports more filters, new added filters are `name` and `driver`.
|
||||
* `GET /containers/(id or name)/logs` now accepts a `details` query parameter to stream the extra attributes that were provided to the containers `LogOpts`, such as environment variables and labels, with the logs.
|
||||
* `POST /images/load` now returns progress information as a JSON stream, and has a `quiet` query parameter to suppress progress details.
|
||||
|
||||
## v1.22 API changes
|
||||
|
||||
[Docker Engine API v1.22](v1.22.md) documentation
|
||||
|
||||
* `POST /container/(name)/update` updates the resources of a container.
|
||||
* `GET /containers/json` supports filter `isolation` on Windows.
|
||||
* `GET /containers/json` now returns the list of networks of containers.
|
||||
* `GET /info` Now returns `Architecture` and `OSType` fields, providing information
|
||||
about the host architecture and operating system type that the daemon runs on.
|
||||
* `GET /networks/(name)` now returns a `Name` field for each container attached to the network.
|
||||
* `GET /version` now returns the `BuildTime` field in RFC3339Nano format to make it
|
||||
consistent with other date/time values returned by the API.
|
||||
* `AuthConfig` now supports a `registrytoken` for token based authentication
|
||||
* `POST /containers/create` now has a 4M minimum value limit for `HostConfig.KernelMemory`
|
||||
* Pushes initiated with `POST /images/(name)/push` and pulls initiated with `POST /images/create`
|
||||
will be cancelled if the HTTP connection making the API request is closed before
|
||||
the push or pull completes.
|
||||
* `POST /containers/create` now allows you to set a read/write rate limit for a
|
||||
device (in bytes per second or IO per second).
|
||||
* `GET /networks` now supports filtering by `name`, `id` and `type`.
|
||||
* `POST /containers/create` now allows you to set the static IPv4 and/or IPv6 address for the container.
|
||||
* `POST /networks/(id)/connect` now allows you to set the static IPv4 and/or IPv6 address for the container.
|
||||
* `GET /info` now includes the number of containers running, stopped, and paused.
|
||||
* `POST /networks/create` now supports restricting external access to the network by setting the `Internal` field.
|
||||
* `POST /networks/(id)/disconnect` now includes a `Force` option to forcefully disconnect a container from network
|
||||
* `GET /containers/(id)/json` now returns the `NetworkID` of containers.
|
||||
* `POST /networks/create` Now supports an options field in the IPAM config that provides options
|
||||
for custom IPAM plugins.
|
||||
* `GET /networks/{network-id}` Now returns IPAM config options for custom IPAM plugins if any
|
||||
are available.
|
||||
* `GET /networks/<network-id>` now returns subnets info for user-defined networks.
|
||||
* `GET /info` can now return a `SystemStatus` field useful for returning additional information about applications
|
||||
that are built on top of engine.
|
||||
|
||||
## v1.21 API changes
|
||||
|
||||
[Docker Engine API v1.21](v1.21.md) documentation
|
||||
|
||||
* `GET /volumes` lists volumes from all volume drivers.
|
||||
* `POST /volumes/create` to create a volume.
|
||||
* `GET /volumes/(name)` get low-level information about a volume.
|
||||
* `DELETE /volumes/(name)` remove a volume with the specified name.
|
||||
* `VolumeDriver` was moved from `config` to `HostConfig` to make the configuration portable.
|
||||
* `GET /images/(name)/json` now returns information about an image's `RepoTags` and `RepoDigests`.
|
||||
* The `config` option now accepts the field `StopSignal`, which specifies the signal to use to kill a container.
|
||||
* `GET /containers/(id)/stats` will return networking information respectively for each interface.
|
||||
* The `HostConfig` option now includes the `DnsOptions` field to configure the container's DNS options.
|
||||
* `POST /build` now optionally takes a serialized map of build-time variables.
|
||||
* `GET /events` now includes a `timenano` field, in addition to the existing `time` field.
|
||||
* `GET /events` now supports filtering by image and container labels.
|
||||
* `GET /info` now lists engine version information and return the information of `CPUShares` and `Cpuset`.
|
||||
* `GET /containers/json` will return `ImageID` of the image used by container.
|
||||
* `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused.
|
||||
* `POST /containers/create` now takes `KernelMemory` in HostConfig to specify kernel memory limit.
|
||||
* `GET /containers/(name)/json` now accepts a `size` parameter. Setting this parameter to '1' returns container size information in the `SizeRw` and `SizeRootFs` fields.
|
||||
* `GET /containers/(name)/json` now returns a `NetworkSettings.Networks` field,
|
||||
detailing network settings per network. This field deprecates the
|
||||
`NetworkSettings.Gateway`, `NetworkSettings.IPAddress`,
|
||||
`NetworkSettings.IPPrefixLen`, and `NetworkSettings.MacAddress` fields, which
|
||||
are still returned for backward-compatibility, but will be removed in a future version.
|
||||
* `GET /exec/(id)/json` now returns a `NetworkSettings.Networks` field,
|
||||
detailing networksettings per network. This field deprecates the
|
||||
`NetworkSettings.Gateway`, `NetworkSettings.IPAddress`,
|
||||
`NetworkSettings.IPPrefixLen`, and `NetworkSettings.MacAddress` fields, which
|
||||
are still returned for backward-compatibility, but will be removed in a future version.
|
||||
* The `HostConfig` option now includes the `OomScoreAdj` field for adjusting the
|
||||
badness heuristic. This heuristic selects which processes the OOM killer kills
|
||||
under out-of-memory conditions.
|
||||
|
||||
## v1.20 API changes
|
||||
|
||||
[Docker Engine API v1.20](v1.20.md) documentation
|
||||
|
||||
* `GET /containers/(id)/archive` get an archive of filesystem content from a container.
|
||||
* `PUT /containers/(id)/archive` upload an archive of content to be extracted to
|
||||
an existing directory inside a container's filesystem.
|
||||
* `POST /containers/(id)/copy` is deprecated in favor of the above `archive`
|
||||
endpoint which can be used to download files and directories from a container.
|
||||
* The `hostConfig` option now accepts the field `GroupAdd`, which specifies a
|
||||
list of additional groups that the container process will run as.
|
||||
|
||||
## v1.19 API changes
|
||||
|
||||
[Docker Engine API v1.19](v1.19.md) documentation
|
||||
|
||||
* When the daemon detects a version mismatch with the client, usually when
|
||||
the client is newer than the daemon, an HTTP 400 is now returned instead
|
||||
of a 404.
|
||||
* `GET /containers/(id)/stats` now accepts `stream` bool to get only one set of stats and disconnect.
|
||||
* `GET /containers/(id)/logs` now accepts a `since` timestamp parameter.
|
||||
* `GET /info` The fields `Debug`, `IPv4Forwarding`, `MemoryLimit`, and
|
||||
`SwapLimit` are now returned as boolean instead of as an int. In addition, the
|
||||
end point now returns the new boolean fields `CpuCfsPeriod`, `CpuCfsQuota`, and
|
||||
`OomKillDisable`.
|
||||
* The `hostConfig` option now accepts the fields `CpuPeriod` and `CpuQuota`
|
||||
* `POST /build` accepts `cpuperiod` and `cpuquota` options
|
||||
|
||||
## v1.18 API changes
|
||||
|
||||
[Docker Engine API v1.18](v1.18.md) documentation
|
||||
|
||||
* `GET /version` now returns `Os`, `Arch` and `KernelVersion`.
|
||||
* `POST /containers/create` and `POST /containers/(id)/start`allow you to set ulimit settings for use in the container.
|
||||
* `GET /info` now returns `SystemTime`, `HttpProxy`,`HttpsProxy` and `NoProxy`.
|
||||
* `GET /images/json` added a `RepoDigests` field to include image digest information.
|
||||
* `POST /build` can now set resource constraints for all containers created for the build.
|
||||
* `CgroupParent` can be passed in the host config to setup container cgroups under a specific cgroup.
|
||||
* `POST /build` closing the HTTP request cancels the build
|
||||
* `POST /containers/(id)/exec` includes `Warnings` field to response.
|
||||
@@ -0,0 +1,290 @@
|
||||
---
|
||||
aliases: ["/engine/misc/deprecated/"]
|
||||
title: "Deprecated Engine Features"
|
||||
description: "Deprecated Features."
|
||||
keywords: "docker, documentation, about, technology, deprecate"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Deprecated Engine Features
|
||||
|
||||
The following list of features are deprecated in Engine.
|
||||
To learn more about Docker Engine's deprecation policy,
|
||||
see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-deprecation-policy).
|
||||
|
||||
|
||||
### Top-level network properties in NetworkSettings
|
||||
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
When inspecting a container, `NetworkSettings` contains top-level information
|
||||
about the default ("bridge") network;
|
||||
|
||||
`EndpointID`, `Gateway`, `GlobalIPv6Address`, `GlobalIPv6PrefixLen`, `IPAddress`,
|
||||
`IPPrefixLen`, `IPv6Gateway`, and `MacAddress`.
|
||||
|
||||
These properties are deprecated in favor of per-network properties in
|
||||
`NetworkSettings.Networks`. These properties were already "deprecated" in
|
||||
docker 1.9, but kept around for backward compatibility.
|
||||
|
||||
Refer to [#17538](https://github.com/docker/docker/pull/17538) for further
|
||||
information.
|
||||
|
||||
### `filter` param for `/images/json` endpoint
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
The `filter` param to filter the list of image by reference (name or name:tag) is now implemented as a regular filter, named `reference`.
|
||||
|
||||
### `repository:shortid` image references
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
`repository:shortid` syntax for referencing images is very little used, collides with tag references can be confused with digest references.
|
||||
|
||||
### `docker daemon` subcommand
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
The daemon is moved to a separate binary (`dockerd`), and should be used instead.
|
||||
|
||||
### Duplicate keys with conflicting values in engine labels
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
Duplicate keys with conflicting values have been deprecated. A warning is displayed
|
||||
in the output, and an error will be returned in the future.
|
||||
|
||||
### `MAINTAINER` in Dockerfile
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
`MAINTAINER` was an early very limited form of `LABEL` which should be used instead.
|
||||
|
||||
### API calls without a version
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
API versions should be supplied to all API calls to ensure compatibility with
|
||||
future Engine versions. Instead of just requesting, for example, the URL
|
||||
`/containers/json`, you must now request `/v1.25/containers/json`.
|
||||
|
||||
### Backing filesystem without `d_type` support for overlay/overlay2
|
||||
**Deprecated In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
The overlay and overlay2 storage driver does not work as expected if the backing
|
||||
filesystem does not support `d_type`. For example, XFS does not support `d_type`
|
||||
if it is formatted with the `ftype=0` option.
|
||||
|
||||
Please also refer to [#27358](https://github.com/docker/docker/issues/27358) for
|
||||
further information.
|
||||
|
||||
### Three arguments form in `docker import`
|
||||
**Deprecated In Release: [v0.6.7](https://github.com/docker/docker/releases/tag/v0.6.7)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
The `docker import` command format `file|URL|- [REPOSITORY [TAG]]` is deprecated since November 2013. It's no more supported.
|
||||
|
||||
### `-h` shorthand for `--help`
|
||||
|
||||
**Deprecated In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
**Target For Removal In Release: v17.09**
|
||||
|
||||
The shorthand (`-h`) is less common than `--help` on Linux and cannot be used
|
||||
on all subcommands (due to it conflicting with, e.g. `-h` / `--hostname` on
|
||||
`docker create`). For this reason, the `-h` shorthand was not printed in the
|
||||
"usage" output of subcommands, nor documented, and is now marked "deprecated".
|
||||
|
||||
### `-e` and `--email` flags on `docker login`
|
||||
**Deprecated In Release: [v1.11.0](https://github.com/docker/docker/releases/tag/v1.11.0)**
|
||||
|
||||
**Target For Removal In Release: v17.06**
|
||||
|
||||
The docker login command is removing the ability to automatically register for an account with the target registry if the given username doesn't exist. Due to this change, the email flag is no longer required, and will be deprecated.
|
||||
|
||||
### Separator (`:`) of `--security-opt` flag on `docker run`
|
||||
**Deprecated In Release: [v1.11.0](https://github.com/docker/docker/releases/tag/v1.11.0)**
|
||||
|
||||
**Target For Removal In Release: v17.06**
|
||||
|
||||
The flag `--security-opt` doesn't use the colon separator(`:`) anymore to divide keys and values, it uses the equal symbol(`=`) for consistency with other similar flags, like `--storage-opt`.
|
||||
|
||||
### `/containers/(id or name)/copy` endpoint
|
||||
|
||||
**Deprecated In Release: [v1.8.0](https://github.com/docker/docker/releases/tag/v1.8.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
The endpoint `/containers/(id or name)/copy` is deprecated in favor of `/containers/(id or name)/archive`.
|
||||
|
||||
### Ambiguous event fields in API
|
||||
**Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
The fields `ID`, `Status` and `From` in the events API have been deprecated in favor of a more rich structure.
|
||||
See the events API documentation for the new format.
|
||||
|
||||
### `-f` flag on `docker tag`
|
||||
**Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
To make tagging consistent across the various `docker` commands, the `-f` flag on the `docker tag` command is deprecated. It is not longer necessary to specify `-f` to move a tag from one image to another. Nor will `docker` generate an error if the `-f` flag is missing and the specified tag is already in use.
|
||||
|
||||
### HostConfig at API container start
|
||||
**Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
Passing an `HostConfig` to `POST /containers/{name}/start` is deprecated in favor of
|
||||
defining it at container creation (`POST /containers/create`).
|
||||
|
||||
### `--before` and `--since` flags on `docker ps`
|
||||
|
||||
**Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
The `docker ps --before` and `docker ps --since` options are deprecated.
|
||||
Use `docker ps --filter=before=...` and `docker ps --filter=since=...` instead.
|
||||
|
||||
### `--automated` and `--stars` flags on `docker search`
|
||||
|
||||
**Deprecated in Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
**Target For Removal In Release: v17.09**
|
||||
|
||||
The `docker search --automated` and `docker search --stars` options are deprecated.
|
||||
Use `docker search --filter=is-automated=...` and `docker search --filter=stars=...` instead.
|
||||
|
||||
### Driver Specific Log Tags
|
||||
**Deprecated In Release: [v1.9.0](https://github.com/docker/docker/releases/tag/v1.9.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
Log tags are now generated in a standard way across different logging drivers.
|
||||
Because of which, the driver specific log tag options `syslog-tag`, `gelf-tag` and
|
||||
`fluentd-tag` have been deprecated in favor of the generic `tag` option.
|
||||
|
||||
```bash
|
||||
{% raw %}
|
||||
docker --log-driver=syslog --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}"
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
### LXC built-in exec driver
|
||||
**Deprecated In Release: [v1.8.0](https://github.com/docker/docker/releases/tag/v1.8.0)**
|
||||
|
||||
**Removed In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
The built-in LXC execution driver, the lxc-conf flag, and API fields have been removed.
|
||||
|
||||
### Old Command Line Options
|
||||
**Deprecated In Release: [v1.8.0](https://github.com/docker/docker/releases/tag/v1.8.0)**
|
||||
|
||||
**Removed In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)**
|
||||
|
||||
The flags `-d` and `--daemon` are deprecated in favor of the `daemon` subcommand:
|
||||
|
||||
docker daemon -H ...
|
||||
|
||||
The following single-dash (`-opt`) variant of certain command line options
|
||||
are deprecated and replaced with double-dash options (`--opt`):
|
||||
|
||||
docker attach -nostdin
|
||||
docker attach -sig-proxy
|
||||
docker build -no-cache
|
||||
docker build -rm
|
||||
docker commit -author
|
||||
docker commit -run
|
||||
docker events -since
|
||||
docker history -notrunc
|
||||
docker images -notrunc
|
||||
docker inspect -format
|
||||
docker ps -beforeId
|
||||
docker ps -notrunc
|
||||
docker ps -sinceId
|
||||
docker rm -link
|
||||
docker run -cidfile
|
||||
docker run -dns
|
||||
docker run -entrypoint
|
||||
docker run -expose
|
||||
docker run -link
|
||||
docker run -lxc-conf
|
||||
docker run -n
|
||||
docker run -privileged
|
||||
docker run -volumes-from
|
||||
docker search -notrunc
|
||||
docker search -stars
|
||||
docker search -t
|
||||
docker search -trusted
|
||||
docker tag -force
|
||||
|
||||
The following double-dash options are deprecated and have no replacement:
|
||||
|
||||
docker run --cpuset
|
||||
docker run --networking
|
||||
docker ps --since-id
|
||||
docker ps --before-id
|
||||
docker search --trusted
|
||||
|
||||
**Deprecated In Release: [v1.5.0](https://github.com/docker/docker/releases/tag/v1.5.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
The single-dash (`-help`) was removed, in favor of the double-dash `--help`
|
||||
|
||||
docker -help
|
||||
docker [COMMAND] -help
|
||||
|
||||
### `--run` flag on docker commit
|
||||
|
||||
**Deprecated In Release: [v0.10.0](https://github.com/docker/docker/releases/tag/v0.10.0)**
|
||||
|
||||
**Removed In Release: [v1.13.0](https://github.com/docker/docker/releases/tag/v1.13.0)**
|
||||
|
||||
The flag `--run` of the docker commit (and its short version `-run`) were deprecated in favor
|
||||
of the `--changes` flag that allows to pass `Dockerfile` commands.
|
||||
|
||||
|
||||
### Interacting with V1 registries
|
||||
|
||||
**Disabled By Default In Release: v17.04**
|
||||
|
||||
**Target For Removal In Release: v17.10**
|
||||
|
||||
Version 1.9 adds a flag (`--disable-legacy-registry=false`) which prevents the
|
||||
docker daemon from `pull`, `push`, and `login` operations against v1
|
||||
registries. Though enabled by default, this signals the intent to deprecate
|
||||
the v1 protocol.
|
||||
|
||||
Support for the v1 protocol to the public registry was removed in 1.13. Any
|
||||
mirror configurations using v1 should be updated to use a
|
||||
[v2 registry mirror](https://docs.docker.com/registry/recipes/mirror/).
|
||||
|
||||
### Docker Content Trust ENV passphrase variables name change
|
||||
**Deprecated In Release: [v1.9.0](https://github.com/docker/docker/releases/tag/v1.9.0)**
|
||||
|
||||
**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
|
||||
|
||||
Since 1.9, Docker Content Trust Offline key has been renamed to Root key and the Tagging key has been renamed to Repository key. Due to this renaming, we're also changing the corresponding environment variables
|
||||
|
||||
- DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE is now named DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE
|
||||
- DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE is now named DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE
|
||||
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1 @@
|
||||
12
|
||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,101 @@
|
||||
---
|
||||
redirect_from:
|
||||
- "/engine/extend/plugins/"
|
||||
title: "Use Docker Engine plugins"
|
||||
description: "How to add additional functionality to Docker with plugins extensions"
|
||||
keywords: "Examples, Usage, plugins, docker, documentation, user guide"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
This document describes the Docker Engine plugins generally available in Docker
|
||||
Engine. To view information on plugins managed by Docker,
|
||||
refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
You can extend the capabilities of the Docker Engine by loading third-party
|
||||
plugins. This page explains the types of plugins and provides links to several
|
||||
volume and network plugins for Docker.
|
||||
|
||||
## Types of plugins
|
||||
|
||||
Plugins extend Docker's functionality. They come in specific types. For
|
||||
example, a [volume plugin](plugins_volume.md) might enable Docker
|
||||
volumes to persist across multiple Docker hosts and a
|
||||
[network plugin](plugins_network.md) might provide network plumbing.
|
||||
|
||||
Currently Docker supports authorization, volume and network driver plugins. In the future it
|
||||
will support additional plugin types.
|
||||
|
||||
## Installing a plugin
|
||||
|
||||
Follow the instructions in the plugin's documentation.
|
||||
|
||||
## Finding a plugin
|
||||
|
||||
The sections below provide an inexhaustive overview of available plugins.
|
||||
|
||||
<style>
|
||||
#DocumentationText tr td:first-child { white-space: nowrap;}
|
||||
</style>
|
||||
|
||||
### Network plugins
|
||||
|
||||
Plugin | Description
|
||||
----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Contiv Networking](https://github.com/contiv/netplugin) | An open source network plugin to provide infrastructure and security policies for a multi-tenant micro services deployment, while providing an integration to physical network for non-container workload. Contiv Networking implements the remote driver and IPAM APIs available in Docker 1.9 onwards.
|
||||
[Kuryr Network Plugin](https://github.com/openstack/kuryr) | A network plugin is developed as part of the OpenStack Kuryr project and implements the Docker networking (libnetwork) remote driver API by utilizing Neutron, the OpenStack networking service. It includes an IPAM driver as well.
|
||||
[Weave Network Plugin](https://www.weave.works/docs/net/latest/introducing-weave/) | A network plugin that creates a virtual network that connects your Docker containers - across multiple hosts or clouds and enables automatic discovery of applications. Weave networks are resilient, partition tolerant, secure and work in partially connected networks, and other adverse environments - all configured with delightful simplicity.
|
||||
|
||||
### Volume plugins
|
||||
|
||||
Plugin | Description
|
||||
----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Azure File Storage plugin](https://github.com/Azure/azurefile-dockervolumedriver) | Lets you mount Microsoft [Azure File Storage](https://azure.microsoft.com/blog/azure-file-storage-now-generally-available/) shares to Docker containers as volumes using the SMB 3.0 protocol. [Learn more](https://azure.microsoft.com/blog/persistent-docker-volumes-with-azure-file-storage/).
|
||||
[BeeGFS Volume Plugin](https://github.com/RedCoolBeans/docker-volume-beegfs) | An open source volume plugin to create persistent volumes in a BeeGFS parallel file system.
|
||||
[Blockbridge plugin](https://github.com/blockbridge/blockbridge-docker-volume) | A volume plugin that provides access to an extensible set of container-based persistent storage options. It supports single and multi-host Docker environments with features that include tenant isolation, automated provisioning, encryption, secure deletion, snapshots and QoS.
|
||||
[Contiv Volume Plugin](https://github.com/contiv/volplugin) | An open source volume plugin that provides multi-tenant, persistent, distributed storage with intent based consumption. It has support for Ceph and NFS.
|
||||
[Convoy plugin](https://github.com/rancher/convoy) | A volume plugin for a variety of storage back-ends including device mapper and NFS. It's a simple standalone executable written in Go and provides the framework to support vendor-specific extensions such as snapshots, backups and restore.
|
||||
[DigitalOcean Block Storage plugin](https://github.com/omallo/docker-volume-plugin-dostorage) | Integrates DigitalOcean's [block storage solution](https://www.digitalocean.com/products/storage/) into the Docker ecosystem by automatically attaching a given block storage volume to a DigitalOcean droplet and making the contents of the volume available to Docker containers running on that droplet.
|
||||
[DRBD plugin](https://www.drbd.org/en/supported-projects/docker) | A volume plugin that provides highly available storage replicated by [DRBD](https://www.drbd.org). Data written to the docker volume is replicated in a cluster of DRBD nodes.
|
||||
[Flocker plugin](https://clusterhq.com/docker-plugin/) | A volume plugin that provides multi-host portable volumes for Docker, enabling you to run databases and other stateful containers and move them around across a cluster of machines.
|
||||
[Fuxi Volume Plugin](https://github.com/openstack/fuxi) | A volume plugin that is developed as part of the OpenStack Kuryr project and implements the Docker volume plugin API by utilizing Cinder, the OpenStack block storage service.
|
||||
[gce-docker plugin](https://github.com/mcuadros/gce-docker) | A volume plugin able to attach, format and mount Google Compute [persistent-disks](https://cloud.google.com/compute/docs/disks/persistent-disks).
|
||||
[GlusterFS plugin](https://github.com/calavera/docker-volume-glusterfs) | A volume plugin that provides multi-host volumes management for Docker using GlusterFS.
|
||||
[Horcrux Volume Plugin](https://github.com/muthu-r/horcrux) | A volume plugin that allows on-demand, version controlled access to your data. Horcrux is an open-source plugin, written in Go, and supports SCP, [Minio](https://www.minio.io) and Amazon S3.
|
||||
[HPE 3Par Volume Plugin](https://github.com/hpe-storage/python-hpedockerplugin/) | A volume plugin that supports HPE 3Par and StoreVirtual iSCSI storage arrays.
|
||||
[IPFS Volume Plugin](http://github.com/vdemeester/docker-volume-ipfs) | An open source volume plugin that allows using an [ipfs](https://ipfs.io/) filesystem as a volume.
|
||||
[Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) | A plugin that provides credentials and secret management using Keywhiz as a central repository.
|
||||
[Local Persist Plugin](https://github.com/CWSpear/local-persist) | A volume plugin that extends the default `local` driver's functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to *always persist*, even if the volume is removed via `docker volume rm`.
|
||||
[NetApp Plugin](https://github.com/NetApp/netappdvp) (nDVP) | A volume plugin that provides direct integration with the Docker ecosystem for the NetApp storage portfolio. The nDVP package supports the provisioning and management of storage resources from the storage platform to Docker hosts, with a robust framework for adding additional platforms in the future.
|
||||
[Netshare plugin](https://github.com/ContainX/docker-volume-netshare) | A volume plugin that provides volume management for NFS 3/4, AWS EFS and CIFS file systems.
|
||||
[Nimble Storage Volume Plugin](https://connect.nimblestorage.com/community/app-integration/docker)| A volume plug-in that integrates with Nimble Storage Unified Flash Fabric arrays. The plug-in abstracts array volume capabilities to the Docker administrator to allow self-provisioning of secure multi-tenant volumes and clones.
|
||||
[OpenStorage Plugin](https://github.com/libopenstorage/openstorage) | A cluster-aware volume plugin that provides volume management for file and block storage solutions. It implements a vendor neutral specification for implementing extensions such as CoS, encryption, and snapshots. It has example drivers based on FUSE, NFS, NBD and EBS to name a few.
|
||||
[Portworx Volume Plugin](https://github.com/portworx/px-dev) | A volume plugin that turns any server into a scale-out converged compute/storage node, providing container granular storage and highly available volumes across any node, using a shared-nothing storage backend that works with any docker scheduler.
|
||||
[Quobyte Volume Plugin](https://github.com/quobyte/docker-volume) | A volume plugin that connects Docker to [Quobyte](http://www.quobyte.com/containers)'s data center file system, a general-purpose scalable and fault-tolerant storage platform.
|
||||
[REX-Ray plugin](https://github.com/emccode/rexray) | A volume plugin which is written in Go and provides advanced storage functionality for many platforms including VirtualBox, EC2, Google Compute Engine, OpenStack, and EMC.
|
||||
[Virtuozzo Storage and Ploop plugin](https://github.com/virtuozzo/docker-volume-ploop) | A volume plugin with support for Virtuozzo Storage distributed cloud file system as well as ploop devices.
|
||||
[VMware vSphere Storage Plugin](https://github.com/vmware/docker-volume-vsphere) | Docker Volume Driver for vSphere enables customers to address persistent storage requirements for Docker containers in vSphere environments.
|
||||
|
||||
### Authorization plugins
|
||||
|
||||
Plugin | Description
|
||||
------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Casbin AuthZ Plugin](https://github.com/casbin/casbin-authz-plugin) | An authorization plugin based on [Casbin](https://github.com/casbin/casbin), which supports access control models like ACL, RBAC, ABAC. The access control model can be customized. The policy can be persisted into file or DB.
|
||||
[Twistlock AuthZ Broker](https://github.com/twistlock/authz) | A basic extendable authorization plugin that runs directly on the host or inside a container. This plugin allows you to define user policies that it evaluates during authorization. Basic authorization is provided if Docker daemon is started with the --tlsverify flag (username is extracted from the certificate common name).
|
||||
|
||||
## Troubleshooting a plugin
|
||||
|
||||
If you are having problems with Docker after loading a plugin, ask the authors
|
||||
of the plugin for help. The Docker team may not be able to assist you.
|
||||
|
||||
## Writing a plugin
|
||||
|
||||
If you are interested in writing a plugin for Docker, or seeing how they work
|
||||
under the hood, see the [docker plugins reference](plugin_api.md).
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,225 @@
|
||||
---
|
||||
title: "Plugin config"
|
||||
description: "How develop and use a plugin with the managed plugin system"
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
|
||||
# Plugin Config Version 1 of Plugin V2
|
||||
|
||||
This document outlines the format of the V0 plugin configuration. The plugin
|
||||
config described herein was introduced in the Docker daemon in the [v1.12.0
|
||||
release](https://github.com/docker/docker/commit/f37117045c5398fd3dca8016ea8ca0cb47e7312b).
|
||||
|
||||
Plugin configs describe the various constituents of a docker plugin. Plugin
|
||||
configs can be serialized to JSON format with the following media types:
|
||||
|
||||
Config Type | Media Type
|
||||
------------- | -------------
|
||||
config | "application/vnd.docker.plugin.v1+json"
|
||||
|
||||
|
||||
## *Config* Field Descriptions
|
||||
|
||||
Config provides the base accessible fields for working with V0 plugin format
|
||||
in the registry.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the plugin
|
||||
|
||||
- **`documentation`** *string*
|
||||
|
||||
link to the documentation about the plugin
|
||||
|
||||
- **`interface`** *PluginInterface*
|
||||
|
||||
interface implemented by the plugins, struct consisting of the following fields
|
||||
|
||||
- **`types`** *string array*
|
||||
|
||||
types indicate what interface(s) the plugin currently implements.
|
||||
|
||||
currently supported:
|
||||
|
||||
- **docker.volumedriver/1.0**
|
||||
|
||||
- **docker.authz/1.0**
|
||||
|
||||
- **`socket`** *string*
|
||||
|
||||
socket is the name of the socket the engine should use to communicate with the plugins.
|
||||
the socket will be created in `/run/docker/plugins`.
|
||||
|
||||
|
||||
- **`entrypoint`** *string array*
|
||||
|
||||
entrypoint of the plugin, see [`ENTRYPOINT`](../reference/builder.md#entrypoint)
|
||||
|
||||
- **`workdir`** *string*
|
||||
|
||||
workdir of the plugin, see [`WORKDIR`](../reference/builder.md#workdir)
|
||||
|
||||
- **`network`** *PluginNetwork*
|
||||
|
||||
network of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`type`** *string*
|
||||
|
||||
network type.
|
||||
|
||||
currently supported:
|
||||
|
||||
- **bridge**
|
||||
- **host**
|
||||
- **none**
|
||||
|
||||
- **`mounts`** *PluginMount array*
|
||||
|
||||
mount of the plugin, struct consisting of the following fields, see [`MOUNTS`](https://github.com/opencontainers/runtime-spec/blob/master/config.md#mounts)
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the mount.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the mount.
|
||||
|
||||
- **`source`** *string*
|
||||
|
||||
source of the mount.
|
||||
|
||||
- **`destination`** *string*
|
||||
|
||||
destination of the mount.
|
||||
|
||||
- **`type`** *string*
|
||||
|
||||
mount type.
|
||||
|
||||
- **`options`** *string array*
|
||||
|
||||
options of the mount.
|
||||
|
||||
- **`propagatedMount`** *string*
|
||||
|
||||
path to be mounted as rshared, so that mounts under that path are visible to docker. This is useful for volume plugins.
|
||||
This path will be bind-mounted outisde of the plugin rootfs so it's contents
|
||||
are preserved on upgrade.
|
||||
|
||||
- **`env`** *PluginEnv array*
|
||||
|
||||
env of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the env.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the env.
|
||||
|
||||
- **`value`** *string*
|
||||
|
||||
value of the env.
|
||||
|
||||
- **`args`** *PluginArgs*
|
||||
|
||||
args of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the args.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the args.
|
||||
|
||||
- **`value`** *string array*
|
||||
|
||||
values of the args.
|
||||
|
||||
- **`linux`** *PluginLinux*
|
||||
|
||||
- **`capabilities`** *string array*
|
||||
|
||||
capabilities of the plugin (*Linux only*), see list [`here`](https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md#security)
|
||||
|
||||
- **`allowAllDevices`** *boolean*
|
||||
|
||||
If `/dev` is bind mounted from the host, and allowAllDevices is set to true, the plugin will have `rwm` access to all devices on the host.
|
||||
|
||||
- **`devices`** *PluginDevice array*
|
||||
|
||||
device of the plugin, (*Linux only*), struct consisting of the following fields, see [`DEVICES`](https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#devices)
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the device.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the device.
|
||||
|
||||
- **`path`** *string*
|
||||
|
||||
path of the device.
|
||||
|
||||
## Example Config
|
||||
|
||||
*Example showing the 'tiborvass/sample-volume-plugin' plugin config.*
|
||||
|
||||
```json
|
||||
{
|
||||
"Args": {
|
||||
"Description": "",
|
||||
"Name": "",
|
||||
"Settable": null,
|
||||
"Value": null
|
||||
},
|
||||
"Description": "A sample volume plugin for Docker",
|
||||
"Documentation": "https://docs.docker.com/engine/extend/plugins/",
|
||||
"Entrypoint": [
|
||||
"/usr/bin/sample-volume-plugin",
|
||||
"/data"
|
||||
],
|
||||
"Env": [
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "DEBUG",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": "0"
|
||||
}
|
||||
],
|
||||
"Interface": {
|
||||
"Socket": "plugin.sock",
|
||||
"Types": [
|
||||
"docker.volumedriver/1.0"
|
||||
]
|
||||
},
|
||||
"Linux": {
|
||||
"Capabilities": null,
|
||||
"AllowAllDevices": false,
|
||||
"Devices": null
|
||||
},
|
||||
"Mounts": null,
|
||||
"Network": {
|
||||
"Type": ""
|
||||
},
|
||||
"PropagatedMount": "/data",
|
||||
"User": {},
|
||||
"Workdir": ""
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,360 @@
|
||||
---
|
||||
title: "Volume plugins"
|
||||
description: "How to manage data with external volume plugins"
|
||||
keywords: "Examples, Usage, volume, docker, data, volumes, plugin, api"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Write a volume plugin
|
||||
|
||||
Docker Engine volume plugins enable Engine deployments to be integrated with
|
||||
external storage systems such as Amazon EBS, and enable data volumes to persist
|
||||
beyond the lifetime of a single Docker host. See the
|
||||
[plugin documentation](legacy_plugins.md) for more information.
|
||||
|
||||
## Changelog
|
||||
|
||||
### 1.13.0
|
||||
|
||||
- If used as part of the v2 plugin architecture, mountpoints that are part of
|
||||
paths returned by the plugin must be mounted under the directory specified by
|
||||
`PropagatedMount` in the plugin configuration
|
||||
([#26398](https://github.com/docker/docker/pull/26398))
|
||||
|
||||
### 1.12.0
|
||||
|
||||
- Add `Status` field to `VolumeDriver.Get` response
|
||||
([#21006](https://github.com/docker/docker/pull/21006#))
|
||||
- Add `VolumeDriver.Capabilities` to get capabilities of the volume driver
|
||||
([#22077](https://github.com/docker/docker/pull/22077))
|
||||
|
||||
### 1.10.0
|
||||
|
||||
- Add `VolumeDriver.Get` which gets the details about the volume
|
||||
([#16534](https://github.com/docker/docker/pull/16534))
|
||||
- Add `VolumeDriver.List` which lists all volumes owned by the driver
|
||||
([#16534](https://github.com/docker/docker/pull/16534))
|
||||
|
||||
### 1.8.0
|
||||
|
||||
- Initial support for volume driver plugins
|
||||
([#14659](https://github.com/docker/docker/pull/14659))
|
||||
|
||||
## Command-line changes
|
||||
|
||||
To give a container access to a volume, use the `--volume` and `--volume-driver`
|
||||
flags on the `docker container run` command. The `--volume` (or `-v`) flag
|
||||
accepts a volume name and path on the host, and the `--volume-driver` flag
|
||||
accepts a driver type.
|
||||
|
||||
```bash
|
||||
$ docker volume create --driver=flocker volumename
|
||||
|
||||
$ docker container run -it --volume volumename:/data busybox sh
|
||||
```
|
||||
|
||||
### `--volume`
|
||||
|
||||
The `--volume` (or `-v`) flag takes a value that is in the format
|
||||
`<volume_name>:<mountpoint>`. The two parts of the value are
|
||||
separated by a colon (`:`) character.
|
||||
|
||||
- The volume name is a human-readable name for the volume, and cannot begin with
|
||||
a `/` character. It is referred to as `volume_name` in the rest of this topic.
|
||||
- The `Mountpoint` is the path on the host (v1) or in the plugin (v2) where the
|
||||
volume has been made available.
|
||||
|
||||
### `volumedriver`
|
||||
|
||||
Specifying a `volumedriver` in conjunction with a `volumename` allows you to
|
||||
use plugins such as [Flocker](https://github.com/ScatterHQ/flocker) to manage
|
||||
volumes external to a single host, such as those on EBS.
|
||||
|
||||
## Create a VolumeDriver
|
||||
|
||||
The container creation endpoint (`/containers/create`) accepts a `VolumeDriver`
|
||||
field of type `string` allowing to specify the name of the driver. If not
|
||||
specified, it defaults to `"local"` (the default driver for local volumes).
|
||||
|
||||
## Volume plugin protocol
|
||||
|
||||
If a plugin registers itself as a `VolumeDriver` when activated, it must
|
||||
provide the Docker Daemon with writeable paths on the host filesystem. The Docker
|
||||
daemon provides these paths to containers to consume. The Docker daemon makes
|
||||
the volumes available by bind-mounting the provided paths into the containers.
|
||||
|
||||
> **Note**: Volume plugins should *not* write data to the `/var/lib/docker/`
|
||||
> directory, including `/var/lib/docker/volumes`. The `/var/lib/docker/`
|
||||
> directory is reserved for Docker.
|
||||
|
||||
### `/VolumeDriver.Create`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name",
|
||||
"Opts": {}
|
||||
}
|
||||
```
|
||||
|
||||
Instruct the plugin that the user wants to create a volume, given a user
|
||||
specified volume name. The plugin does not need to actually manifest the
|
||||
volume on the filesystem yet (until `Mount` is called).
|
||||
`Opts` is a map of driver specific options passed through from the user request.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a string error if an error occurred.
|
||||
|
||||
### `/VolumeDriver.Remove`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name"
|
||||
}
|
||||
```
|
||||
|
||||
Delete the specified volume from disk. This request is issued when a user
|
||||
invokes `docker rm -v` to remove volumes associated with a container.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a string error if an error occurred.
|
||||
|
||||
### `/VolumeDriver.Mount`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name",
|
||||
"ID": "b87d7442095999a92b65b3d9691e697b61713829cc0ffd1bb72e4ccd51aa4d6c"
|
||||
}
|
||||
```
|
||||
|
||||
Docker requires the plugin to provide a volume, given a user specified volume
|
||||
name. `Mount` is called once per container start. If the same `volume_name` is requested
|
||||
more than once, the plugin may need to keep track of each new mount request and provision
|
||||
at the first mount request and deprovision at the last corresponding unmount request.
|
||||
|
||||
`ID` is a unique ID for the caller that is requesting the mount.
|
||||
|
||||
**Response**:
|
||||
|
||||
- **v1**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Mountpoint": "/path/to/directory/on/host",
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
- **v2**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Mountpoint": "/path/under/PropagatedMount",
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
`Mountpoint` is the path on the host (v1) or in the plugin (v2) where the volume
|
||||
has been made available.
|
||||
|
||||
`Err` is either empty or contains an error string.
|
||||
|
||||
### `/VolumeDriver.Path`
|
||||
|
||||
**Request**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name"
|
||||
}
|
||||
```
|
||||
|
||||
Request the path to the volume with the given `volume_name`.
|
||||
|
||||
**Response**:
|
||||
|
||||
- **v1**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Mountpoin": "/path/to/directory/on/host",
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
- **v2**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Mountpoint": "/path/under/PropagatedMount",
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with the path on the host (v1) or inside the plugin (v2) where the
|
||||
volume has been made available, and/or a string error if an error occurred.
|
||||
|
||||
`Mountpoint` is optional. However, the plugin may be queried again later if one
|
||||
is not provided.
|
||||
|
||||
### `/VolumeDriver.Unmount`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name",
|
||||
"ID": "b87d7442095999a92b65b3d9691e697b61713829cc0ffd1bb72e4ccd51aa4d6c"
|
||||
}
|
||||
```
|
||||
|
||||
Docker is no longer using the named volume. `Unmount` is called once per
|
||||
container stop. Plugin may deduce that it is safe to deprovision the volume at
|
||||
this point.
|
||||
|
||||
`ID` is a unique ID for the caller that is requesting the mount.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a string error if an error occurred.
|
||||
|
||||
|
||||
### `/VolumeDriver.Get`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Name": "volume_name"
|
||||
}
|
||||
```
|
||||
|
||||
Get info about `volume_name`.
|
||||
|
||||
|
||||
**Response**:
|
||||
|
||||
- **v1**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Volume": {
|
||||
"Name": "volume_name",
|
||||
"Mountpoint": "/path/to/directory/on/host",
|
||||
"Status": {}
|
||||
},
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
- **v2**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Volume": {
|
||||
"Name": "volume_name",
|
||||
"Mountpoint": "/path/under/PropagatedMount",
|
||||
"Status": {}
|
||||
},
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a string error if an error occurred. `Mountpoint` and `Status` are
|
||||
optional.
|
||||
|
||||
|
||||
### /VolumeDriver.List
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Get the list of volumes registered with the plugin.
|
||||
|
||||
**Response**:
|
||||
|
||||
- **v1**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Volumes": [
|
||||
{
|
||||
"Name": "volume_name",
|
||||
"Mountpoint": "/path/to/directory/on/host"
|
||||
}
|
||||
],
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
- **v2**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Volumes": [
|
||||
{
|
||||
"Name": "volume_name",
|
||||
"Mountpoint": "/path/under/PropagatedMount"
|
||||
}
|
||||
],
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Respond with a string error if an error occurred. `Mountpoint` is optional.
|
||||
|
||||
### /VolumeDriver.Capabilities
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Get the list of capabilities the driver supports.
|
||||
|
||||
The driver is not required to implement `Capabilities`. If it is not
|
||||
implemented, the default values are used.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Capabilities": {
|
||||
"Scope": "global"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported scopes are `global` and `local`. Any other value in `Scope` will be
|
||||
ignored, and `local` is used. `Scope` allows cluster managers to handle the
|
||||
volume in different ways. For instance, a scope of `global`, signals to the
|
||||
cluster manager that it only needs to create the volume once instead of on each
|
||||
Docker host. More capabilities may be added in the future.
|
||||
@@ -0,0 +1,164 @@
|
||||
---
|
||||
description: Volume plugin for Amazon EBS
|
||||
keywords: "API, Usage, plugins, documentation, developer, amazon, ebs, rexray, volume"
|
||||
title: Volume plugin for Amazon EBS
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# A proof-of-concept Rexray plugin
|
||||
|
||||
In this example, a simple Rexray plugin will be created for the purposes of using
|
||||
it on an Amazon EC2 instance with EBS. It is not meant to be a complete Rexray plugin.
|
||||
|
||||
The example source is available at [https://github.com/tiborvass/rexray-plugin](https://github.com/tiborvass/rexray-plugin).
|
||||
|
||||
To learn more about Rexray: [https://github.com/codedellemc/rexray](https://github.com/codedellemc/rexray)
|
||||
|
||||
## 1. Make a Docker image
|
||||
|
||||
The following is the Dockerfile used to containerize rexray.
|
||||
|
||||
```Dockerfile
|
||||
FROM debian:jessie
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates
|
||||
RUN wget https://dl.bintray.com/emccode/rexray/stable/0.6.4/rexray-Linux-x86_64-0.6.4.tar.gz -O rexray.tar.gz && tar -xvzf rexray.tar.gz -C /usr/bin && rm rexray.tar.gz
|
||||
RUN mkdir -p /run/docker/plugins /var/lib/libstorage/volumes
|
||||
ENTRYPOINT ["rexray"]
|
||||
CMD ["--help"]
|
||||
```
|
||||
|
||||
To build it you can run `image=$(cat Dockerfile | docker build -q -)` and `$image`
|
||||
will reference the containerized rexray image.
|
||||
|
||||
## 2. Extract rootfs
|
||||
|
||||
```sh
|
||||
$ TMPDIR=/tmp/rexray # for the purpose of this example
|
||||
$ # create container without running it, to extract the rootfs from image
|
||||
$ docker create --name rexray "$image"
|
||||
$ # save the rootfs to a tar archive
|
||||
$ docker export -o $TMPDIR/rexray.tar rexray
|
||||
$ # extract rootfs from tar archive to a rootfs folder
|
||||
$ ( mkdir -p $TMPDIR/rootfs; cd $TMPDIR/rootfs; tar xf ../rexray.tar )
|
||||
```
|
||||
|
||||
## 3. Add plugin configuration
|
||||
|
||||
We have to put the following JSON to `$TMPDIR/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Args": {
|
||||
"Description": "",
|
||||
"Name": "",
|
||||
"Settable": null,
|
||||
"Value": null
|
||||
},
|
||||
"Description": "A proof-of-concept EBS plugin (using rexray) for Docker",
|
||||
"Documentation": "https://github.com/tiborvass/rexray-plugin",
|
||||
"Entrypoint": [
|
||||
"/usr/bin/rexray", "service", "start", "-f"
|
||||
],
|
||||
"Env": [
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "REXRAY_SERVICE",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": "ebs"
|
||||
},
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "EBS_ACCESSKEY",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": ""
|
||||
},
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "EBS_SECRETKEY",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": ""
|
||||
}
|
||||
],
|
||||
"Interface": {
|
||||
"Socket": "rexray.sock",
|
||||
"Types": [
|
||||
"docker.volumedriver/1.0"
|
||||
]
|
||||
},
|
||||
"Linux": {
|
||||
"AllowAllDevices": true,
|
||||
"Capabilities": ["CAP_SYS_ADMIN"],
|
||||
"Devices": null
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Source": "/dev",
|
||||
"Destination": "/dev",
|
||||
"Type": "bind",
|
||||
"Options": ["rbind"]
|
||||
}
|
||||
],
|
||||
"Network": {
|
||||
"Type": "host"
|
||||
},
|
||||
"PropagatedMount": "/var/lib/libstorage/volumes",
|
||||
"User": {},
|
||||
"WorkDir": ""
|
||||
}
|
||||
```
|
||||
|
||||
Please note a couple of points:
|
||||
- `PropagatedMount` is needed so that the docker daemon can see mounts done by the
|
||||
rexray plugin from within the container, otherwise the docker daemon is not able
|
||||
to mount a docker volume.
|
||||
- The rexray plugin needs dynamic access to host devices. For that reason, we
|
||||
have to give it access to all devices under `/dev` and set `AllowAllDevices` to
|
||||
true for proper access.
|
||||
- The user of this simple plugin can change only 3 settings: `REXRAY_SERVICE`,
|
||||
`EBS_ACCESSKEY` and `EBS_SECRETKEY`. This is because of the reduced scope of this
|
||||
plugin. Ideally other rexray parameters could also be set.
|
||||
|
||||
## 4. Create plugin
|
||||
|
||||
`docker plugin create tiborvass/rexray-plugin "$TMPDIR"` will create the plugin.
|
||||
|
||||
```sh
|
||||
$ docker plugin ls
|
||||
ID NAME DESCRIPTION ENABLED
|
||||
2475a4bd0ca5 tiborvass/rexray-plugin:latest A rexray volume plugin for Docker false
|
||||
```
|
||||
|
||||
## 5. Test plugin
|
||||
|
||||
```sh
|
||||
$ docker plugin set tiborvass/rexray-plugin EBS_ACCESSKEY=$AWS_ACCESSKEY EBS_SECRETKEY=$AWS_SECRETKEY`
|
||||
$ docker plugin enable tiborvass/rexray-plugin
|
||||
$ docker volume create -d tiborvass/rexray-plugin my-ebs-volume
|
||||
$ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
tiborvass/rexray-plugin:latest my-ebs-volume
|
||||
$ docker run --rm -v my-ebs-volume:/volume busybox sh -c 'echo bye > /volume/hi'
|
||||
$ docker run --rm -v my-ebs-volume:/volume busybox cat /volume/hi
|
||||
bye
|
||||
```
|
||||
|
||||
## 6. Push plugin
|
||||
|
||||
First, ensure you are logged in with `docker login`. Then you can run:
|
||||
`docker plugin push tiborvass/rexray-plugin` to push it like a regular docker
|
||||
image to a registry, to make it available for others to install via
|
||||
`docker plugin install tiborvass/rexray-plugin EBS_ACCESSKEY=$AWS_ACCESSKEY EBS_SECRETKEY=$AWS_SECRETKEY`.
|
||||
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: "Plugins API"
|
||||
description: "How to write Docker plugins extensions "
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Docker Plugin API
|
||||
|
||||
Docker plugins are out-of-process extensions which add capabilities to the
|
||||
Docker Engine.
|
||||
|
||||
This document describes the Docker Engine plugin API. To view information on
|
||||
plugins managed by Docker Engine, refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
This page is intended for people who want to develop their own Docker plugin.
|
||||
If you just want to learn about or use Docker plugins, look
|
||||
[here](legacy_plugins.md).
|
||||
|
||||
## What plugins are
|
||||
|
||||
A plugin is a process running on the same or a different host as the docker daemon,
|
||||
which registers itself by placing a file on the same docker host in one of the plugin
|
||||
directories described in [Plugin discovery](#plugin-discovery).
|
||||
|
||||
Plugins have human-readable names, which are short, lowercase strings. For
|
||||
example, `flocker` or `weave`.
|
||||
|
||||
Plugins can run inside or outside containers. Currently running them outside
|
||||
containers is recommended.
|
||||
|
||||
## Plugin discovery
|
||||
|
||||
Docker discovers plugins by looking for them in the plugin directory whenever a
|
||||
user or container tries to use one by name.
|
||||
|
||||
There are three types of files which can be put in the plugin directory.
|
||||
|
||||
* `.sock` files are UNIX domain sockets.
|
||||
* `.spec` files are text files containing a URL, such as `unix:///other.sock` or `tcp://localhost:8080`.
|
||||
* `.json` files are text files containing a full json specification for the plugin.
|
||||
|
||||
Plugins with UNIX domain socket files must run on the same docker host, whereas
|
||||
plugins with spec or json files can run on a different host if a remote URL is specified.
|
||||
|
||||
UNIX domain socket files must be located under `/run/docker/plugins`, whereas
|
||||
spec files can be located either under `/etc/docker/plugins` or `/usr/lib/docker/plugins`.
|
||||
|
||||
The name of the file (excluding the extension) determines the plugin name.
|
||||
|
||||
For example, the `flocker` plugin might create a UNIX socket at
|
||||
`/run/docker/plugins/flocker.sock`.
|
||||
|
||||
You can define each plugin into a separated subdirectory if you want to isolate definitions from each other.
|
||||
For example, you can create the `flocker` socket under `/run/docker/plugins/flocker/flocker.sock` and only
|
||||
mount `/run/docker/plugins/flocker` inside the `flocker` container.
|
||||
|
||||
Docker always searches for unix sockets in `/run/docker/plugins` first. It checks for spec or json files under
|
||||
`/etc/docker/plugins` and `/usr/lib/docker/plugins` if the socket doesn't exist. The directory scan stops as
|
||||
soon as it finds the first plugin definition with the given name.
|
||||
|
||||
### JSON specification
|
||||
|
||||
This is the JSON format for a plugin:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "plugin-example",
|
||||
"Addr": "https://example.com/docker/plugin",
|
||||
"TLSConfig": {
|
||||
"InsecureSkipVerify": false,
|
||||
"CAFile": "/usr/shared/docker/certs/example-ca.pem",
|
||||
"CertFile": "/usr/shared/docker/certs/example-cert.pem",
|
||||
"KeyFile": "/usr/shared/docker/certs/example-key.pem"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `TLSConfig` field is optional and TLS will only be verified if this configuration is present.
|
||||
|
||||
## Plugin lifecycle
|
||||
|
||||
Plugins should be started before Docker, and stopped after Docker. For
|
||||
example, when packaging a plugin for a platform which supports `systemd`, you
|
||||
might use [`systemd` dependencies](
|
||||
http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Before=) to
|
||||
manage startup and shutdown order.
|
||||
|
||||
When upgrading a plugin, you should first stop the Docker daemon, upgrade the
|
||||
plugin, then start Docker again.
|
||||
|
||||
## Plugin activation
|
||||
|
||||
When a plugin is first referred to -- either by a user referring to it by name
|
||||
(e.g. `docker run --volume-driver=foo`) or a container already configured to
|
||||
use a plugin being started -- Docker looks for the named plugin in the plugin
|
||||
directory and activates it with a handshake. See Handshake API below.
|
||||
|
||||
Plugins are *not* activated automatically at Docker daemon startup. Rather,
|
||||
they are activated only lazily, or on-demand, when they are needed.
|
||||
|
||||
## Systemd socket activation
|
||||
|
||||
Plugins may also be socket activated by `systemd`. The official [Plugins helpers](https://github.com/docker/go-plugins-helpers)
|
||||
natively supports socket activation. In order for a plugin to be socket activated it needs
|
||||
a `service` file and a `socket` file.
|
||||
|
||||
The `service` file (for example `/lib/systemd/system/your-plugin.service`):
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Your plugin
|
||||
Before=docker.service
|
||||
After=network.target your-plugin.socket
|
||||
Requires=your-plugin.socket docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/lib/docker/your-plugin
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
The `socket` file (for example `/lib/systemd/system/your-plugin.socket`):
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Your plugin
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/docker/plugins/your-plugin.sock
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
```
|
||||
|
||||
This will allow plugins to be actually started when the Docker daemon connects to
|
||||
the sockets they're listening on (for instance the first time the daemon uses them
|
||||
or if one of the plugin goes down accidentally).
|
||||
|
||||
## API design
|
||||
|
||||
The Plugin API is RPC-style JSON over HTTP, much like webhooks.
|
||||
|
||||
Requests flow *from* the Docker daemon *to* the plugin. So the plugin needs to
|
||||
implement an HTTP server and bind this to the UNIX socket mentioned in the
|
||||
"plugin discovery" section.
|
||||
|
||||
All requests are HTTP `POST` requests.
|
||||
|
||||
The API is versioned via an Accept header, which currently is always set to
|
||||
`application/vnd.docker.plugins.v1+json`.
|
||||
|
||||
## Handshake API
|
||||
|
||||
Plugins are activated via the following "handshake" API call.
|
||||
|
||||
### /Plugin.Activate
|
||||
|
||||
**Request:** empty body
|
||||
|
||||
**Response:**
|
||||
```
|
||||
{
|
||||
"Implements": ["VolumeDriver"]
|
||||
}
|
||||
```
|
||||
|
||||
Responds with a list of Docker subsystems which this plugin implements.
|
||||
After activation, the plugin will then be sent events from this subsystem.
|
||||
|
||||
Possible values are:
|
||||
|
||||
* [`authz`](plugins_authorization.md)
|
||||
* [`NetworkDriver`](plugins_network.md)
|
||||
* [`VolumeDriver`](plugins_volume.md)
|
||||
|
||||
|
||||
## Plugin retries
|
||||
|
||||
Attempts to call a method on a plugin are retried with an exponential backoff
|
||||
for up to 30 seconds. This may help when packaging plugins as containers, since
|
||||
it gives plugin containers a chance to start up before failing any user
|
||||
containers which depend on them.
|
||||
|
||||
## Plugins helpers
|
||||
|
||||
To ease plugins development, we're providing an `sdk` for each kind of plugins
|
||||
currently supported by Docker at [docker/go-plugins-helpers](https://github.com/docker/go-plugins-helpers).
|
||||
@@ -0,0 +1,380 @@
|
||||
---
|
||||
title: "Graphdriver plugins"
|
||||
description: "How to manage image and container filesystems with external plugins"
|
||||
keywords: "Examples, Usage, storage, image, docker, data, graph, plugin, api"
|
||||
advisory: experimental
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
### 1.13.0
|
||||
|
||||
- Support v2 plugins
|
||||
|
||||
# Docker graph driver plugins
|
||||
|
||||
Docker graph driver plugins enable admins to use an external/out-of-process
|
||||
graph driver for use with Docker engine. This is an alternative to using the
|
||||
built-in storage drivers, such as aufs/overlay/devicemapper/btrfs.
|
||||
|
||||
You need to install and enable the plugin and then restart the Docker daemon
|
||||
before using the plugin. See the following example for the correct ordering
|
||||
of steps.
|
||||
|
||||
```
|
||||
$ docker plugin install cpuguy83/docker-overlay2-graphdriver-plugin # this command also enables the driver
|
||||
<output supressed>
|
||||
$ pkill dockerd
|
||||
$ dockerd --experimental -s cpuguy83/docker-overlay2-graphdriver-plugin
|
||||
```
|
||||
|
||||
# Write a graph driver plugin
|
||||
|
||||
See the [plugin documentation](/docs/extend/index.md) for detailed information
|
||||
on the underlying plugin protocol.
|
||||
|
||||
|
||||
## Graph Driver plugin protocol
|
||||
|
||||
If a plugin registers itself as a `GraphDriver` when activated, then it is
|
||||
expected to provide the rootfs for containers as well as image layer storage.
|
||||
|
||||
### /GraphDriver.Init
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"Home": "/graph/home/path",
|
||||
"Opts": [],
|
||||
"UIDMaps": [],
|
||||
"GIDMaps": []
|
||||
}
|
||||
```
|
||||
|
||||
Initialize the graph driver plugin with a home directory and array of options.
|
||||
These are passed through from the user, but the plugin is not required to parse
|
||||
or honor them.
|
||||
|
||||
The request also includes a list of UID and GID mappings, structed as follows:
|
||||
```json
|
||||
{
|
||||
"ContainerID": 0,
|
||||
"HostID": 0,
|
||||
"Size": 0
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
|
||||
### /GraphDriver.Create
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142",
|
||||
"MountLabel": "",
|
||||
"StorageOpt": {}
|
||||
}
|
||||
```
|
||||
|
||||
Create a new, empty, read-only filesystem layer with the specified
|
||||
`ID`, `Parent` and `MountLabel`. If `Parent` is an empty string, there is no
|
||||
parent layer. `StorageOpt` is map of strings which indicate storage options.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.CreateReadWrite
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142",
|
||||
"MountLabel": "",
|
||||
"StorageOpt": {}
|
||||
}
|
||||
```
|
||||
|
||||
Similar to `/GraphDriver.Create` but creates a read-write filesystem layer.
|
||||
|
||||
### /GraphDriver.Remove
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
```
|
||||
|
||||
Remove the filesystem layer with this given `ID`.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.Get
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"MountLabel": ""
|
||||
}
|
||||
```
|
||||
|
||||
Get the mountpoint for the layered filesystem referred to by the given `ID`.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Dir": "/var/mygraph/46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with the absolute path to the mounted layered filesystem.
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.Put
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
```
|
||||
|
||||
Release the system resources for the specified `ID`, such as unmounting the
|
||||
filesystem layer.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.Exists
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
```
|
||||
|
||||
Determine if a filesystem layer with the specified `ID` exists.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Exists": true
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a boolean for whether or not the filesystem layer with the specified
|
||||
`ID` exists.
|
||||
|
||||
### /GraphDriver.Status
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Get low-level diagnostic information about the graph driver.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Status": [[]]
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a 2-D array with key/value pairs for the underlying status
|
||||
information.
|
||||
|
||||
|
||||
### /GraphDriver.GetMetadata
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
```
|
||||
|
||||
Get low-level diagnostic information about the layered filesystem with the
|
||||
with the specified `ID`
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Metadata": {},
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a set of key/value pairs containing the low-level diagnostic
|
||||
information about the layered filesystem.
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.Cleanup
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Perform necessary tasks to release resources help by the plugin, such as
|
||||
unmounting all the layered file systems.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
|
||||
### /GraphDriver.Diff
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
}
|
||||
```
|
||||
|
||||
Get an archive of the changes between the filesystem layers specified by the `ID`
|
||||
and `Parent`. `Parent` may be an empty string, in which case there is no parent.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
{% raw %}
|
||||
{{ TAR STREAM }}
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
### /GraphDriver.Changes
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
}
|
||||
```
|
||||
|
||||
Get a list of changes between the filesystem layers specified by the `ID` and
|
||||
`Parent`. If `Parent` is an empty string, there is no parent.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Changes": [{}],
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with a list of changes. The structure of a change is:
|
||||
```json
|
||||
"Path": "/some/path",
|
||||
"Kind": 0,
|
||||
```
|
||||
|
||||
Where the `Path` is the filesystem path within the layered filesystem that is
|
||||
changed and `Kind` is an integer specifying the type of change that occurred:
|
||||
|
||||
- 0 - Modified
|
||||
- 1 - Added
|
||||
- 2 - Deleted
|
||||
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.ApplyDiff
|
||||
|
||||
**Request**:
|
||||
```
|
||||
{% raw %}
|
||||
{{ TAR STREAM }}
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
Extract the changeset from the given diff into the layer with the specified `ID`
|
||||
and `Parent`
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- id (required)- the `ID` of the new filesystem layer to extract the diff to
|
||||
- parent (required)- the `Parent` of the given `ID`
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Size": 512366,
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with the size of the new layer in bytes.
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
|
||||
### /GraphDriver.DiffSize
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
}
|
||||
```
|
||||
|
||||
Calculate the changes between the specified `ID`
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"Size": 512366,
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Respond with the size changes between the specified `ID` and `Parent`
|
||||
Respond with a non-empty string error if an error occurred.
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: "Access authorization plugin"
|
||||
description: "How to create authorization plugins to manage access control to your Docker daemon."
|
||||
keywords: "security, authorization, authentication, docker, documentation, plugin, extend"
|
||||
redirect_from:
|
||||
- "/engine/extend/authorization/"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Create an authorization plugin
|
||||
|
||||
This document describes the Docker Engine plugins generally available in Docker
|
||||
Engine. To view information on plugins managed by Docker Engine,
|
||||
refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
Docker's out-of-the-box authorization model is all or nothing. Any user with
|
||||
permission to access the Docker daemon can run any Docker client command. The
|
||||
same is true for callers using Docker's Engine API to contact the daemon. If you
|
||||
require greater access control, you can create authorization plugins and add
|
||||
them to your Docker daemon configuration. Using an authorization plugin, a
|
||||
Docker administrator can configure granular access policies for managing access
|
||||
to Docker daemon.
|
||||
|
||||
Anyone with the appropriate skills can develop an authorization plugin. These
|
||||
skills, at their most basic, are knowledge of Docker, understanding of REST, and
|
||||
sound programming knowledge. This document describes the architecture, state,
|
||||
and methods information available to an authorization plugin developer.
|
||||
|
||||
## Basic principles
|
||||
|
||||
Docker's [plugin infrastructure](plugin_api.md) enables
|
||||
extending Docker by loading, removing and communicating with
|
||||
third-party components using a generic API. The access authorization subsystem
|
||||
was built using this mechanism.
|
||||
|
||||
Using this subsystem, you don't need to rebuild the Docker daemon to add an
|
||||
authorization plugin. You can add a plugin to an installed Docker daemon. You do
|
||||
need to restart the Docker daemon to add a new plugin.
|
||||
|
||||
An authorization plugin approves or denies requests to the Docker daemon based
|
||||
on both the current authentication context and the command context. The
|
||||
authentication context contains all user details and the authentication method.
|
||||
The command context contains all the relevant request data.
|
||||
|
||||
Authorization plugins must follow the rules described in [Docker Plugin API](plugin_api.md).
|
||||
Each plugin must reside within directories described under the
|
||||
[Plugin discovery](plugin_api.md#plugin-discovery) section.
|
||||
|
||||
**Note**: the abbreviations `AuthZ` and `AuthN` mean authorization and authentication
|
||||
respectively.
|
||||
|
||||
## Default user authorization mechanism
|
||||
|
||||
If TLS is enabled in the [Docker daemon](https://docs.docker.com/engine/security/https/), the default user authorization flow extracts the user details from the certificate subject name.
|
||||
That is, the `User` field is set to the client certificate subject common name, and the `AuthenticationMethod` field is set to `TLS`.
|
||||
|
||||
## Basic architecture
|
||||
|
||||
You are responsible for registering your plugin as part of the Docker daemon
|
||||
startup. You can install multiple plugins and chain them together. This chain
|
||||
can be ordered. Each request to the daemon passes in order through the chain.
|
||||
Only when all the plugins grant access to the resource, is the access granted.
|
||||
|
||||
When an HTTP request is made to the Docker daemon through the CLI or via the
|
||||
Engine API, the authentication subsystem passes the request to the installed
|
||||
authentication plugin(s). The request contains the user (caller) and command
|
||||
context. The plugin is responsible for deciding whether to allow or deny the
|
||||
request.
|
||||
|
||||
The sequence diagrams below depict an allow and deny authorization flow:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Each request sent to the plugin includes the authenticated user, the HTTP
|
||||
headers, and the request/response body. Only the user name and the
|
||||
authentication method used are passed to the plugin. Most importantly, no user
|
||||
credentials or tokens are passed. Finally, not all request/response bodies
|
||||
are sent to the authorization plugin. Only those request/response bodies where
|
||||
the `Content-Type` is either `text/*` or `application/json` are sent.
|
||||
|
||||
For commands that can potentially hijack the HTTP connection (`HTTP
|
||||
Upgrade`), such as `exec`, the authorization plugin is only called for the
|
||||
initial HTTP requests. Once the plugin approves the command, authorization is
|
||||
not applied to the rest of the flow. Specifically, the streaming data is not
|
||||
passed to the authorization plugins. For commands that return chunked HTTP
|
||||
response, such as `logs` and `events`, only the HTTP request is sent to the
|
||||
authorization plugins.
|
||||
|
||||
During request/response processing, some authorization flows might
|
||||
need to do additional queries to the Docker daemon. To complete such flows,
|
||||
plugins can call the daemon API similar to a regular user. To enable these
|
||||
additional queries, the plugin must provide the means for an administrator to
|
||||
configure proper authentication and security policies.
|
||||
|
||||
## Docker client flows
|
||||
|
||||
To enable and configure the authorization plugin, the plugin developer must
|
||||
support the Docker client interactions detailed in this section.
|
||||
|
||||
### Setting up Docker daemon
|
||||
|
||||
Enable the authorization plugin with a dedicated command line flag in the
|
||||
`--authorization-plugin=PLUGIN_ID` format. The flag supplies a `PLUGIN_ID`
|
||||
value. This value can be the plugin’s socket or a path to a specification file.
|
||||
Authorization plugins can be loaded without restarting the daemon. Refer
|
||||
to the [`dockerd` documentation](../reference/commandline/dockerd.md#configuration-reloading) for more information.
|
||||
|
||||
```bash
|
||||
$ dockerd --authorization-plugin=plugin1 --authorization-plugin=plugin2,...
|
||||
```
|
||||
|
||||
Docker's authorization subsystem supports multiple `--authorization-plugin` parameters.
|
||||
|
||||
### Calling authorized command (allow)
|
||||
|
||||
```bash
|
||||
$ docker pull centos
|
||||
...
|
||||
f1b10cd84249: Pull complete
|
||||
...
|
||||
```
|
||||
|
||||
### Calling unauthorized command (deny)
|
||||
|
||||
```bash
|
||||
$ docker pull centos
|
||||
...
|
||||
docker: Error response from daemon: authorization denied by plugin PLUGIN_NAME: volumes are not allowed.
|
||||
```
|
||||
|
||||
### Error from plugins
|
||||
|
||||
```bash
|
||||
$ docker pull centos
|
||||
...
|
||||
docker: Error response from daemon: plugin PLUGIN_NAME failed with error: AuthZPlugin.AuthZReq: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
|
||||
```
|
||||
|
||||
## API schema and implementation
|
||||
|
||||
In addition to Docker's standard plugin registration method, each plugin
|
||||
should implement the following two methods:
|
||||
|
||||
* `/AuthZPlugin.AuthZReq` This authorize request method is called before the Docker daemon processes the client request.
|
||||
|
||||
* `/AuthZPlugin.AuthZRes` This authorize response method is called before the response is returned from Docker daemon to the client.
|
||||
|
||||
#### /AuthZPlugin.AuthZReq
|
||||
|
||||
**Request**:
|
||||
|
||||
```json
|
||||
{
|
||||
"User": "The user identification",
|
||||
"UserAuthNMethod": "The authentication method used",
|
||||
"RequestMethod": "The HTTP method",
|
||||
"RequestURI": "The HTTP request URI",
|
||||
"RequestBody": "Byte array containing the raw HTTP request body",
|
||||
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string "
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Allow": "Determined whether the user is allowed or not",
|
||||
"Msg": "The authorization message",
|
||||
"Err": "The error message if things go wrong"
|
||||
}
|
||||
```
|
||||
#### /AuthZPlugin.AuthZRes
|
||||
|
||||
**Request**:
|
||||
|
||||
```json
|
||||
{
|
||||
"User": "The user identification",
|
||||
"UserAuthNMethod": "The authentication method used",
|
||||
"RequestMethod": "The HTTP method",
|
||||
"RequestURI": "The HTTP request URI",
|
||||
"RequestBody": "Byte array containing the raw HTTP request body",
|
||||
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string",
|
||||
"ResponseBody": "Byte array containing the raw HTTP response body",
|
||||
"ResponseHeader": "Byte array containing the raw HTTP response header as a map[string][]string",
|
||||
"ResponseStatusCode":"Response status code"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"Allow": "Determined whether the user is allowed or not",
|
||||
"Msg": "The authorization message",
|
||||
"Err": "The error message if things go wrong"
|
||||
}
|
||||
```
|
||||
|
||||
### Request authorization
|
||||
|
||||
Each plugin must support two request authorization messages formats, one from the daemon to the plugin and then from the plugin to the daemon. The tables below detail the content expected in each message.
|
||||
|
||||
#### Daemon -> Plugin
|
||||
|
||||
Name | Type | Description
|
||||
-----------------------|-------------------|-------------------------------------------------------
|
||||
User | string | The user identification
|
||||
Authentication method | string | The authentication method used
|
||||
Request method | enum | The HTTP method (GET/DELETE/POST)
|
||||
Request URI | string | The HTTP request URI including API version (e.g., v.1.17/containers/json)
|
||||
Request headers | map[string]string | Request headers as key value pairs (without the authorization header)
|
||||
Request body | []byte | Raw request body
|
||||
|
||||
|
||||
#### Plugin -> Daemon
|
||||
|
||||
Name | Type | Description
|
||||
--------|--------|----------------------------------------------------------------------------------
|
||||
Allow | bool | Boolean value indicating whether the request is allowed or denied
|
||||
Msg | string | Authorization message (will be returned to the client in case the access is denied)
|
||||
Err | string | Error message (will be returned to the client in case the plugin encounter an error. The string value supplied may appear in logs, so should not include confidential information)
|
||||
|
||||
### Response authorization
|
||||
|
||||
The plugin must support two authorization messages formats, one from the daemon to the plugin and then from the plugin to the daemon. The tables below detail the content expected in each message.
|
||||
|
||||
#### Daemon -> Plugin
|
||||
|
||||
|
||||
Name | Type | Description
|
||||
----------------------- |------------------ |----------------------------------------------------
|
||||
User | string | The user identification
|
||||
Authentication method | string | The authentication method used
|
||||
Request method | string | The HTTP method (GET/DELETE/POST)
|
||||
Request URI | string | The HTTP request URI including API version (e.g., v.1.17/containers/json)
|
||||
Request headers | map[string]string | Request headers as key value pairs (without the authorization header)
|
||||
Request body | []byte | Raw request body
|
||||
Response status code | int | Status code from the docker daemon
|
||||
Response headers | map[string]string | Response headers as key value pairs
|
||||
Response body | []byte | Raw docker daemon response body
|
||||
|
||||
|
||||
#### Plugin -> Daemon
|
||||
|
||||
Name | Type | Description
|
||||
--------|--------|----------------------------------------------------------------------------------
|
||||
Allow | bool | Boolean value indicating whether the response is allowed or denied
|
||||
Msg | string | Authorization message (will be returned to the client in case the access is denied)
|
||||
Err | string | Error message (will be returned to the client in case the plugin encounter an error. The string value supplied may appear in logs, so should not include confidential information)
|
||||
@@ -0,0 +1,319 @@
|
||||
---
|
||||
description: Develop and use a plugin with the managed plugin system
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
title: Managed plugin system
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Docker Engine managed plugin system
|
||||
|
||||
* [Installing and using a plugin](index.md#installing-and-using-a-plugin)
|
||||
* [Developing a plugin](index.md#developing-a-plugin)
|
||||
* [Debugging plugins](index.md#debugging-plugins)
|
||||
|
||||
Docker Engine's plugin system allows you to install, start, stop, and remove
|
||||
plugins using Docker Engine.
|
||||
|
||||
For information about the legacy plugin system available in Docker Engine 1.12
|
||||
and earlier, see [Understand legacy Docker Engine plugins](legacy_plugins.md).
|
||||
|
||||
> **Note**: Docker Engine managed plugins are currently not supported
|
||||
on Windows daemons.
|
||||
|
||||
## Installing and using a plugin
|
||||
|
||||
Plugins are distributed as Docker images and can be hosted on Docker Hub or on
|
||||
a private registry.
|
||||
|
||||
To install a plugin, use the `docker plugin install` command, which pulls the
|
||||
plugin from Docker Hub or your private registry, prompts you to grant
|
||||
permissions or capabilities if necessary, and enables the plugin.
|
||||
|
||||
To check the status of installed plugins, use the `docker plugin ls` command.
|
||||
Plugins that start successfully are listed as enabled in the output.
|
||||
|
||||
After a plugin is installed, you can use it as an option for another Docker
|
||||
operation, such as creating a volume.
|
||||
|
||||
In the following example, you install the `sshfs` plugin, verify that it is
|
||||
enabled, and use it to create a volume.
|
||||
|
||||
> **Note**: This example is intended for instructional purposes only. Once the volume is created, your SSH password to the remote host will be exposed as plaintext when inspecting the volume. You should delete the volume as soon as you are done with the example.
|
||||
|
||||
1. Install the `sshfs` plugin.
|
||||
|
||||
```bash
|
||||
$ docker plugin install vieux/sshfs
|
||||
|
||||
Plugin "vieux/sshfs" is requesting the following privileges:
|
||||
- network: [host]
|
||||
- capabilities: [CAP_SYS_ADMIN]
|
||||
Do you grant the above permissions? [y/N] y
|
||||
|
||||
vieux/sshfs
|
||||
```
|
||||
|
||||
The plugin requests 2 privileges:
|
||||
|
||||
- It needs access to the `host` network.
|
||||
- It needs the `CAP_SYS_ADMIN` capability, which allows the plugin to run
|
||||
the `mount` command.
|
||||
|
||||
2. Check that the plugin is enabled in the output of `docker plugin ls`.
|
||||
|
||||
```bash
|
||||
$ docker plugin ls
|
||||
|
||||
ID NAME TAG DESCRIPTION ENABLED
|
||||
69553ca1d789 vieux/sshfs latest the `sshfs` plugin true
|
||||
```
|
||||
|
||||
3. Create a volume using the plugin.
|
||||
This example mounts the `/remote` directory on host `1.2.3.4` into a
|
||||
volume named `sshvolume`.
|
||||
|
||||
This volume can now be mounted into containers.
|
||||
|
||||
```bash
|
||||
$ docker volume create \
|
||||
-d vieux/sshfs \
|
||||
--name sshvolume \
|
||||
-o sshcmd=user@1.2.3.4:/remote \
|
||||
-o password=$(cat file_containing_password_for_remote_host)
|
||||
|
||||
sshvolume
|
||||
```
|
||||
4. Verify that the volume was created successfully.
|
||||
|
||||
```bash
|
||||
$ docker volume ls
|
||||
|
||||
DRIVER NAME
|
||||
vieux/sshfs sshvolume
|
||||
```
|
||||
|
||||
5. Start a container that uses the volume `sshvolume`.
|
||||
|
||||
```bash
|
||||
$ docker run --rm -v sshvolume:/data busybox ls /data
|
||||
|
||||
<content of /remote on machine 1.2.3.4>
|
||||
```
|
||||
|
||||
6. Remove the volume `sshvolume`
|
||||
```bash
|
||||
docker volume rm sshvolume
|
||||
|
||||
sshvolume
|
||||
```
|
||||
To disable a plugin, use the `docker plugin disable` command. To completely
|
||||
remove it, use the `docker plugin remove` command. For other available
|
||||
commands and options, see the
|
||||
[command line reference](../reference/commandline/index.md).
|
||||
|
||||
## Service creation using plugins
|
||||
|
||||
In swarm mode, it is possible to create a service that allows for attaching
|
||||
to networks or mounting volumes. Swarm schedules services based on plugin availability
|
||||
on a node. In this example, a volume plugin is installed on a swarm worker and a volume
|
||||
is created using the plugin. In the manager, a service is created with the relevant
|
||||
mount options. It can be observed that the service is scheduled to run on the worker
|
||||
node with the said volume plugin and volume.
|
||||
|
||||
In the following example, node1 is the manager and node2 is the worker.
|
||||
|
||||
1. Prepare manager. In node 1:
|
||||
|
||||
```bash
|
||||
$ docker swarm init
|
||||
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
|
||||
```
|
||||
|
||||
2. Join swarm, install plugin and create volume on worker. In node 2:
|
||||
|
||||
```bash
|
||||
$ docker swarm join \
|
||||
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
|
||||
192.168.99.100:2377
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker plugin install tiborvass/sample-volume-plugin
|
||||
latest: Pulling from tiborvass/sample-volume-plugin
|
||||
eb9c16fbdc53: Download complete
|
||||
Digest: sha256:00b42de88f3a3e0342e7b35fa62394b0a9ceb54d37f4c50be5d3167899994639
|
||||
Status: Downloaded newer image for tiborvass/sample-volume-plugin:latest
|
||||
Installed plugin tiborvass/sample-volume-plugin
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker volume create -d tiborvass/sample-volume-plugin --name pluginVol
|
||||
```
|
||||
|
||||
3. Create a service using the plugin and volume. In node1:
|
||||
|
||||
```bash
|
||||
$ docker service create --name my-service --mount type=volume,volume-driver=tiborvass/sample-volume-plugin,source=pluginVol,destination=/tmp busybox top
|
||||
|
||||
$ docker service ls
|
||||
z1sj8bb8jnfn my-service replicated 1/1 busybox:latest
|
||||
```
|
||||
docker service ls shows service 1 instance of service running.
|
||||
|
||||
4. Observe the task getting scheduled in node 2:
|
||||
|
||||
```bash
|
||||
{% raw %}
|
||||
$ docker ps --format '{{.ID}}\t {{.Status}} {{.Names}} {{.Command}}'
|
||||
83fc1e842599 Up 2 days my-service.1.9jn59qzn7nbc3m0zt1hij12xs "top"
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
## Developing a plugin
|
||||
|
||||
#### The rootfs directory
|
||||
The `rootfs` directory represents the root filesystem of the plugin. In this
|
||||
example, it was created from a Dockerfile:
|
||||
|
||||
>**Note:** The `/run/docker/plugins` directory is mandatory inside of the
|
||||
plugin's filesystem for docker to communicate with the plugin.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/vieux/docker-volume-sshfs
|
||||
$ cd docker-volume-sshfs
|
||||
$ docker build -t rootfsimage .
|
||||
$ id=$(docker create rootfsimage true) # id was cd851ce43a403 when the image was created
|
||||
$ sudo mkdir -p myplugin/rootfs
|
||||
$ sudo docker export "$id" | sudo tar -x -C myplugin/rootfs
|
||||
$ docker rm -vf "$id"
|
||||
$ docker rmi rootfsimage
|
||||
```
|
||||
|
||||
#### The config.json file
|
||||
|
||||
The `config.json` file describes the plugin. See the [plugins config reference](config.md).
|
||||
|
||||
Consider the following `config.json` file.
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "sshFS plugin for Docker",
|
||||
"documentation": "https://docs.docker.com/engine/extend/plugins/",
|
||||
"entrypoint": ["/docker-volume-sshfs"],
|
||||
"network": {
|
||||
"type": "host"
|
||||
},
|
||||
"interface" : {
|
||||
"types": ["docker.volumedriver/1.0"],
|
||||
"socket": "sshfs.sock"
|
||||
},
|
||||
"linux": {
|
||||
"capabilities": ["CAP_SYS_ADMIN"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This plugin is a volume driver. It requires a `host` network and the
|
||||
`CAP_SYS_ADMIN` capability. It depends upon the `/docker-volume-sshfs`
|
||||
entrypoint and uses the `/run/docker/plugins/sshfs.sock` socket to communicate
|
||||
with Docker Engine. This plugin has no runtime parameters.
|
||||
|
||||
#### Creating the plugin
|
||||
|
||||
A new plugin can be created by running
|
||||
`docker plugin create <plugin-name> ./path/to/plugin/data` where the plugin
|
||||
data contains a plugin configuration file `config.json` and a root filesystem
|
||||
in subdirectory `rootfs`.
|
||||
|
||||
After that the plugin `<plugin-name>` will show up in `docker plugin ls`.
|
||||
Plugins can be pushed to remote registries with
|
||||
`docker plugin push <plugin-name>`.
|
||||
|
||||
|
||||
## Debugging plugins
|
||||
|
||||
Stdout of a plugin is redirected to dockerd logs. Such entries have a
|
||||
`plugin=<ID>` suffix. Here are a few examples of commands for pluginID
|
||||
`f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62` and their
|
||||
corresponding log entries in the docker daemon logs.
|
||||
|
||||
```bash
|
||||
$ docker plugin install tiborvass/sample-volume-plugins
|
||||
|
||||
INFO[0036] Starting... Found 0 volumes on startup plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker volume create -d tiborvass/sample-volume-plugins samplevol
|
||||
|
||||
INFO[0193] Create Called... Ensuring directory /data/samplevol exists on host... plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] open /var/lib/docker/plugin-data/local-persist.json: no such file or directory plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] Created volume samplevol with mountpoint /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker run -v samplevol:/tmp busybox sh
|
||||
|
||||
INFO[0421] Get Called... Found samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Mount Called... Mounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Unmount Called... Unmounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
#### Using docker-runc to obtain logfiles and shell into the plugin.
|
||||
|
||||
`docker-runc`, the default docker container runtime can be used for debugging
|
||||
plugins. This is specifically useful to collect plugin logs if they are
|
||||
redirected to a file.
|
||||
|
||||
```bash
|
||||
$ docker-runc list
|
||||
ID PID STATUS BUNDLE CREATED
|
||||
f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2679 running /run/docker/libcontainerd/f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2017-02-06T21:53:03.031537592Z
|
||||
r
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker-runc exec f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 cat /var/log/plugin.log
|
||||
```
|
||||
|
||||
If the plugin has a built-in shell, then exec into the plugin can be done as
|
||||
follows:
|
||||
```bash
|
||||
$ docker-runc exec -t f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 sh
|
||||
```
|
||||
|
||||
#### Using curl to debug plugin socket issues.
|
||||
|
||||
To verify if the plugin API socket that the docker daemon communicates with
|
||||
is responsive, use curl. In this example, we will make API calls from the
|
||||
docker host to volume and network plugins using curl 7.47.0 to ensure that
|
||||
the plugin is listening on the said socket. For a well functioning plugin,
|
||||
these basic requests should work. Note that plugin sockets are available on the host under `/var/run/docker/plugins/<pluginID>`
|
||||
|
||||
|
||||
```bash
|
||||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/e8a37ba56fc879c991f7d7921901723c64df6b42b87e6a0b055771ecf8477a6d/plugin.sock http:/VolumeDriver.List
|
||||
|
||||
{"Mountpoint":"","Err":"","Volumes":[{"Name":"myvol1","Mountpoint":"/data/myvol1"},{"Name":"myvol2","Mountpoint":"/data/myvol2"}],"Volume":null}
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/45e00a7ce6185d6e365904c8bcf62eb724b1fe307e0d4e7ecc9f6c1eb7bcdb70/plugin.sock http:/NetworkDriver.GetCapabilities
|
||||
|
||||
{"Scope":"local"}
|
||||
```
|
||||
When using curl 7.5 and above, the URL should be of the form
|
||||
`http://hostname/APICall`, where `hostname` is the valid hostname where the
|
||||
plugin is installed and `APICall` is the call to the plugin API.
|
||||
|
||||
For example, `http://localhost/VolumeDriver.List`
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: "Docker network driver plugins"
|
||||
description: "Network driver plugins."
|
||||
keywords: "Examples, Usage, plugins, docker, documentation, user guide"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Engine network driver plugins
|
||||
|
||||
This document describes Docker Engine network driver plugins generally
|
||||
available in Docker Engine. To view information on plugins
|
||||
managed by Docker Engine, refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
Docker Engine network plugins enable Engine deployments to be extended to
|
||||
support a wide range of networking technologies, such as VXLAN, IPVLAN, MACVLAN
|
||||
or something completely different. Network driver plugins are supported via the
|
||||
LibNetwork project. Each plugin is implemented as a "remote driver" for
|
||||
LibNetwork, which shares plugin infrastructure with Engine. Effectively, network
|
||||
driver plugins are activated in the same way as other plugins, and use the same
|
||||
kind of protocol.
|
||||
|
||||
## Network driver plugins and swarm mode
|
||||
|
||||
Docker 1.12 adds support for cluster management and orchestration called
|
||||
[swarm mode](https://docs.docker.com/engine/swarm/). Docker Engine running in swarm mode currently
|
||||
only supports the built-in overlay driver for networking. Therefore existing
|
||||
networking plugins will not work in swarm mode.
|
||||
|
||||
When you run Docker Engine outside of swarm mode, all networking plugins that
|
||||
worked in Docker 1.11 will continue to function normally. They do not require
|
||||
any modification.
|
||||
|
||||
## Using network driver plugins
|
||||
|
||||
The means of installing and running a network driver plugin depend on the
|
||||
particular plugin. So, be sure to install your plugin according to the
|
||||
instructions obtained from the plugin developer.
|
||||
|
||||
Once running however, network driver plugins are used just like the built-in
|
||||
network drivers: by being mentioned as a driver in network-oriented Docker
|
||||
commands. For example,
|
||||
|
||||
$ docker network create --driver weave mynet
|
||||
|
||||
Some network driver plugins are listed in [plugins](legacy_plugins.md)
|
||||
|
||||
The `mynet` network is now owned by `weave`, so subsequent commands
|
||||
referring to that network will be sent to the plugin,
|
||||
|
||||
$ docker run --network=mynet busybox top
|
||||
|
||||
|
||||
## Write a network plugin
|
||||
|
||||
Network plugins implement the [Docker plugin
|
||||
API](plugin_api.md) and the network plugin protocol
|
||||
|
||||
## Network plugin protocol
|
||||
|
||||
The network driver protocol, in addition to the plugin activation call, is
|
||||
documented as part of libnetwork:
|
||||
[https://github.com/docker/libnetwork/blob/master/docs/remote.md](https://github.com/docker/libnetwork/blob/master/docs/remote.md).
|
||||
|
||||
# Related Information
|
||||
|
||||
To interact with the Docker maintainers and other interested users, see the IRC channel `#docker-network`.
|
||||
|
||||
- [Docker networks feature overview](https://docs.docker.com/engine/userguide/networking/)
|
||||
- The [LibNetwork](https://github.com/docker/libnetwork) project
|
||||
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 45 KiB |
@@ -0,0 +1,164 @@
|
||||
---
|
||||
description: Volume plugin for Amazon EBS
|
||||
keywords: "API, Usage, plugins, documentation, developer, amazon, ebs, rexray, volume"
|
||||
title: Volume plugin for Amazon EBS
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# A proof-of-concept Rexray plugin
|
||||
|
||||
In this example, a simple Rexray plugin will be created for the purposes of using
|
||||
it on an Amazon EC2 instance with EBS. It is not meant to be a complete Rexray plugin.
|
||||
|
||||
The example source is available at [https://github.com/tiborvass/rexray-plugin](https://github.com/tiborvass/rexray-plugin).
|
||||
|
||||
To learn more about Rexray: [https://github.com/codedellemc/rexray](https://github.com/codedellemc/rexray)
|
||||
|
||||
## 1. Make a Docker image
|
||||
|
||||
The following is the Dockerfile used to containerize rexray.
|
||||
|
||||
```Dockerfile
|
||||
FROM debian:jessie
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates
|
||||
RUN wget https://dl.bintray.com/emccode/rexray/stable/0.6.4/rexray-Linux-x86_64-0.6.4.tar.gz -O rexray.tar.gz && tar -xvzf rexray.tar.gz -C /usr/bin && rm rexray.tar.gz
|
||||
RUN mkdir -p /run/docker/plugins /var/lib/libstorage/volumes
|
||||
ENTRYPOINT ["rexray"]
|
||||
CMD ["--help"]
|
||||
```
|
||||
|
||||
To build it you can run `image=$(cat Dockerfile | docker build -q -)` and `$image`
|
||||
will reference the containerized rexray image.
|
||||
|
||||
## 2. Extract rootfs
|
||||
|
||||
```sh
|
||||
$ TMPDIR=/tmp/rexray # for the purpose of this example
|
||||
$ # create container without running it, to extract the rootfs from image
|
||||
$ docker create --name rexray "$image"
|
||||
$ # save the rootfs to a tar archive
|
||||
$ docker export -o $TMPDIR/rexray.tar rexray
|
||||
$ # extract rootfs from tar archive to a rootfs folder
|
||||
$ ( mkdir -p $TMPDIR/rootfs; cd $TMPDIR/rootfs; tar xf ../rexray.tar )
|
||||
```
|
||||
|
||||
## 3. Add plugin configuration
|
||||
|
||||
We have to put the following JSON to `$TMPDIR/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Args": {
|
||||
"Description": "",
|
||||
"Name": "",
|
||||
"Settable": null,
|
||||
"Value": null
|
||||
},
|
||||
"Description": "A proof-of-concept EBS plugin (using rexray) for Docker",
|
||||
"Documentation": "https://github.com/tiborvass/rexray-plugin",
|
||||
"Entrypoint": [
|
||||
"/usr/bin/rexray", "service", "start", "-f"
|
||||
],
|
||||
"Env": [
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "REXRAY_SERVICE",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": "ebs"
|
||||
},
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "EBS_ACCESSKEY",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": ""
|
||||
},
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "EBS_SECRETKEY",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": ""
|
||||
}
|
||||
],
|
||||
"Interface": {
|
||||
"Socket": "rexray.sock",
|
||||
"Types": [
|
||||
"docker.volumedriver/1.0"
|
||||
]
|
||||
},
|
||||
"Linux": {
|
||||
"AllowAllDevices": true,
|
||||
"Capabilities": ["CAP_SYS_ADMIN"],
|
||||
"Devices": null
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Source": "/dev",
|
||||
"Destination": "/dev",
|
||||
"Type": "bind",
|
||||
"Options": ["rbind"]
|
||||
}
|
||||
],
|
||||
"Network": {
|
||||
"Type": "host"
|
||||
},
|
||||
"PropagatedMount": "/var/lib/libstorage/volumes",
|
||||
"User": {},
|
||||
"WorkDir": ""
|
||||
}
|
||||
```
|
||||
|
||||
Please note a couple of points:
|
||||
- `PropagatedMount` is needed so that the docker daemon can see mounts done by the
|
||||
rexray plugin from within the container, otherwise the docker daemon is not able
|
||||
to mount a docker volume.
|
||||
- The rexray plugin needs dynamic access to host devices. For that reason, we
|
||||
have to give it access to all devices under `/dev` and set `AllowAllDevices` to
|
||||
true for proper access.
|
||||
- The user of this simple plugin can change only 3 settings: `REXRAY_SERVICE`,
|
||||
`EBS_ACCESSKEY` and `EBS_SECRETKEY`. This is because of the reduced scope of this
|
||||
plugin. Ideally other rexray parameters could also be set.
|
||||
|
||||
## 4. Create plugin
|
||||
|
||||
`docker plugin create tiborvass/rexray-plugin "$TMPDIR"` will create the plugin.
|
||||
|
||||
```sh
|
||||
$ docker plugin ls
|
||||
ID NAME DESCRIPTION ENABLED
|
||||
2475a4bd0ca5 tiborvass/rexray-plugin:latest A rexray volume plugin for Docker false
|
||||
```
|
||||
|
||||
## 5. Test plugin
|
||||
|
||||
```sh
|
||||
$ docker plugin set tiborvass/rexray-plugin EBS_ACCESSKEY=$AWS_ACCESSKEY EBS_SECRETKEY=$AWS_SECRETKEY`
|
||||
$ docker plugin enable tiborvass/rexray-plugin
|
||||
$ docker volume create -d tiborvass/rexray-plugin my-ebs-volume
|
||||
$ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
tiborvass/rexray-plugin:latest my-ebs-volume
|
||||
$ docker run --rm -v my-ebs-volume:/volume busybox sh -c 'echo bye > /volume/hi'
|
||||
$ docker run --rm -v my-ebs-volume:/volume busybox cat /volume/hi
|
||||
bye
|
||||
```
|
||||
|
||||
## 6. Push plugin
|
||||
|
||||
First, ensure you are logged in with `docker login`. Then you can run:
|
||||
`docker plugin push tiborvass/rexray-plugin` to push it like a regular docker
|
||||
image to a registry, to make it available for others to install via
|
||||
`docker plugin install tiborvass/rexray-plugin EBS_ACCESSKEY=$AWS_ACCESSKEY EBS_SECRETKEY=$AWS_SECRETKEY`.
|
||||
@@ -0,0 +1,225 @@
|
||||
---
|
||||
title: "Plugin config"
|
||||
description: "How develop and use a plugin with the managed plugin system"
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
|
||||
# Plugin Config Version 1 of Plugin V2
|
||||
|
||||
This document outlines the format of the V0 plugin configuration. The plugin
|
||||
config described herein was introduced in the Docker daemon in the [v1.12.0
|
||||
release](https://github.com/docker/docker/commit/f37117045c5398fd3dca8016ea8ca0cb47e7312b).
|
||||
|
||||
Plugin configs describe the various constituents of a docker plugin. Plugin
|
||||
configs can be serialized to JSON format with the following media types:
|
||||
|
||||
Config Type | Media Type
|
||||
------------- | -------------
|
||||
config | "application/vnd.docker.plugin.v1+json"
|
||||
|
||||
|
||||
## *Config* Field Descriptions
|
||||
|
||||
Config provides the base accessible fields for working with V0 plugin format
|
||||
in the registry.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the plugin
|
||||
|
||||
- **`documentation`** *string*
|
||||
|
||||
link to the documentation about the plugin
|
||||
|
||||
- **`interface`** *PluginInterface*
|
||||
|
||||
interface implemented by the plugins, struct consisting of the following fields
|
||||
|
||||
- **`types`** *string array*
|
||||
|
||||
types indicate what interface(s) the plugin currently implements.
|
||||
|
||||
currently supported:
|
||||
|
||||
- **docker.volumedriver/1.0**
|
||||
|
||||
- **docker.authz/1.0**
|
||||
|
||||
- **`socket`** *string*
|
||||
|
||||
socket is the name of the socket the engine should use to communicate with the plugins.
|
||||
the socket will be created in `/run/docker/plugins`.
|
||||
|
||||
|
||||
- **`entrypoint`** *string array*
|
||||
|
||||
entrypoint of the plugin, see [`ENTRYPOINT`](../reference/builder.md#entrypoint)
|
||||
|
||||
- **`workdir`** *string*
|
||||
|
||||
workdir of the plugin, see [`WORKDIR`](../reference/builder.md#workdir)
|
||||
|
||||
- **`network`** *PluginNetwork*
|
||||
|
||||
network of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`type`** *string*
|
||||
|
||||
network type.
|
||||
|
||||
currently supported:
|
||||
|
||||
- **bridge**
|
||||
- **host**
|
||||
- **none**
|
||||
|
||||
- **`mounts`** *PluginMount array*
|
||||
|
||||
mount of the plugin, struct consisting of the following fields, see [`MOUNTS`](https://github.com/opencontainers/runtime-spec/blob/master/config.md#mounts)
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the mount.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the mount.
|
||||
|
||||
- **`source`** *string*
|
||||
|
||||
source of the mount.
|
||||
|
||||
- **`destination`** *string*
|
||||
|
||||
destination of the mount.
|
||||
|
||||
- **`type`** *string*
|
||||
|
||||
mount type.
|
||||
|
||||
- **`options`** *string array*
|
||||
|
||||
options of the mount.
|
||||
|
||||
- **`propagatedMount`** *string*
|
||||
|
||||
path to be mounted as rshared, so that mounts under that path are visible to docker. This is useful for volume plugins.
|
||||
This path will be bind-mounted outisde of the plugin rootfs so it's contents
|
||||
are preserved on upgrade.
|
||||
|
||||
- **`env`** *PluginEnv array*
|
||||
|
||||
env of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the env.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the env.
|
||||
|
||||
- **`value`** *string*
|
||||
|
||||
value of the env.
|
||||
|
||||
- **`args`** *PluginArgs*
|
||||
|
||||
args of the plugin, struct consisting of the following fields
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the args.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the args.
|
||||
|
||||
- **`value`** *string array*
|
||||
|
||||
values of the args.
|
||||
|
||||
- **`linux`** *PluginLinux*
|
||||
|
||||
- **`capabilities`** *string array*
|
||||
|
||||
capabilities of the plugin (*Linux only*), see list [`here`](https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md#security)
|
||||
|
||||
- **`allowAllDevices`** *boolean*
|
||||
|
||||
If `/dev` is bind mounted from the host, and allowAllDevices is set to true, the plugin will have `rwm` access to all devices on the host.
|
||||
|
||||
- **`devices`** *PluginDevice array*
|
||||
|
||||
device of the plugin, (*Linux only*), struct consisting of the following fields, see [`DEVICES`](https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#devices)
|
||||
|
||||
- **`name`** *string*
|
||||
|
||||
name of the device.
|
||||
|
||||
- **`description`** *string*
|
||||
|
||||
description of the device.
|
||||
|
||||
- **`path`** *string*
|
||||
|
||||
path of the device.
|
||||
|
||||
## Example Config
|
||||
|
||||
*Example showing the 'tiborvass/sample-volume-plugin' plugin config.*
|
||||
|
||||
```json
|
||||
{
|
||||
"Args": {
|
||||
"Description": "",
|
||||
"Name": "",
|
||||
"Settable": null,
|
||||
"Value": null
|
||||
},
|
||||
"Description": "A sample volume plugin for Docker",
|
||||
"Documentation": "https://docs.docker.com/engine/extend/plugins/",
|
||||
"Entrypoint": [
|
||||
"/usr/bin/sample-volume-plugin",
|
||||
"/data"
|
||||
],
|
||||
"Env": [
|
||||
{
|
||||
"Description": "",
|
||||
"Name": "DEBUG",
|
||||
"Settable": [
|
||||
"value"
|
||||
],
|
||||
"Value": "0"
|
||||
}
|
||||
],
|
||||
"Interface": {
|
||||
"Socket": "plugin.sock",
|
||||
"Types": [
|
||||
"docker.volumedriver/1.0"
|
||||
]
|
||||
},
|
||||
"Linux": {
|
||||
"Capabilities": null,
|
||||
"AllowAllDevices": false,
|
||||
"Devices": null
|
||||
},
|
||||
"Mounts": null,
|
||||
"Network": {
|
||||
"Type": ""
|
||||
},
|
||||
"PropagatedMount": "/data",
|
||||
"User": {},
|
||||
"Workdir": ""
|
||||
}
|
||||
```
|
||||
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,319 @@
|
||||
---
|
||||
description: Develop and use a plugin with the managed plugin system
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
title: Managed plugin system
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Docker Engine managed plugin system
|
||||
|
||||
* [Installing and using a plugin](index.md#installing-and-using-a-plugin)
|
||||
* [Developing a plugin](index.md#developing-a-plugin)
|
||||
* [Debugging plugins](index.md#debugging-plugins)
|
||||
|
||||
Docker Engine's plugin system allows you to install, start, stop, and remove
|
||||
plugins using Docker Engine.
|
||||
|
||||
For information about the legacy plugin system available in Docker Engine 1.12
|
||||
and earlier, see [Understand legacy Docker Engine plugins](legacy_plugins.md).
|
||||
|
||||
> **Note**: Docker Engine managed plugins are currently not supported
|
||||
on Windows daemons.
|
||||
|
||||
## Installing and using a plugin
|
||||
|
||||
Plugins are distributed as Docker images and can be hosted on Docker Hub or on
|
||||
a private registry.
|
||||
|
||||
To install a plugin, use the `docker plugin install` command, which pulls the
|
||||
plugin from Docker Hub or your private registry, prompts you to grant
|
||||
permissions or capabilities if necessary, and enables the plugin.
|
||||
|
||||
To check the status of installed plugins, use the `docker plugin ls` command.
|
||||
Plugins that start successfully are listed as enabled in the output.
|
||||
|
||||
After a plugin is installed, you can use it as an option for another Docker
|
||||
operation, such as creating a volume.
|
||||
|
||||
In the following example, you install the `sshfs` plugin, verify that it is
|
||||
enabled, and use it to create a volume.
|
||||
|
||||
> **Note**: This example is intended for instructional purposes only. Once the volume is created, your SSH password to the remote host will be exposed as plaintext when inspecting the volume. You should delete the volume as soon as you are done with the example.
|
||||
|
||||
1. Install the `sshfs` plugin.
|
||||
|
||||
```bash
|
||||
$ docker plugin install vieux/sshfs
|
||||
|
||||
Plugin "vieux/sshfs" is requesting the following privileges:
|
||||
- network: [host]
|
||||
- capabilities: [CAP_SYS_ADMIN]
|
||||
Do you grant the above permissions? [y/N] y
|
||||
|
||||
vieux/sshfs
|
||||
```
|
||||
|
||||
The plugin requests 2 privileges:
|
||||
|
||||
- It needs access to the `host` network.
|
||||
- It needs the `CAP_SYS_ADMIN` capability, which allows the plugin to run
|
||||
the `mount` command.
|
||||
|
||||
2. Check that the plugin is enabled in the output of `docker plugin ls`.
|
||||
|
||||
```bash
|
||||
$ docker plugin ls
|
||||
|
||||
ID NAME TAG DESCRIPTION ENABLED
|
||||
69553ca1d789 vieux/sshfs latest the `sshfs` plugin true
|
||||
```
|
||||
|
||||
3. Create a volume using the plugin.
|
||||
This example mounts the `/remote` directory on host `1.2.3.4` into a
|
||||
volume named `sshvolume`.
|
||||
|
||||
This volume can now be mounted into containers.
|
||||
|
||||
```bash
|
||||
$ docker volume create \
|
||||
-d vieux/sshfs \
|
||||
--name sshvolume \
|
||||
-o sshcmd=user@1.2.3.4:/remote \
|
||||
-o password=$(cat file_containing_password_for_remote_host)
|
||||
|
||||
sshvolume
|
||||
```
|
||||
4. Verify that the volume was created successfully.
|
||||
|
||||
```bash
|
||||
$ docker volume ls
|
||||
|
||||
DRIVER NAME
|
||||
vieux/sshfs sshvolume
|
||||
```
|
||||
|
||||
5. Start a container that uses the volume `sshvolume`.
|
||||
|
||||
```bash
|
||||
$ docker run --rm -v sshvolume:/data busybox ls /data
|
||||
|
||||
<content of /remote on machine 1.2.3.4>
|
||||
```
|
||||
|
||||
6. Remove the volume `sshvolume`
|
||||
```bash
|
||||
docker volume rm sshvolume
|
||||
|
||||
sshvolume
|
||||
```
|
||||
To disable a plugin, use the `docker plugin disable` command. To completely
|
||||
remove it, use the `docker plugin remove` command. For other available
|
||||
commands and options, see the
|
||||
[command line reference](../reference/commandline/index.md).
|
||||
|
||||
## Service creation using plugins
|
||||
|
||||
In swarm mode, it is possible to create a service that allows for attaching
|
||||
to networks or mounting volumes. Swarm schedules services based on plugin availability
|
||||
on a node. In this example, a volume plugin is installed on a swarm worker and a volume
|
||||
is created using the plugin. In the manager, a service is created with the relevant
|
||||
mount options. It can be observed that the service is scheduled to run on the worker
|
||||
node with the said volume plugin and volume.
|
||||
|
||||
In the following example, node1 is the manager and node2 is the worker.
|
||||
|
||||
1. Prepare manager. In node 1:
|
||||
|
||||
```bash
|
||||
$ docker swarm init
|
||||
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
|
||||
```
|
||||
|
||||
2. Join swarm, install plugin and create volume on worker. In node 2:
|
||||
|
||||
```bash
|
||||
$ docker swarm join \
|
||||
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
|
||||
192.168.99.100:2377
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker plugin install tiborvass/sample-volume-plugin
|
||||
latest: Pulling from tiborvass/sample-volume-plugin
|
||||
eb9c16fbdc53: Download complete
|
||||
Digest: sha256:00b42de88f3a3e0342e7b35fa62394b0a9ceb54d37f4c50be5d3167899994639
|
||||
Status: Downloaded newer image for tiborvass/sample-volume-plugin:latest
|
||||
Installed plugin tiborvass/sample-volume-plugin
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker volume create -d tiborvass/sample-volume-plugin --name pluginVol
|
||||
```
|
||||
|
||||
3. Create a service using the plugin and volume. In node1:
|
||||
|
||||
```bash
|
||||
$ docker service create --name my-service --mount type=volume,volume-driver=tiborvass/sample-volume-plugin,source=pluginVol,destination=/tmp busybox top
|
||||
|
||||
$ docker service ls
|
||||
z1sj8bb8jnfn my-service replicated 1/1 busybox:latest
|
||||
```
|
||||
docker service ls shows service 1 instance of service running.
|
||||
|
||||
4. Observe the task getting scheduled in node 2:
|
||||
|
||||
```bash
|
||||
{% raw %}
|
||||
$ docker ps --format '{{.ID}}\t {{.Status}} {{.Names}} {{.Command}}'
|
||||
83fc1e842599 Up 2 days my-service.1.9jn59qzn7nbc3m0zt1hij12xs "top"
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
## Developing a plugin
|
||||
|
||||
#### The rootfs directory
|
||||
The `rootfs` directory represents the root filesystem of the plugin. In this
|
||||
example, it was created from a Dockerfile:
|
||||
|
||||
>**Note:** The `/run/docker/plugins` directory is mandatory inside of the
|
||||
plugin's filesystem for docker to communicate with the plugin.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/vieux/docker-volume-sshfs
|
||||
$ cd docker-volume-sshfs
|
||||
$ docker build -t rootfsimage .
|
||||
$ id=$(docker create rootfsimage true) # id was cd851ce43a403 when the image was created
|
||||
$ sudo mkdir -p myplugin/rootfs
|
||||
$ sudo docker export "$id" | sudo tar -x -C myplugin/rootfs
|
||||
$ docker rm -vf "$id"
|
||||
$ docker rmi rootfsimage
|
||||
```
|
||||
|
||||
#### The config.json file
|
||||
|
||||
The `config.json` file describes the plugin. See the [plugins config reference](config.md).
|
||||
|
||||
Consider the following `config.json` file.
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "sshFS plugin for Docker",
|
||||
"documentation": "https://docs.docker.com/engine/extend/plugins/",
|
||||
"entrypoint": ["/docker-volume-sshfs"],
|
||||
"network": {
|
||||
"type": "host"
|
||||
},
|
||||
"interface" : {
|
||||
"types": ["docker.volumedriver/1.0"],
|
||||
"socket": "sshfs.sock"
|
||||
},
|
||||
"linux": {
|
||||
"capabilities": ["CAP_SYS_ADMIN"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This plugin is a volume driver. It requires a `host` network and the
|
||||
`CAP_SYS_ADMIN` capability. It depends upon the `/docker-volume-sshfs`
|
||||
entrypoint and uses the `/run/docker/plugins/sshfs.sock` socket to communicate
|
||||
with Docker Engine. This plugin has no runtime parameters.
|
||||
|
||||
#### Creating the plugin
|
||||
|
||||
A new plugin can be created by running
|
||||
`docker plugin create <plugin-name> ./path/to/plugin/data` where the plugin
|
||||
data contains a plugin configuration file `config.json` and a root filesystem
|
||||
in subdirectory `rootfs`.
|
||||
|
||||
After that the plugin `<plugin-name>` will show up in `docker plugin ls`.
|
||||
Plugins can be pushed to remote registries with
|
||||
`docker plugin push <plugin-name>`.
|
||||
|
||||
|
||||
## Debugging plugins
|
||||
|
||||
Stdout of a plugin is redirected to dockerd logs. Such entries have a
|
||||
`plugin=<ID>` suffix. Here are a few examples of commands for pluginID
|
||||
`f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62` and their
|
||||
corresponding log entries in the docker daemon logs.
|
||||
|
||||
```bash
|
||||
$ docker plugin install tiborvass/sample-volume-plugins
|
||||
|
||||
INFO[0036] Starting... Found 0 volumes on startup plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker volume create -d tiborvass/sample-volume-plugins samplevol
|
||||
|
||||
INFO[0193] Create Called... Ensuring directory /data/samplevol exists on host... plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] open /var/lib/docker/plugin-data/local-persist.json: no such file or directory plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] Created volume samplevol with mountpoint /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0193] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker run -v samplevol:/tmp busybox sh
|
||||
|
||||
INFO[0421] Get Called... Found samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Mount Called... Mounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
INFO[0421] Unmount Called... Unmounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||||
```
|
||||
|
||||
#### Using docker-runc to obtain logfiles and shell into the plugin.
|
||||
|
||||
`docker-runc`, the default docker container runtime can be used for debugging
|
||||
plugins. This is specifically useful to collect plugin logs if they are
|
||||
redirected to a file.
|
||||
|
||||
```bash
|
||||
$ docker-runc list
|
||||
ID PID STATUS BUNDLE CREATED
|
||||
f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2679 running /run/docker/libcontainerd/f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2017-02-06T21:53:03.031537592Z
|
||||
r
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker-runc exec f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 cat /var/log/plugin.log
|
||||
```
|
||||
|
||||
If the plugin has a built-in shell, then exec into the plugin can be done as
|
||||
follows:
|
||||
```bash
|
||||
$ docker-runc exec -t f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 sh
|
||||
```
|
||||
|
||||
#### Using curl to debug plugin socket issues.
|
||||
|
||||
To verify if the plugin API socket that the docker daemon communicates with
|
||||
is responsive, use curl. In this example, we will make API calls from the
|
||||
docker host to volume and network plugins using curl 7.47.0 to ensure that
|
||||
the plugin is listening on the said socket. For a well functioning plugin,
|
||||
these basic requests should work. Note that plugin sockets are available on the host under `/var/run/docker/plugins/<pluginID>`
|
||||
|
||||
|
||||
```bash
|
||||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/e8a37ba56fc879c991f7d7921901723c64df6b42b87e6a0b055771ecf8477a6d/plugin.sock http:/VolumeDriver.List
|
||||
|
||||
{"Mountpoint":"","Err":"","Volumes":[{"Name":"myvol1","Mountpoint":"/data/myvol1"},{"Name":"myvol2","Mountpoint":"/data/myvol2"}],"Volume":null}
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/45e00a7ce6185d6e365904c8bcf62eb724b1fe307e0d4e7ecc9f6c1eb7bcdb70/plugin.sock http:/NetworkDriver.GetCapabilities
|
||||
|
||||
{"Scope":"local"}
|
||||
```
|
||||
When using curl 7.5 and above, the URL should be of the form
|
||||
`http://hostname/APICall`, where `hostname` is the valid hostname where the
|
||||
plugin is installed and `APICall` is the call to the plugin API.
|
||||
|
||||
For example, `http://localhost/VolumeDriver.List`
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
redirect_from:
|
||||
- "/engine/extend/plugins/"
|
||||
title: "Use Docker Engine plugins"
|
||||
description: "How to add additional functionality to Docker with plugins extensions"
|
||||
keywords: "Examples, Usage, plugins, docker, documentation, user guide"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
This document describes the Docker Engine plugins generally available in Docker
|
||||
Engine. To view information on plugins managed by Docker,
|
||||
refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
You can extend the capabilities of the Docker Engine by loading third-party
|
||||
plugins. This page explains the types of plugins and provides links to several
|
||||
volume and network plugins for Docker.
|
||||
|
||||
## Types of plugins
|
||||
|
||||
Plugins extend Docker's functionality. They come in specific types. For
|
||||
example, a [volume plugin](plugins_volume.md) might enable Docker
|
||||
volumes to persist across multiple Docker hosts and a
|
||||
[network plugin](plugins_network.md) might provide network plumbing.
|
||||
|
||||
Currently Docker supports authorization, volume and network driver plugins. In the future it
|
||||
will support additional plugin types.
|
||||
|
||||
## Installing a plugin
|
||||
|
||||
Follow the instructions in the plugin's documentation.
|
||||
|
||||
## Finding a plugin
|
||||
|
||||
The sections below provide an inexhaustive overview of available plugins.
|
||||
|
||||
<style>
|
||||
#DocumentationText tr td:first-child { white-space: nowrap;}
|
||||
</style>
|
||||
|
||||
### Network plugins
|
||||
|
||||
Plugin | Description
|
||||
----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Contiv Networking](https://github.com/contiv/netplugin) | An open source network plugin to provide infrastructure and security policies for a multi-tenant micro services deployment, while providing an integration to physical network for non-container workload. Contiv Networking implements the remote driver and IPAM APIs available in Docker 1.9 onwards.
|
||||
[Kuryr Network Plugin](https://github.com/openstack/kuryr) | A network plugin is developed as part of the OpenStack Kuryr project and implements the Docker networking (libnetwork) remote driver API by utilizing Neutron, the OpenStack networking service. It includes an IPAM driver as well.
|
||||
[Weave Network Plugin](https://www.weave.works/docs/net/latest/introducing-weave/) | A network plugin that creates a virtual network that connects your Docker containers - across multiple hosts or clouds and enables automatic discovery of applications. Weave networks are resilient, partition tolerant, secure and work in partially connected networks, and other adverse environments - all configured with delightful simplicity.
|
||||
|
||||
### Volume plugins
|
||||
|
||||
Plugin | Description
|
||||
----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Azure File Storage plugin](https://github.com/Azure/azurefile-dockervolumedriver) | Lets you mount Microsoft [Azure File Storage](https://azure.microsoft.com/blog/azure-file-storage-now-generally-available/) shares to Docker containers as volumes using the SMB 3.0 protocol. [Learn more](https://azure.microsoft.com/blog/persistent-docker-volumes-with-azure-file-storage/).
|
||||
[BeeGFS Volume Plugin](https://github.com/RedCoolBeans/docker-volume-beegfs) | An open source volume plugin to create persistent volumes in a BeeGFS parallel file system.
|
||||
[Blockbridge plugin](https://github.com/blockbridge/blockbridge-docker-volume) | A volume plugin that provides access to an extensible set of container-based persistent storage options. It supports single and multi-host Docker environments with features that include tenant isolation, automated provisioning, encryption, secure deletion, snapshots and QoS.
|
||||
[Contiv Volume Plugin](https://github.com/contiv/volplugin) | An open source volume plugin that provides multi-tenant, persistent, distributed storage with intent based consumption. It has support for Ceph and NFS.
|
||||
[Convoy plugin](https://github.com/rancher/convoy) | A volume plugin for a variety of storage back-ends including device mapper and NFS. It's a simple standalone executable written in Go and provides the framework to support vendor-specific extensions such as snapshots, backups and restore.
|
||||
[DigitalOcean Block Storage plugin](https://github.com/omallo/docker-volume-plugin-dostorage) | Integrates DigitalOcean's [block storage solution](https://www.digitalocean.com/products/storage/) into the Docker ecosystem by automatically attaching a given block storage volume to a DigitalOcean droplet and making the contents of the volume available to Docker containers running on that droplet.
|
||||
[DRBD plugin](https://www.drbd.org/en/supported-projects/docker) | A volume plugin that provides highly available storage replicated by [DRBD](https://www.drbd.org). Data written to the docker volume is replicated in a cluster of DRBD nodes.
|
||||
[Flocker plugin](https://clusterhq.com/docker-plugin/) | A volume plugin that provides multi-host portable volumes for Docker, enabling you to run databases and other stateful containers and move them around across a cluster of machines.
|
||||
[Fuxi Volume Plugin](https://github.com/openstack/fuxi) | A volume plugin that is developed as part of the OpenStack Kuryr project and implements the Docker volume plugin API by utilizing Cinder, the OpenStack block storage service.
|
||||
[gce-docker plugin](https://github.com/mcuadros/gce-docker) | A volume plugin able to attach, format and mount Google Compute [persistent-disks](https://cloud.google.com/compute/docs/disks/persistent-disks).
|
||||
[GlusterFS plugin](https://github.com/calavera/docker-volume-glusterfs) | A volume plugin that provides multi-host volumes management for Docker using GlusterFS.
|
||||
[Horcrux Volume Plugin](https://github.com/muthu-r/horcrux) | A volume plugin that allows on-demand, version controlled access to your data. Horcrux is an open-source plugin, written in Go, and supports SCP, [Minio](https://www.minio.io) and Amazon S3.
|
||||
[HPE 3Par Volume Plugin](https://github.com/hpe-storage/python-hpedockerplugin/) | A volume plugin that supports HPE 3Par and StoreVirtual iSCSI storage arrays.
|
||||
[IPFS Volume Plugin](http://github.com/vdemeester/docker-volume-ipfs) | An open source volume plugin that allows using an [ipfs](https://ipfs.io/) filesystem as a volume.
|
||||
[Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) | A plugin that provides credentials and secret management using Keywhiz as a central repository.
|
||||
[Local Persist Plugin](https://github.com/CWSpear/local-persist) | A volume plugin that extends the default `local` driver's functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to *always persist*, even if the volume is removed via `docker volume rm`.
|
||||
[NetApp Plugin](https://github.com/NetApp/netappdvp) (nDVP) | A volume plugin that provides direct integration with the Docker ecosystem for the NetApp storage portfolio. The nDVP package supports the provisioning and management of storage resources from the storage platform to Docker hosts, with a robust framework for adding additional platforms in the future.
|
||||
[Netshare plugin](https://github.com/ContainX/docker-volume-netshare) | A volume plugin that provides volume management for NFS 3/4, AWS EFS and CIFS file systems.
|
||||
[Nimble Storage Volume Plugin](https://connect.nimblestorage.com/community/app-integration/docker)| A volume plug-in that integrates with Nimble Storage Unified Flash Fabric arrays. The plug-in abstracts array volume capabilities to the Docker administrator to allow self-provisioning of secure multi-tenant volumes and clones.
|
||||
[OpenStorage Plugin](https://github.com/libopenstorage/openstorage) | A cluster-aware volume plugin that provides volume management for file and block storage solutions. It implements a vendor neutral specification for implementing extensions such as CoS, encryption, and snapshots. It has example drivers based on FUSE, NFS, NBD and EBS to name a few.
|
||||
[Portworx Volume Plugin](https://github.com/portworx/px-dev) | A volume plugin that turns any server into a scale-out converged compute/storage node, providing container granular storage and highly available volumes across any node, using a shared-nothing storage backend that works with any docker scheduler.
|
||||
[Quobyte Volume Plugin](https://github.com/quobyte/docker-volume) | A volume plugin that connects Docker to [Quobyte](http://www.quobyte.com/containers)'s data center file system, a general-purpose scalable and fault-tolerant storage platform.
|
||||
[REX-Ray plugin](https://github.com/emccode/rexray) | A volume plugin which is written in Go and provides advanced storage functionality for many platforms including VirtualBox, EC2, Google Compute Engine, OpenStack, and EMC.
|
||||
[Virtuozzo Storage and Ploop plugin](https://github.com/virtuozzo/docker-volume-ploop) | A volume plugin with support for Virtuozzo Storage distributed cloud file system as well as ploop devices.
|
||||
[VMware vSphere Storage Plugin](https://github.com/vmware/docker-volume-vsphere) | Docker Volume Driver for vSphere enables customers to address persistent storage requirements for Docker containers in vSphere environments.
|
||||
|
||||
### Authorization plugins
|
||||
|
||||
Plugin | Description
|
||||
------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[Casbin AuthZ Plugin](https://github.com/casbin/casbin-authz-plugin) | An authorization plugin based on [Casbin](https://github.com/casbin/casbin), which supports access control models like ACL, RBAC, ABAC. The access control model can be customized. The policy can be persisted into file or DB.
|
||||
[Twistlock AuthZ Broker](https://github.com/twistlock/authz) | A basic extendable authorization plugin that runs directly on the host or inside a container. This plugin allows you to define user policies that it evaluates during authorization. Basic authorization is provided if Docker daemon is started with the --tlsverify flag (username is extracted from the certificate common name).
|
||||
|
||||
## Troubleshooting a plugin
|
||||
|
||||
If you are having problems with Docker after loading a plugin, ask the authors
|
||||
of the plugin for help. The Docker team may not be able to assist you.
|
||||
|
||||
## Writing a plugin
|
||||
|
||||
If you are interested in writing a plugin for Docker, or seeing how they work
|
||||
under the hood, see the [docker plugins reference](plugin_api.md).
|
||||
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: "Plugins API"
|
||||
description: "How to write Docker plugins extensions "
|
||||
keywords: "API, Usage, plugins, documentation, developer"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# Docker Plugin API
|
||||
|
||||
Docker plugins are out-of-process extensions which add capabilities to the
|
||||
Docker Engine.
|
||||
|
||||
This document describes the Docker Engine plugin API. To view information on
|
||||
plugins managed by Docker Engine, refer to [Docker Engine plugin system](index.md).
|
||||
|
||||
This page is intended for people who want to develop their own Docker plugin.
|
||||
If you just want to learn about or use Docker plugins, look
|
||||
[here](legacy_plugins.md).
|
||||
|
||||
## What plugins are
|
||||
|
||||
A plugin is a process running on the same or a different host as the docker daemon,
|
||||
which registers itself by placing a file on the same docker host in one of the plugin
|
||||
directories described in [Plugin discovery](#plugin-discovery).
|
||||
|
||||
Plugins have human-readable names, which are short, lowercase strings. For
|
||||
example, `flocker` or `weave`.
|
||||
|
||||
Plugins can run inside or outside containers. Currently running them outside
|
||||
containers is recommended.
|
||||
|
||||
## Plugin discovery
|
||||
|
||||
Docker discovers plugins by looking for them in the plugin directory whenever a
|
||||
user or container tries to use one by name.
|
||||
|
||||
There are three types of files which can be put in the plugin directory.
|
||||
|
||||
* `.sock` files are UNIX domain sockets.
|
||||
* `.spec` files are text files containing a URL, such as `unix:///other.sock` or `tcp://localhost:8080`.
|
||||
* `.json` files are text files containing a full json specification for the plugin.
|
||||
|
||||
Plugins with UNIX domain socket files must run on the same docker host, whereas
|
||||
plugins with spec or json files can run on a different host if a remote URL is specified.
|
||||
|
||||
UNIX domain socket files must be located under `/run/docker/plugins`, whereas
|
||||
spec files can be located either under `/etc/docker/plugins` or `/usr/lib/docker/plugins`.
|
||||
|
||||
The name of the file (excluding the extension) determines the plugin name.
|
||||
|
||||
For example, the `flocker` plugin might create a UNIX socket at
|
||||
`/run/docker/plugins/flocker.sock`.
|
||||
|
||||
You can define each plugin into a separated subdirectory if you want to isolate definitions from each other.
|
||||
For example, you can create the `flocker` socket under `/run/docker/plugins/flocker/flocker.sock` and only
|
||||
mount `/run/docker/plugins/flocker` inside the `flocker` container.
|
||||
|
||||
Docker always searches for unix sockets in `/run/docker/plugins` first. It checks for spec or json files under
|
||||
`/etc/docker/plugins` and `/usr/lib/docker/plugins` if the socket doesn't exist. The directory scan stops as
|
||||
soon as it finds the first plugin definition with the given name.
|
||||
|
||||
### JSON specification
|
||||
|
||||
This is the JSON format for a plugin:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "plugin-example",
|
||||
"Addr": "https://example.com/docker/plugin",
|
||||
"TLSConfig": {
|
||||
"InsecureSkipVerify": false,
|
||||
"CAFile": "/usr/shared/docker/certs/example-ca.pem",
|
||||
"CertFile": "/usr/shared/docker/certs/example-cert.pem",
|
||||
"KeyFile": "/usr/shared/docker/certs/example-key.pem"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `TLSConfig` field is optional and TLS will only be verified if this configuration is present.
|
||||
|
||||
## Plugin lifecycle
|
||||
|
||||
Plugins should be started before Docker, and stopped after Docker. For
|
||||
example, when packaging a plugin for a platform which supports `systemd`, you
|
||||
might use [`systemd` dependencies](
|
||||
http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Before=) to
|
||||
manage startup and shutdown order.
|
||||
|
||||
When upgrading a plugin, you should first stop the Docker daemon, upgrade the
|
||||
plugin, then start Docker again.
|
||||
|
||||
## Plugin activation
|
||||
|
||||
When a plugin is first referred to -- either by a user referring to it by name
|
||||
(e.g. `docker run --volume-driver=foo`) or a container already configured to
|
||||
use a plugin being started -- Docker looks for the named plugin in the plugin
|
||||
directory and activates it with a handshake. See Handshake API below.
|
||||
|
||||
Plugins are *not* activated automatically at Docker daemon startup. Rather,
|
||||
they are activated only lazily, or on-demand, when they are needed.
|
||||
|
||||
## Systemd socket activation
|
||||
|
||||
Plugins may also be socket activated by `systemd`. The official [Plugins helpers](https://github.com/docker/go-plugins-helpers)
|
||||
natively supports socket activation. In order for a plugin to be socket activated it needs
|
||||
a `service` file and a `socket` file.
|
||||
|
||||
The `service` file (for example `/lib/systemd/system/your-plugin.service`):
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Your plugin
|
||||
Before=docker.service
|
||||
After=network.target your-plugin.socket
|
||||
Requires=your-plugin.socket docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/lib/docker/your-plugin
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
The `socket` file (for example `/lib/systemd/system/your-plugin.socket`):
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Your plugin
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/docker/plugins/your-plugin.sock
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
```
|
||||
|
||||
This will allow plugins to be actually started when the Docker daemon connects to
|
||||
the sockets they're listening on (for instance the first time the daemon uses them
|
||||
or if one of the plugin goes down accidentally).
|
||||
|
||||
## API design
|
||||
|
||||
The Plugin API is RPC-style JSON over HTTP, much like webhooks.
|
||||
|
||||
Requests flow *from* the Docker daemon *to* the plugin. So the plugin needs to
|
||||
implement an HTTP server and bind this to the UNIX socket mentioned in the
|
||||
"plugin discovery" section.
|
||||
|
||||
All requests are HTTP `POST` requests.
|
||||
|
||||
The API is versioned via an Accept header, which currently is always set to
|
||||
`application/vnd.docker.plugins.v1+json`.
|
||||
|
||||
## Handshake API
|
||||
|
||||
Plugins are activated via the following "handshake" API call.
|
||||
|
||||
### /Plugin.Activate
|
||||
|
||||
**Request:** empty body
|
||||
|
||||
**Response:**
|
||||
```
|
||||
{
|
||||
"Implements": ["VolumeDriver"]
|
||||
}
|
||||
```
|
||||
|
||||
Responds with a list of Docker subsystems which this plugin implements.
|
||||
After activation, the plugin will then be sent events from this subsystem.
|
||||
|
||||
Possible values are:
|
||||
|
||||
* [`authz`](plugins_authorization.md)
|
||||
* [`NetworkDriver`](plugins_network.md)
|
||||
* [`VolumeDriver`](plugins_volume.md)
|
||||
|
||||
|
||||
## Plugin retries
|
||||
|
||||
Attempts to call a method on a plugin are retried with an exponential backoff
|
||||
for up to 30 seconds. This may help when packaging plugins as containers, since
|
||||
it gives plugin containers a chance to start up before failing any user
|
||||
containers which depend on them.
|
||||
|
||||
## Plugins helpers
|
||||
|
||||
To ease plugins development, we're providing an `sdk` for each kind of plugins
|
||||
currently supported by Docker at [docker/go-plugins-helpers](https://github.com/docker/go-plugins-helpers).
|
||||