docker-swarm plugin

The Docker[^1] Swarm plugin provides instance deployment and operations using services in Docker Swarm and using the "stack" namespace separation for applications.

For easiest configuration and reduced failure modes, it is best to run Skopos on the same cluster where the application runs, with the docker socket directory-mapped on the master node (see the Installing Skopos document for command examples). For advanced configurations (e.g., Skopos accessing the swarm cluster remotely), please contact our technical support.

Quick jump to Configuration.

[^1]: All product and company names are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Compatibility

Docker Swarm type and engine version

The Skopos docker-swarm plugin requires Docker engine version 1.13 or later (tested with 17.03, API version 1.26) in swarm mode.

It is possible to use it on a single-node swarm (equivalent to just plain docker but with the service, stack and vip functionality) and on a multi-node swarm cluster.

This version does not support the older Docker Swarm cluster or swarm-kit configurations.

For easiest configuration and reduced failure modes, it is best to run Skopos on the same cluster as the application, with access to the docker socket on the master node. For advanced configurations (e.g., Skopos accessing the swarm cluster remotely), please contact our technical support.

Compatibility with Docker service and stack commands

The Docker Swarm plugin for Skopos uses the native Docker API for creating instances as Docker Swarm services. Applications and services deployed with the docker-swarm plugin for Skopos are fully interoperable with services created using docker service create and stacks created with docker stack deploy. Also services and apps deployed by Skopos can be manipulated with the corresponding Docker commands and vice-versa (of course, it is not a good idea to make modifications with both at the same time). The Skopos project name corresponds to the Docker stack name.

Importing docker-compose files

Skopos also supports the versions 2 and 3 of the Docker Compose files; they can be used instead of native Skopos models. Labels can optionally be used to provide some Skopos-specific service attributes, such as stateful, singleton and the visual position in the architecture model view. Importing docker-compose files is further described in the Importing Docker Compose files topic.

This provides the easiest method to import existing docker-compose or stack projects into Skopos. If you don't have a docker-compose file, consider using our model discovery tool (contact our support) or creating the model YAML manifest manually (this is easy and we will be glad to help).

Mapping Volumes

Connecting volumes to services is supported with the docker-swarm plugin.

There are 3 ways to provide backing for a logical volume referenced from the model:

  • docker volume named <project>_<logicalvolume> is the default name that will be attempted unless the logical volume name has been mapped (see volumes map below). This is the recommended naming convention which does not require further configuration and matches the service naming convention.
  • docker volume mapped in the volume map in the target environment file
  • host directory mapped in the volume map in the target environment file. Note that in multi-node clusters placement constraints may need to be used for the service to be placed on the node(s) that provide these directories (however, this setting is very useful in single-node development and testing clusters).

Plugin-specific component attributes

This plugin supports the following plugin-specific attributes of components in the Skopos model:

components:
  web:
    image: opsani/sample-back

    provides:
      ports:
        - "8080/tcp"
    visual: { x: 350, y: 200 }

    plugin:
      docker-swarm:
        command: ['bash']
        args: ['-c', 'ls']
        default_network: true
        networks:
          - target: my_global_net1      # no alias
          - target: ${global_network}   # example using target env file var
            alias: back22               # single alias
          - target: my_global_net3
            Aliases: ['back', 'web', 'back22']  # raw attribute
        endpoint_mode: dnsrr
        cpu_reservation: 1
        cpu_limit: 2
        mem_reservation: 300m
        mem_limit: 1g
        secrets:
          - file: secret1.txt
            secret: secret1.dev
          - file: key.pem
            gid: "0"
            uid: "0"
            mode: 0x440               # no access to others
            secret: ${web_secret}     # pull name from env vars ('~' to disable)
        raw:
          Mode:
            Global: {}  # set global replication mode
          TaskTemplate:
            Placement:
              Constraints: ["node.role==manager"]

