{"id":13871874,"url":"https://github.com/m-barthelemy/DockerSwift","last_synced_at":"2025-07-16T01:31:58.198Z","repository":{"id":41447492,"uuid":"509612796","full_name":"m-barthelemy/DockerSwift","owner":"m-barthelemy","description":"A Swift client library for Docker","archived":false,"fork":false,"pushed_at":"2023-12-28T21:55:30.000Z","size":495,"stargazers_count":21,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-03-14T22:33:24.310Z","etag":null,"topics":["docker","docker-api","docker-client","docker-library","swift","swift-nio"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m-barthelemy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-01T23:31:34.000Z","updated_at":"2024-07-31T02:57:37.866Z","dependencies_parsed_at":"2023-12-12T23:26:48.676Z","dependency_job_id":"d1728131-f934-482d-ba56-84731f66b426","html_url":"https://github.com/m-barthelemy/DockerSwift","commit_stats":{"total_commits":344,"total_committers":4,"mean_commits":86.0,"dds":0.06395348837209303,"last_synced_commit":"be6949ca4c38b7da2d4828eb3020bb1623eb2c9f"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-barthelemy%2FDockerSwift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-barthelemy%2FDockerSwift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-barthelemy%2FDockerSwift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-barthelemy%2FDockerSwift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m-barthelemy","download_url":"https://codeload.github.com/m-barthelemy/DockerSwift/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226089973,"owners_count":17572112,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-api","docker-client","docker-library","swift","swift-nio"],"created_at":"2024-08-05T23:00:29.026Z","updated_at":"2024-11-23T19:31:21.582Z","avatar_url":"https://github.com/m-barthelemy.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Docker Client\n[![Language](https://img.shields.io/badge/Swift-5.5-brightgreen.svg)](http://swift.org)\n[![Docker Engine API](https://img.shields.io/badge/Docker%20Engine%20API-%20%201.41-blue)](https://docs.docker.com/engine/api/v1.41/)\n[![Platforms](https://img.shields.io/badge/platform-linux--64%20%7C%20osx--64-blue)]()\n\nThis is a low-level Docker Client written in Swift. It very closely follows the Docker API.\n\nIt fully uses the Swift concurrency features introduced with Swift 5.5 (`async`/`await`).\n\n\n## Docker API version support\nThis client library aims at implementing the Docker API version 1.41 (https://docs.docker.com/engine/api/v1.41).\nThis means that it will work with Docker \u003e= 20.10.\n\n\n## Current implementation status\n\n| Section                     | Operation               | Support  | Notes       |\n|-----------------------------|-------------------------|----------|-------------|\n| Client connection           | Local Unix socket       | ✅       |             |\n|                             | HTTP                    | ✅       |             |\n|                             | HTTPS                   | ✅       |             |\n|                             |                         |          |             |\n| Docker daemon \u0026 System info | Ping                    | ✅       |             |\n|                             | Info                    | ✅       |             |\n|                             | Version                 | ✅       |             |\n|                             | Events                  | ✅       |             |\n|                             | Get data usage info     | ✅       |             |\n|                             |                         |          |             |\n| Containers                  | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             | Rename                  | ✅       |             |\n|                             | Start/Stop/Kill         | ✅       |             |\n|                             | Pause/Unpause           | ✅       |             |\n|                             | Get logs                | ✅       |             |\n|                             | Get stats               | ✅       |             |\n|                             | Get processes (top)     | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             | Prune                   | ✅       |             |\n|                             | Wait                    | ✅       |             |\n|                             | Filesystem changes      | ✅       | untested    |\n|                             | Attach                  | ✅       | basic support \u003csup\u003e1\u003c/sup\u003e|\n|                             | Exec                    | ❌       | unlikely \u003csup\u003e2\u003c/sup\u003e|\n|                             | Resize TTY              | ❌       |             |\n|                             |                         |          |             |\n| Images                      | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | History                 | ✅       |             |\n|                             | Pull                    | ✅       | basic support |\n|                             | Build                   | ✅       | basic support |\n|                             | Tag                     | ✅       |             |\n|                             | Push                    | ✅       |             |\n|                             | Create (container commit)| ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             | Prune                   | ✅       |             |\n|                             |                         |          |             |\n| Swarm                       | Init                    | ✅       |             |\n|                             | Join                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Leave                   | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             |                         |          |             |\n| Nodes                       | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             |                         |          |             |\n| Services                    | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Get logs                | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             | Rollback                | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             |                         |          |             |\n| Networks                    | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             | Prune                   | ✅       |             |\n|                             | (Dis)connect container  | ✅       |             |\n|                             |                         |          |             |\n| Volumes                     | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             | Prune                   | ✅       |             |\n|                             |                         |          |             |\n| Secrets                     | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             |                         |          |             |\n| Configs                     | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Create                  | ✅       |             |\n|                             | Update                  | ✅       |             |\n|                             | Delete                  | ✅       |             |\n|                             |                         |          |             |\n| Tasks                       | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Get logs                | ✅       |             |\n|                             |                         |          |             |\n| Plugins                     | List                    | ✅       |             |\n|                             | Inspect                 | ✅       |             |\n|                             | Get Privileges          | ✅       |             |\n|                             | Install                 | ✅       |             |\n|                             | Remove                  | ✅       |             |\n|                             | Enable/disable          | ✅       |             |\n|                             | Upgrade                 | ✅       | untested    |\n|                             | Configure               | ✅       | untested    |\n|                             | Create                  | ❌       | TBD         |\n|                             | Push                    | ❌       | TBD         |\n|                             |                         |          |             |\n| Registries                  | Login                   | ✅       | basic support |\n|                             |                         |          |             |\n| Docker error responses mgmt |                         | 🚧       |             |\n\n\n\n✅ : done or _mostly_ done\n\n🚧 : work in progress, partially implemented, might not work\n\n❌ : not implemented/supported at the moment.\n\nNote: various Docker endpoints such as list or prune support *filters*. These are currently not implemented.\n\n\u003csup\u003e1\u003c/sup\u003e Attach is currently **not** supported when connecting to Docker via local Unix socket, or when using a proxy. It uses the Websocket protocol.\n\n\u003csup\u003e2\u003c/sup\u003e Docker exec is using an unconventional protocol that requires raw access to the TCP socket. Significant work needed in order to support it (https://github.com/swift-server/async-http-client/issues/353).\n\n\n## Installation\n### Package.swift \n```Swift\nimport PackageDescription\n\nlet package = Package(\n    dependencies: [\n        .package(url: \"https://github.com/m-barthelemy/DockerSwift.git\", .branch(\"main\")),\n    ],\n    targets: [\n        .target(name: \"App\", dependencies: [\n            ...\n            .product(name: \"DockerSwift\", package: \"DockerSwift\")\n        ]),\n    ...\n    ]\n)\n```\n\n### Xcode Project\nTo add DockerClientSwift to your existing Xcode project, select File -\u003e Swift Packages -\u003e Add Package Dependancy. \nEnter `https://github.com/m-barthelemy/DockerSwift.git` for the URL.\n\n\n## Usage Examples\n\n### Connect to a Docker daemon\n\nLocal socket (defaults to `/var/run/docker.sock`):\n```swift\nimport DockerSwift\n\nlet docker = DockerClient()\ndefer {try! docker.syncShutdown()}\n```\n\nRemote daemon over HTTP:\n```swift\nimport DockerSwift\n\nlet docker = DockerClient(daemonURL: URL(string: \"http://127.0.0.1:2375\")!)\ndefer {try! docker.syncShutdown()}\n```\n\nRemote daemon over HTTPS, using a client certificate for authentication:\n```swift\nimport DockerSwift\n\nvar tlsConfig = TLSConfiguration.makeClientConfiguration()\ntlsConfig.privateKey = NIOSSLPrivateKeySource.file(\"client-key.pem\")\ntlsConfig.certificateChain.append(NIOSSLCertificateSource.file(\"client-certificate.pem\"))\ntlsConfig.additionalTrustRoots.append(.file(\"docker-daemon-ca.pem\"))\ntlsConfig.certificateVerification = .noHostnameVerification\n\nlet docker = DockerClient(\n    daemonURL: .init(string: \"https://your.docker.daemon:2376\")!,\n    tlsConfig: tlsConfig\n)\ndefer {try! docker.syncShutdown()}\n```\n\n### Docker system info\n\u003cdetails\u003e\n  \u003csummary\u003eGet detailed information about the Docker daemon\u003c/summary\u003e\n  \n  ```swift\n  let info = try await docker.info()\n  print(\"• Docker daemon info: \\(info)\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet versions information about the Docker daemon\u003c/summary\u003e\n  \n  ```swift\n  let version = try await docker.version()\n  print(\"• Docker API version: \\(version.apiVersion)\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eListen for Docker daemon events\u003c/summary\u003e\n  \n  We start by listening for docker events, then we create a container:\n  ```swift\n  async let events = try await docker.events()\n  \n  let container = try await docker.containers.create(\n      name: \"hello\",\n      spec: .init(\n          config: .init(image: \"hello-world:latest\"),\n          hostConfig: .init()\n      )\n  )\n  ```\n  \n  Now, we should get an event whose `action` is \"create\" and whose `type` is \"container\".\n  ```swift\n  for try await event in try await events {\n      print(\"\\n••• event: \\(event)\")\n  }\n  ```\n\u003c/details\u003e\n\n \n### Containers\n\u003cdetails\u003e\n  \u003csummary\u003eList containers\u003c/summary\u003e\n  \n  Add `all: true` to also return stopped containers.\n  ```swift\n  let containers = try await docker.containers.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet a container details\u003c/summary\u003e\n  \n  ```swift\n  let container = try await docker.containers.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreate a container\u003c/summary\u003e\n  \n  \u003e Note: you will also need to start it for the container to actually run.\n  \n  The simplest way of creating a new container is to only specify the image to run:\n  ```swift\n  let spec = ContainerSpec(\n      config: .init(image: \"hello-world:latest\")\n  )\n  let container = try await docker.containers.create(name: \"test\", spec: spec)\n  ```\n  \n  Docker allows customizing many parameters:\n  ```swift\n  let spec = ContainerSpec(\n      config: .init(\n          // Override the default command of the Image\n          command: [\"/custom/command\", \"--option\"],\n          // Add new environment variables\n          environmentVars: [\"HELLO=hi\"],\n          // Expose port 80\n          exposedPorts: [.tcp(80)],\n          image: \"nginx:latest\",\n          // Set custom container labels\n          labels: [\"label1\": \"value1\", \"label2\": \"value2\"]\n      ),\n      hostConfig: .init(\n          // Memory the container is allocated when starting\n          memoryReservation: .mb(64),\n          // Maximum memory the container can use\n          memoryLimit: .mb(128),\n          // Needs to be either disabled (-1) or be equal to, or greater than, `memoryLimit`\n          memorySwap: .mb(128),\n          // Let's publish the port we exposed in `config`\n          portBindings: [.tcp(80): [.publishTo(hostIp: \"0.0.0.0\", hostPort: 8000)]]\n      )\n  )\n  let container = try await docker.containers.create(name: \"nginx-test\", spec: spec)\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eUpdate a container\u003c/summary\u003e\n  \n  Let's update the memory limits for an existing container:\n  ```swift\n  let newConfig = ContainerUpdate(memoryLimit: .mb(64), memorySwap: .mb(64))\n  try await docker.containers.update(\"nameOrId\", spec: newConfig)\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eStart a container\u003c/summary\u003e\n  \n  ```swift\n  try await docker.containers.start(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eStop a container\u003c/summary\u003e\n  \n  ```swift\n  try await docker.containers.stop(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRename a container\u003c/summary\u003e\n  \n  ```swift\n  try await docker.containers.rename(\"nameOrId\", to: \"hahi\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDelete a container\u003c/summary\u003e\n  \n  If the container is running, deletion can be forced by passing `force: true` \n  ```swift\n  try await docker.containers.remove(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet container logs\u003c/summary\u003e\n  \n  \u003e Logs are streamed progressively in an asynchronous way.\n  \n  Get all logs:\n  ```swift\n  let container = try await docker.containers.get(\"nameOrId\")\n        \n  for try await line in try await docker.containers.logs(container: container, timestamps: true) {\n      print(line.message + \"\\n\")\n  }\n  ```\n  \n  Wait for future log messages:\n  ```swift\n  let container = try await docker.containers.get(\"nameOrId\")\n        \n  for try await line in try await docker.containers.logs(container: container, follow: true) {\n      print(line.message + \"\\n\")\n  }\n  ```\n  \n  Only the last 100 messages:\n  ```swift\n  let container = try await docker.containers.get(\"nameOrId\")\n        \n  for try await line in try await docker.containers.logs(container: container, tail: 100) {\n      print(line.message + \"\\n\")\n  }\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAttach to a container\u003c/summary\u003e\n  \n  Let's create a container that defaults to running a shell, and attach to it:\n  ```swift\n  let _ = try await docker.images.pull(byIdentifier: \"alpine:latest\")\n  let spec = ContainerSpec(\n      config: .init(\n          attachStdin: true,\n          attachStdout: true,\n          attachStderr: true,\n          image: \"alpine:latest\",\n          openStdin: true\n      )\n  )\n  let container = try await docker.containers.create(spec: spec)\n  let attach = try await docker.containers.attach(container: container, stream: true, logs: true)\n  \n  // Let's display any output from the container\n  Task {\n      for try await output in attach.output {\n          print(\"• \\(output)\")\n      }\n  }\n  \n  // We need to be sure that the container is really running before being able to send commands to it.\n  try await docker.containers.start(container.id)\n  try await Task.sleep(for: .seconds(1))\n  \n  // Now let's send the command; the response will be printed to the screen.\n  try await attach.send(\"uname\")\n  ```\n\u003c/details\u003e\n  \n\n### Images\n\u003cdetails\u003e\n  \u003csummary\u003eList the Docker images\u003c/summary\u003e\n  \n  ```swift\n  let images = try await docker.images.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet an image details\u003c/summary\u003e\n  \n  ```swift\n  let image = try await docker.images.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ePull an image\u003c/summary\u003e\n  \n  Pull an image from a public repository:\n  ```swift\n  let image = try await docker.images.pull(byIdentifier: \"hello-world:latest\")\n  ```\n\n  Pull an image from a registry that requires authentication:\n  ```swift\n  var credentials = RegistryAuth(username: \"myUsername\", password: \"....\")\n  try await docker.registries.login(credentials: \u0026credentials)\n  let image = try await docker.images.pull(byIdentifier: \"my-private-image:latest\", credentials: credentials)\n  ```\n  \u003e NOTE: `RegistryAuth` also accepts a `serverAddress` parameter in order to use a custom registry.\n  \n  \u003e Creating images from a remote URL or from the standard input is currently not supported.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ePush an image\u003c/summary\u003e\n\n  Supposing that the Docker daemon has an image named \"my-private-image:latest\":\n  ```swift\n  var credentials = RegistryAuth(username: \"myUsername\", password: \"....\")\n  try await docker.registries.login(credentials: \u0026credentials)\n  try await docker.images.push(\"my-private-image:latest\", credentials: credentials)\n  ```\n  \u003e NOTE: `RegistryAuth` also accepts a `serverAddress` parameter in order to use a custom registry.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eBuild an image\u003c/summary\u003e\n  \n  \u003e The current implementation of this library is very bare-bones.\n  \u003e The Docker build context, containing the Dockerfile and any other resources required during the build, must be passed as a TAR archive.\n  \n  Supposing we already have a TAR archive of the build context:\n  ```swift\n  let tar = FileManager.default.contents(atPath: \"/tmp/docker-build.tar\")\n  let buffer = ByteBuffer.init(data: tar)\n  let buildOutput = try await docker.images.build(\n      config: .init(dockerfile: \"./Dockerfile\", repoTags: [\"build:test\"]),\n      context: buffer\n  )\n  // The built Image ID is returned towards the end of the build output\n  var imageId: String!\n  for try await item in buildOutput {\n      if item.aux != nil {\n          imageId = item.aux!.id\n      }\n      else {\n        print(\"\\n• Build output: \\(item.stream)\")\n      }\n  }\n  print(\"\\n• Image ID: \\(imageId)\")\n  ```\n  \n  You can use external libraries to create TAR archives of your build context.\n  Example with [Tarscape](https://github.com/kayembi/Tarscape) (only available on macOS):\n  ```swift\n  import Tarscape\n  \n  let tarContextPath = \"/tmp/docker-build.tar\"\n  try FileManager.default.createTar(\n      at: URL(fileURLWithPath: tarContextPath),\n      from: URL(string: \"file:///path/to/your/context/folder\")!\n  )\n  ```\n\u003c/details\u003e\n\n\n### Networks\n\u003cdetails\u003e\n  \u003csummary\u003eList networks\u003c/summary\u003e\n  \n  ```swift\n  let networks = try await docker.networks.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet a network details\u003c/summary\u003e\n  \n  ```swift\n  let network = try await docker.networks.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreate a network\u003c/summary\u003e\n  \n  Create a new network without any custom options:\n  ```swift\n  let network = try await docker.networks.create(\n    spec: .init(name: \"my-network\")\n  )\n  ```\n  \n  Create a new network with custom IPs range:\n  ```swift\n  let network = try await docker.networks.create(\n      spec: .init(\n          name: \"my-network\",\n          ipam: .init(\n              config: [.init(subnet: \"192.168.2.0/24\", gateway: \"192.168.2.1\")]\n          )\n      )\n  )\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDelete a network\u003c/summary\u003e\n  \n  ```swift\n  try await docker.networks.remove(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eConnect an existing Container to a Network\u003c/summary\u003e\n  \n  ```swift\n  let network = try await docker.networks.create(spec: .init(name: \"myNetwork\"))\n  var container = try await docker.containers.create(\n      name: \"myContainer\",\n      spec: .init(config: .init(image: image.id))\n  )\n  \n  try await docker.networks.connect(container: container.id, to: network.id)\n  ```\n\u003c/details\u003e\n\n\n### Volumes\n\u003cdetails\u003e\n  \u003csummary\u003eList volumes\u003c/summary\u003e\n  \n  ```swift\n  let volumes = try await docker.volumes.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet a volume details\u003c/summary\u003e\n  \n  ```swift\n  let volume = try await docker.volumes.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreate a volume\u003c/summary\u003e\n  \n  ```swift\n  let volume = try await docker.volumes.create(\n    spec: .init(name: \"myVolume\", labels: [\"myLabel\": \"value\"])\n  )\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDelete a volume\u003c/summary\u003e\n  \n  ```swift\n  try await docker.volumes.remove(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\n### Swarm\n\u003cdetails\u003e\n  \u003csummary\u003eInitialize Swarm mode\u003c/summary\u003e\n  \n  ```swift\n  let swarmId = try await docker.swarm.initSwarm()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet Swarm cluster details (inspect)\u003c/summary\u003e\n  \n  \u003e The client must be connected to a Swarm manager node.\n  ```swift\n  let swarm = try await docker.swarm.get()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eMake the Docker daemon to join an existing Swarm cluster\u003c/summary\u003e\n  \n  ```swift\n  // This first client points to an existing Swarm cluster manager\n  let swarmClient = Dockerclient(...)\n  let swarm = try await swarmClient.swarm.get()\n  \n  // This client is the docker daemon we want to add to the Swarm cluster\n  let client = Dockerclient(...)\n  try await client.swarm.join(\n      config: .init(\n          // To join the Swarm cluster as a Manager node\n          joinToken: swarmClient.joinTokens.manager,\n          // IP/Host of the existing Swarm managers\n          remoteAddrs: [\"10.0.0.1\"]\n      )\n  )\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRemove the current Node from the Swarm\u003c/summary\u003e\n  \n  \u003e Note: `force` is needed if the node is a manager\n  ```swift\n  try await docker.swarm.leave(force: true)\n  ```\n\u003c/details\u003e\n\n\n### Nodes\n\u003e This requires a Docker daemon with Swarm mode enabled.\n\u003e Additionally, the client must be connected to a manager node.\n\n\u003cdetails\u003e\n  \u003csummary\u003eList the Swarm nodes\u003c/summary\u003e\n  \n  ```swift\n  let nodes = try await docker.nodes.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRemove a Node from a Swarm\u003c/summary\u003e\n  \n  \u003e Note: `force` is needed if the node is a manager\n  ```swift\n  try await docker.nodes.delete(id: \"xxxxxx\", force: true)\n  ```\n\u003c/details\u003e\n\n\n### Services\n\u003e This requires a Docker daemon with Swarm mode enabled.\n\u003e Additionally, the client must be connected to a manager node.\n\n\u003cdetails\u003e\n  \u003csummary\u003eList services\u003c/summary\u003e\n  \n  ```swift\n  let services = try await docker.services.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet a service details\u003c/summary\u003e\n  \n  ```swift\n  let service = try await docker.services.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreate a service\u003c/summary\u003e\n  \n  Simplest possible example, we only specify the name of the service and the image to use:\n  ```swift\n  let spec = ServiceSpec(\n      name: \"my-nginx\",\n      taskTemplate: .init(\n          containerSpec: .init(image: \"nginx:latest\")\n      )\n  )\n  let service = try await docker.services.create(spec: spec)\n  ```\n  \n  Let's specify a number of replicas, a published port and a memory limit of 64MB for our service:\n  ```swift\n  let spec = ServiceSpec(\n      name: \"my-nginx\",\n      taskTemplate: .init(\n          containerSpec: .init(image: \"nginx:latest\"),\n          resources: .init(\n              limits: .init(memoryBytes: .mb(64))\n          ),\n          // Uses default Docker routing mesh mode\n          endpointSpec: .init(ports: [.init(name: \"HTTP\", targetPort: 80, publishedPort: 8000)])\n      ),\n      mode: .replicated(2)\n  )\n  let service = try await docker.services.create(spec: spec)\n  ```\n  \n  What if we then want to know when our service is fully running?\n  ```swift\n  var index = 0 // Keep track of how long we've been waiting\n  repeat {\n      try await Task.sleep(for: .seconds(1))\n      print(\"\\n Service still not fully running!\")\n      index += 1\n  } while try await docker.tasks.list()\n        .filter({$0.serviceId == service.id \u0026\u0026 $0.status.state == .running})\n        .count \u003c 1 /* number of replicas */ \u0026\u0026 index \u003c 15\n  print(\"\\n Service is fully running!\")\n  ```\n  \n  What if we want to create a one-off job instead of a service?\n  ```swift\n  let spec = ServiceSpec(\n      name: \"hello-world-job\",\n      taskTemplate: .init(\n          containerSpec: .init(image: \"hello-world:latest\"),\n          ...\n      ),\n      mode: .job(1)\n  )\n  let job = try await docker.services.create(spec: spec)\n  ```\n  \n  \u003cbr/\u003e\n  \n  Something more advanced? Let's create a Service:\n  - connected to a custom Network\n  - storing data into a custom Volume, for each container\n  - requiring a Secret\n  - publishing the port 80 of the containers to the port 8000 of each Docker Swarm node\n  - getting restarted automatically in case of failure\n  ```swift\n  let network = try await docker.networks.create(spec: .init(name: \"myNet\", driver: \"overlay\"))\n  let secret = try await docker.secrets.create(spec: .init(name: \"myPassword\", value: \"blublublu\"))\n  let spec = ServiceSpec(\n      name: \"my-nginx\",\n      taskTemplate: .init(\n          containerSpec: .init(\n              image: \"nginx:latest\",\n              // Create and mount a dedicated Volume named \"myStorage\" on each running container. \n              mounts: [.volume(name: \"myVolume\", to: \"/mnt\")],\n              // Add our Secret. Will appear as `/run/secrets/myPassword` in the containers.\n              secrets: [.init(secret)]\n          ),\n          resources: .init(\n              limits: .init(memoryBytes: .mb(64))\n          ),\n          // If a container exits or crashes, replace it with a new one.\n          restartPolicy: .init(condition: .any, delay: .seconds(2), maxAttempts: 2)\n      ),\n      mode: .replicated(1),\n      // Add our custom Network\n      networks: [.init(target: network.id)],\n      // Publish our Nginx image port 80 to 8000 on the Docker Swarm nodes\n      endpointSpec: .init(ports: [.init(name: \"HTTP\", targetPort: 80, publishedPort: 8000)])\n  )\n    \n  let service = try await docker.services.create(spec: spec)\n  ```\n\u003c/details\u003e\n \n\u003cdetails\u003e\n  \u003csummary\u003eUpdate a service\u003c/summary\u003e\n  \n  Let's scale an existing service up to 3 replicas:\n  ```swift\n  let service = try await docker.services.get(\"nameOrId\")\n  var updatedSpec = service.spec\n  updatedSpec.mode = .replicated(3)\n  try await docker.services.update(\"nameOrId\", spec: updatedSpec)\n  ```\n\u003c/details\u003e\n       \n\u003cdetails\u003e\n  \u003csummary\u003eGet service logs\u003c/summary\u003e\n  \n  \u003e Logs are streamed progressively in an asynchronous way.\n  \n  Get all logs:\n  ```swift\n  let service = try await docker.services.get(\"nameOrId\")\n        \n  for try await line in try await docker.services.logs(service: service) {\n      print(line.message + \"\\n\")\n  }\n  ```\n  \n  Wait for future log messages:\n  ```swift\n  let service = try await docker.services.get(\"nameOrId\")\n        \n  for try await line in try await docker.services.logs(service: service, follow: true) {\n      print(line.message + \"\\n\")\n  }\n  ```\n  \n  Only the last 100 messages:\n  ```swift\n  let service = try await docker.services.get(\"nameOrId\")\n        \n  for try await line in try await docker.services.logs(service: service, tail: 100) {\n      print(line.message + \"\\n\")\n  }\n  ```\n  \n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRollback a service\u003c/summary\u003e\n  \n  Suppose that we updated our existing service configuration, and something is not working properly.\n  We want to revert back to the previous, working version.\n  ```swift\n  try await docker.services.rollback(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDelete a service\u003c/summary\u003e\n  \n  ```swift\n  try await docker.services.remove(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\n### Secrets\n\u003e This requires a Docker daemon with Swarm mode enabled.\n\u003e \n\u003e Note: The API for managing Docker Configs is very similar to the Secrets API and the below examples also apply to them.\n\n\u003cdetails\u003e\n  \u003csummary\u003eList secrets\u003c/summary\u003e\n  \n  ```swift\n  let secrets = try await docker.secrets.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGet a secret details\u003c/summary\u003e\n  \n  \u003e Note: The Docker API doesn't return secret data/values.\n  \n  ```swift\n  let secret = try await docker.secrets.get(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreate a secret\u003c/summary\u003e\n  \n  Create a Secret containing a `String` value:\n  ```swift\n  let secret = try await docker.secrets.create(\n    spec: .init(name: \"mySecret\", value: \"test secret value 💥\")\n  )\n  ```\n  \n  You can also pass a `Data` value to be stored as a Secret:\n  ```swift\n  let data: Data = ...\n  let secret = try await docker.secrets.create(\n    spec: .init(name: \"mySecret\", data: data)\n  )\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eUpdate a secret\u003c/summary\u003e\n  \n  \u003e Currently, only the `labels` field can be updated (Docker limitation).\n  \n  ```swift\n  try await docker.secrets.update(\"nameOrId\", labels: [\"myKey\": \"myValue\"])\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDelete a secret\u003c/summary\u003e\n  \n  ```swift\n  try await docker.secrets.remove(\"nameOrId\")\n  ```\n\u003c/details\u003e\n\n\n### Plugins\n\u003cdetails\u003e\n  \u003csummary\u003eList installed plugins\u003c/summary\u003e\n  \n  ```swift\n  let plugins = try await docker.plugins.list()\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eInstall a plugin\u003c/summary\u003e\n  \n  \u003e Note: the `install()` method can be passed a `credentials` parameter containing credentials for a private registry.\n  \u003e See \"Pull an image\" for more information.\n  ```swift\n  // First, we fetch the privileges required by the plugin:\n  let privileges = try await docker.plugins.getPrivileges(\"vieux/sshfs:latest\")\n  \n  // Now, we can install it\n  try await docker.plugins.install(remote: \"vieux/sshfs:latest\", privileges: privileges)\n  \n  // finally, we need to enable it before using it\n  try await docker.plugins.enable(\"vieux/sshfs:latest\")\n  ```\n\u003c/details\u003e\n\n## Credits\nThis is a fork of the great work at https://github.com/alexsteinerde/docker-client-swift\n\n## License\nThis project is released under the MIT license. See [LICENSE](LICENSE) for details.\n\n\n## Contribute\nYou can contribute to this project by submitting a detailed issue or by forking this project and sending a pull request. Contributions of any kind are very welcome :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-barthelemy%2FDockerSwift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm-barthelemy%2FDockerSwift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-barthelemy%2FDockerSwift/lists"}