app icon indicating copy to clipboard operation
app copied to clipboard

Installed apps show up as stacks

Open thaJeztah opened this issue 6 years ago • 8 comments

Apps that were installed with docker app install show up both as app, and as stack;

docker app ls
INSTALLATION   APPLICATION        LAST ACTION RESULT  CREATED    MODIFIED  REFERENCE
myinstallation myotherapp (0.1.0) upgrade     success 12 minutes 8 minutes 

docker stack ls
NAME                SERVICES            ORCHESTRATOR
myinstallation      1                   Swarm
mystack             1                   Swarm

Do we want stacks and apps to work in the same "namespace"? Or should we prevent users from interacting with apps through docker stack xxx commands (and vice-versa)?

I guess there's two possible angles;

  1. apps and stacks are separate things
  2. apps and stacks form a hierarchy; an app consists of 1 (or perhaps in future more than 1) stacks (and stacks consist of 1 or more services, volumes, etc.)

If 2., then stacks that are part of an app should likely show up under docker stack ls, but we should think how users can/are allows to interact with them.

I think in both cases, we should add additional metadata/labels to (both stacks, and) apps so that we can distinguish apps from stacks, allowing use to filter and/or provide info about the stack/app separate from the local storage in ~/.docker/apps.

thaJeztah avatar Sep 27 '19 11:09 thaJeztah

Note that adding additional metadata/labels to the deployed apps would also help with https://github.com/docker/app/issues/604

Looking at the information stored (~/.docker/app/installations/37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f/myinstallation.json)

  • 37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f could be stored as ID (e.g. com.docker.app.id)
  • myinstallation is the installation name, which is already stored as com.docker.stack.namespace, but we may want to store that as a "docker app" specific label as well (com.docker.app.name ?)

From the myinstallation.json (shown below, collapsed);

{
  "name": "myinstallation",
  "revision": "01DNS4S9HPYSTS1FCG77WVJCXT",
  "created": "2019-09-27T12:34:06.685081+02:00",
  "modified": "2019-09-27T12:38:08.950407+02:00",
  "bundle": {
    "name": "myotherapp",
    "version": "0.1.0",
    "description": "",
    "maintainers": [
      {
        "name": "sebastiaan",
        "email": "[email protected]"
      }
    ],
    "invocationImages": [
      {
        "imageType": "docker",
        "image": "myotherapp:0.1.0-invoc"
      }
    ],
    "images": {
      "hello": {
        "imageType": "docker",
        "image": "hashicorp/http-echo",
        "description": "hashicorp/http-echo"
      }
    },
    "actions": {
      "com.docker.app.inspect": {
        "stateless": true
      },
      "com.docker.app.render": {
        "stateless": true
      },
      "com.docker.app.status": {}
    },
    "parameters": {
      "com.docker.app.kubernetes-namespace": {
        "type": "string",
        "default": "",
        "metadata": {
          "description": "Namespace in which to deploy"
        },
        "destination": {
          "env": "DOCKER_KUBERNETES_NAMESPACE"
        },
        "apply-to": [
          "install",
          "upgrade",
          "uninstall",
          "com.docker.app.status"
        ]
      },
      "com.docker.app.orchestrator": {
        "type": "string",
        "default": "",
        "allowedValues": [
          "",
          "swarm",
          "kubernetes"
        ],
        "metadata": {
          "description": "Orchestrator on which to deploy"
        },
        "destination": {
          "env": "DOCKER_STACK_ORCHESTRATOR"
        },
        "apply-to": [
          "install",
          "upgrade",
          "uninstall",
          "com.docker.app.status"
        ]
      },
      "com.docker.app.render-format": {
        "type": "string",
        "default": "yaml",
        "allowedValues": [
          "yaml",
          "json"
        ],
        "metadata": {
          "description": "Output format for the render command"
        },
        "destination": {
          "env": "DOCKER_RENDER_FORMAT"
        },
        "apply-to": [
          "com.docker.app.render"
        ]
      },
      "com.docker.app.share-registry-creds": {
        "type": "bool",
        "default": false,
        "metadata": {
          "description": "Share registry credentials with the invocation image"
        },
        "destination": {
          "env": "DOCKER_SHARE_REGISTRY_CREDS"
        }
      },
      "hello.port": {
        "type": "string",
        "default": "8080",
        "destination": {
          "env": "docker_param1"
        }
      },
      "hello.text": {
        "type": "string",
        "default": "Hello myotherapp!",
        "destination": {
          "env": "docker_param2"
        }
      }
    },
    "credentials": {
      "com.docker.app.registry-creds": {
        "path": "/cnab/app/registry-creds.json"
      },
      "docker.context": {
        "path": "/cnab/app/context.dockercontext"
      }
    }
  },
  "result": {
    "message": "",
    "action": "upgrade",
    "status": "success"
  },
  "parameters": {
    "com.docker.app.kubernetes-namespace": "default",
    "com.docker.app.orchestrator": "",
    "com.docker.app.render-format": "yaml",
    "com.docker.app.share-registry-creds": false,
    "hello.port": "8080",
    "hello.text": "Hello myapp!"
  },
  "files": null
}
  • name (already mentioned above), revision, created, modified could be good candidates for labels (com.docker.app.<property>)