Details:

  • command - override the container command (list of strings)
  • args - provide additional arguments to the container (list of strings)
  • default_network - whether to attach to the default project network (default: true)
  • networks - networks to connect to (in addition or instead of the default project network). List with attributes, target is network's name, alias is an optional DNS short name for that network. Other attributes, if any, will be passed as-is (raw) to Docker
  • endpoint_mode - override the endpoint mode, vip (default) or dnsrr (other values may be specified if/when supported by Docker)
  • cpu_reservation - reserve CPUs (default 0.000)
  • cpu_limit - limit CPUs (default no limit)
  • mem_reservation - reserve memory (default 0), in bytes. Supports m and g suffixes, e.g., 300m or 1g
  • mem_limit - reserve memory (default no limit), in bytes. Supports m and g suffixes, e.g., 300m or 1g
  • secrets - list of secrets to expose to the service. Each element is a map with file (filename to expose under /run/secrets/) and secret (Docker secret's name). By default files are owned by root:root and have permissions mode 444; optional attributes gid, uid and mode can override the defaults. If the secret value is set to the YAML null value or the string "~", the secret will not be exposed to the service (disabled). The secret name can be varied across environments using variable substitution.
  • raw - attributes to override settings in the low-level Docker API object ServiceSpec. Fields may not be overridden if they are already defined through the Skopos model (e.g., Name). Exceptions are made for RestartPolicy, Mode (setting to global), UpdateConfig, which are allowed to override default values set by Skopos.

Note: the raw settings may cause the docker-swarm plugin to malfunction due to unexpected behavior caused by specific settings (e.g., changing FailureAction in UpdateConfig)

Note: for port-specific endpoint settings, see gateway's plugin-specific attributes

Gateways

Both Skopos ingress gateway types, load_balancer and host_port are automatically mapped to Docker Swarm service endpoints.

The docker-swarm plugin will not enforce that host_port gateways have only a single target. However, we recommend using this gateway type for single replicas, and using the load_balancer gateway type to expose services that are provided by multiple replicas. This will ensure future compatibility (i.e., if the plugin starts enforcing the single replica constraint) and will allow using the same model with the docker plugin (e.g., on development systems that don't have swarm mode support).

When running Docker Swarm on Amazon EC2, the recommended approach for exposing replicated services is by using ELB load balancer that has all swarm nodes as a target and leaving the Docker Swarm routing mesh to direct the traffic to the right node and instance.

Currently, there are no custom load balancer plugins that work with the docker-swarm plugin (load balancing is automatically provided with Docker Swarm for services exposed via a load_balancer gateway)

Plugin-specific attributes for gateways

Gateways support the following docker swarm-specific parameters:

  • publish_mode - port publishing mode, ingress(default) or host (useful primarily for globally replicated services; see overview and bugs)
  • raw - raw port settings, allowing direct API-level attributes for the EndpointPortConfig API object (inside ServiceSpec.EndpointSpec); the raw attribute can override settings already defined elsewhere and "wins" over them (e.g., PublishedPort). There are currently no known parameters that are not already set by Skopos; it is provided for any future API extensions by Docker

Note 1: These settings apply to all ports of the gateway

Note 2: The endpoint mode (vip vs. dnsrr) can be set in the component plugin settings.

Example:

components:
  web:
    provides:
      ports:
        - "8080/tcp"
    # ...
#...
gateways:
  in:
    type: host_port
    target: [ web ]
    exposes:
      - name: http
        port: 8081/tcp
        target_port: 8080
    plugin:
      docker-swarm:
        publish_mode: host
        raw:
          PublishedPort: 8000   # overrides port '8081/tcp' with '8000'

Service Discovery

Service discovery is always included with Docker Swarm. There is no need to specify service_discovery_plugin or service_discovery_auto. Note that currently, it is not possible to replace or append service discovery steps (see supported injection points below).

Known Limitations

The following known limitations exist in the current version of the docker-swarm plugin for Skopos. Please contact our support if you have further questions or are constrained by one or more of these limitations.

  • By default, the docker-swarm plugin creates a project-specific network named <project>_default (where is the name of the project) with type overlay and scope swarm. If the network already exists, it will be left alone (e.g., if you want to use different drivers and network plugins).
  • Only the following step injection points are supported in the model lifecycle with the docker-swarm plugin (all other injection points are silently ignored if present):
  • application level: preflight and postflight
  • component level: pre_component, post_component and quality_gate (the pre-component and post-component steps are invoked once; the quality gate steps are invoked once per new instance).

Configuration

All configuration for this plugin is optional and may be omitted.

A detailed configuration may look something like this:

core_plugin: docker-swarm

plugin_config:
  docker-swarm:
    ipv6: true
    timeout: 300
    update_monitor: 10
    api_ver: 1.26
    local_images_only: false
    insecure_registries: false
    volumes:
      db: { from: "/var/lib/mysql" }  # host directory mapped
      html: { from: "www-vol" }     # docker volume

The following configuration settings may be provided when desired:

ipv6

ipv6 is a boolean that determines whether to enable IPv6 when creating the application networks (implicitly or by calling network_create action). This setting has no effect on networks that already exist. Supported values are true and false (default).

Example:

plugin_config:
  docker-swarm:
    ipv6: true

timeout

timeout is the timeout, in seconds, to wait either for the deployed service to become operational or for a change in the service's set of running tasks. As such, this timeout rolls forward during the deployment and will only fail if there is no forward progress and no completion during its period. The default is 60 seconds.

Example:

plugin_config:
  docker-swarm:
    timeout: 300

update_monitor

update_monitor is the period in seconds during which all running tasks must remain stable in their target (updated) states in order to consider an update operation to be completed. The default is 5 seconds.

Example:

plugin_config:
  docker-swarm:
    update_monitor: 10

api_ver

api_ver is the Docker API version that Skopos should specify when calling the Docker API. The default is 1.26 (the minimum compatible version).

Example:

plugin_config:
  docker-swarm:
    api_ver: 1.26

local_images_only

local_images_only can be used to disable calling remote image registries to check image versions and will also not monitor remote registries for newer versions of any of the images that are running. Supported values are true and false (default).

Setting this to true is suitable for development on a single-node swarm cluster where images are built locally and not pushed to a remote registry.

This setting should not be enabled on multi-node clusters or when needing images from a remote image repository (Docker Hub or private).

Example:

plugin_config:
  docker-swarm:
    local_images_only: false

insecure_registries

insecure_registries can be used to allow the plugin to fall back to insecure connection if it fails to establish a secure one to an image registry when checking the metadata of an image (e.g., tags and digests). Note that this setting does not allow images to be pulled from insecure registries (this is a setting of the docker engine, see https://docs.docker.com/registry/insecure/)

This setting shoult not be enabled in production environments or when the registry access is not secured in an alternate way.

This setting has no impact if local_images_only is true.

Example:

plugin_config:
  docker-swarm:
    insecure_registries: true  # allow fallback to non-SSL for image check

volumes

volumes is a configuration a map that defines the location of data for volumes used by the application. See the Mapping Volumes section for an overview of supported volume options.

The map format is:

volumes:
  <logical-volume-name>:
    from: <path_or_volume>
  ...

Each <logical-volume-name> corresponds to a volume name as used in the application model.

The <path_or_volume> is either an absolute file/directory path accessible to the Docker engine or the name of a Docker volume object (e.g., as shown by the Docker CLI command docker volume ls).

If a volume X is referred to in the application model that isn't in this map, and the project name is Y, it is treated as if an entry in the form X: { from: Y_X } were found in the map (i.e., the logical name in the model is simply used as the Docker volume object name prepended by the project name). If all the application's volumes are pre-existing Docker volume objects fitting this convention, the entire volumes configuration map can be omitted (recommended).

Note: This behavior is consistent with the default volume naming with the docker plugin

Example:

plugin_config:
  docker-swarm:
    volumes:
      db: { from : "/var/lib/mysql" }  # host directory mapped
      html: { from: "www-vol" }      # docker volume

You can also disable a volume by setting its from value to ~; this will leave the original container directory and not mount any volumes or host directories. The ~ value can be represented in one of three ways:

  • The YAML constant ~
  • The YAML constant null
  • The string value "~"

Example:

plugin_config:
  docker-swarm:
    volumes:
      db: { from : "~" }             # use container directory for testing (destroyed with container)
      html: { from: "www-vol" }      # docker volume