Docker · Arazzo Workflow

Docker Roll a Swarm Service Onto a New Image

Version 1.0.0

Read a service's current version, update it to a new image, watch the tasks reconverge, and tail the service logs.

1 workflow 1 source API 1 provider
View Spec View on GitHub CloudContainersDevOpsInfrastructureMicroservicesArazzoWorkflows

Provider

docker

Workflows

rolling-update-service
Update a running swarm service to a new image using its current version index.
Inspects the service to obtain its current spec and version index, submits an updated spec pinned to that version so a concurrent write is rejected rather than lost, then lists tasks and tails logs to confirm the rollout.
5 steps inputs: newImage, parallelism, registryAuth, replicas, serviceName, tail, updateDelay outputs: previousImage, runningImage, serviceId, updateStatus
1
inspectService
ServiceInspect
Read the service's current spec and version index. The version index is required by the update call — it is what makes the write conditional on nobody else having changed the service in the meantime.
2
updateService
ServiceUpdate
Submit the updated spec pinned to the version index read above, rolling tasks onto the new image start-first so capacity is never dipped below the target during the update.
3
watchRollout
TaskList
List the service's tasks desired to be running so the caller can watch the new tasks come up and the old ones drain during the rolling update.
4
confirmUpdateState
ServiceInspect
Read the service back to check the update status the swarm reports. A state of "completed" means the rollout landed; "paused" or "rolling_back" means it tripped the failure action.
5
tailServiceLogs
ServiceLogs
Tail the aggregated logs across the service's tasks with timestamps, so a failed rollout can be diagnosed without hunting for individual containers.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Docker Roll a Swarm Service Onto a New Image
  summary: Read a service's current version, update it to a new image, watch the tasks reconverge, and tail the service logs.
  description: >-
    The deploy step of a swarm pipeline, and a textbook optimistic-concurrency
    flow. ServiceUpdate requires the version index the service carried *before* the
    update, so the read-back is mandatory rather than a nicety — skipping it is how
    concurrent deploys clobber each other. The workflow inspects the service, sends
    the updated spec with that version, lists the tasks to watch the rollout, and
    tails the service logs. Every step spells out its request inline so the flow can
    be read and executed without opening the underlying OpenAPI description.
  version: 1.0.0
sourceDescriptions:
- name: dockerEngineApi
  url: ../openapi/docker-openapi.yml
  type: openapi
workflows:
- workflowId: rolling-update-service
  summary: Update a running swarm service to a new image using its current version index.
  description: >-
    Inspects the service to obtain its current spec and version index, submits an
    updated spec pinned to that version so a concurrent write is rejected rather
    than lost, then lists tasks and tails logs to confirm the rollout.
  inputs:
    type: object
    required:
    - serviceName
    - newImage
    - replicas
    properties:
      serviceName:
        type: string
        description: ID or name of the service to update.
      newImage:
        type: string
        description: New image to roll out, ideally pinned by digest.
      replicas:
        type: integer
        description: Desired replica count after the update.
      parallelism:
        type: integer
        description: How many tasks to update simultaneously.
      updateDelay:
        type: integer
        description: Nanoseconds to wait between updating task batches.
      registryAuth:
        type: string
        description: Base64url-encoded auth configuration for pulling from a private registry.
      tail:
        type: string
        description: Number of log lines to return from the end of the service logs, or "all".
  steps:
  - stepId: inspectService
    description: >-
      Read the service's current spec and version index. The version index is
      required by the update call — it is what makes the write conditional on
      nobody else having changed the service in the meantime.
    operationId: ServiceInspect
    parameters:
    - name: id
      in: path
      value: $inputs.serviceName
    - name: insertDefaults
      in: query
      value: true
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      serviceId: $response.body#/ID
      versionIndex: $response.body#/Version/Index
      currentSpec: $response.body#/Spec
      currentImage: $response.body#/Spec/TaskTemplate/ContainerSpec/Image
  - stepId: updateService
    description: >-
      Submit the updated spec pinned to the version index read above, rolling tasks
      onto the new image start-first so capacity is never dipped below the target
      during the update.
    operationId: ServiceUpdate
    parameters:
    - name: id
      in: path
      value: $steps.inspectService.outputs.serviceId
    - name: version
      in: query
      value: $steps.inspectService.outputs.versionIndex
    - name: registryAuthFrom
      in: query
      value: spec
    - name: X-Registry-Auth
      in: header
      value: $inputs.registryAuth
    requestBody:
      contentType: application/json
      payload:
        Name: $inputs.serviceName
        TaskTemplate:
          ContainerSpec:
            Image: $inputs.newImage
          RestartPolicy:
            Condition: on-failure
            MaxAttempts: 3
        Mode:
          Replicated:
            Replicas: $inputs.replicas
        UpdateConfig:
          Parallelism: $inputs.parallelism
          Delay: $inputs.updateDelay
          FailureAction: rollback
          Order: start-first
          Monitor: 15000000000
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      warnings: $response.body#/Warnings
  - stepId: watchRollout
    description: >-
      List the service's tasks desired to be running so the caller can watch the
      new tasks come up and the old ones drain during the rolling update.
    operationId: TaskList
    parameters:
    - name: filters
      in: query
      value: '{"service": ["$inputs.serviceName"], "desired-state": ["running"]}'
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      tasks: $response.body
  - stepId: confirmUpdateState
    description: >-
      Read the service back to check the update status the swarm reports. A state
      of "completed" means the rollout landed; "paused" or "rolling_back" means it
      tripped the failure action.
    operationId: ServiceInspect
    parameters:
    - name: id
      in: path
      value: $steps.inspectService.outputs.serviceId
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      updateStatus: $response.body#/UpdateStatus
      newVersionIndex: $response.body#/Version/Index
      runningImage: $response.body#/Spec/TaskTemplate/ContainerSpec/Image
  - stepId: tailServiceLogs
    description: >-
      Tail the aggregated logs across the service's tasks with timestamps, so a
      failed rollout can be diagnosed without hunting for individual containers.
    operationId: ServiceLogs
    parameters:
    - name: id
      in: path
      value: $steps.inspectService.outputs.serviceId
    - name: stdout
      in: query
      value: true
    - name: stderr
      in: query
      value: true
    - name: timestamps
      in: query
      value: true
    - name: details
      in: query
      value: true
    - name: follow
      in: query
      value: false
    - name: tail
      in: query
      value: $inputs.tail
    successCriteria:
    - condition: $statusCode == 200
  outputs:
    serviceId: $steps.inspectService.outputs.serviceId
    previousImage: $steps.inspectService.outputs.currentImage
    runningImage: $steps.confirmUpdateState.outputs.runningImage
    updateStatus: $steps.confirmUpdateState.outputs.updateStatus