Possibly;

  • store standard parameters as labels (com.docker.app.kubernetes-namespace ?)
  • not sure about the custom parameters, as they may contain sensitive data. If not, they could be stored as com.docker.app.parameters.<name-of-parameter>

thaJeztah avatar Sep 27 '19 11:09 thaJeztah

/cc @chris-crone @silvin-lubecki

thaJeztah avatar Sep 27 '19 11:09 thaJeztah

Hm, actually, looks like the 37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f is not an ID (or at least, the same ID is created when re-deploying the application after removing the local store); is it a hash of the name, not a UUID/random ID?

thaJeztah avatar Sep 27 '19 11:09 thaJeztah

So, looks like interacting through docker stack is indeed problematic, because docker app currently relies on the local store;

$ docker stack rm myinstallation
Removing service myinstallation_hello
Removing network myinstallation_default

$ docker app ls
INSTALLATION   APPLICATION        LAST ACTION RESULT  CREATED   MODIFIED       REFERENCE
myinstallation myotherapp (0.1.0) upgrade     success 7 minutes About a minute 

$ docker app status myinstallation
INSTALLATION
------------
Name:         myinstallation
Created:      10 minutes
Modified:     4 minutes
Revision:     01DNS7WG2EJP1Q1KTM1DATP5SD
Last Action:  upgrade
Result:       SUCCESS
Orchestrator: swarm

APPLICATION
-----------
Name:      myotherapp
Version:   0.1.0
Reference: 

PARAMETERS
----------
hello.port: 8080
hello.text: Hello myapp!

STATUS
------

thaJeztah avatar Sep 27 '19 11:09 thaJeztah

@thaJeztah your last result is weird, status should have failed, not being able to reach the rmed stack.

silvin-lubecki avatar Sep 27 '19 11:09 silvin-lubecki

37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f could be stored as ID (e.g. com.docker.app.id)

Actually 37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f is the id of the installation context 😅 The installation store is split by context ids, and inside you will find all the named installations.

silvin-lubecki avatar Sep 27 '19 11:09 silvin-lubecki

Ah! Gotcha 👍 Guess having a GUID stored somewhere would work for IDs

thaJeztah avatar Sep 27 '19 12:09 thaJeztah

At a high level, I like the idea of 2 where an app consists of one or more stacks. But, I feel that might lead to confusion about apps vs stacks.

I think labeling app-based deployments so that existing stack/service commands can work with them would ease adoption, and make them interoperable with third-party tools like Portainer out of the box.

Perhaps a bigger gain for apps and stacks as a whole would be to create a resource type and APIs for it (as a combined entity). Right now, there is no actual stack resource in the Docker API. The concept of stacks only exist in the Docker CLI. A new resource type could hold the information that's currently being stored locally in ~/.docker/app/installations/, and finally provide an API that external tools can use.

kinghuang avatar Sep 27 '19 19:09 kinghuang