Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Portainer HTTP API by example

DEPRECATION NOTICE

This gist is now deprecated in favor of our official documentation: https://documentation.portainer.io/api/api-examples/ which contains up to date examples!

THE FOLLOWING DOCUMENTATION IS DEPRECATED

Please refer to the link above to get access to our updated API documentation and examples.

Introduction

This document presents a simple way to manage your Docker resource by using Portainer as a gateway (HTTP queries against the Portainer API).

The API documentation is available here: https://app.swaggerhub.com/apis/deviantony/portainer/

WARNING: This documentation is valid for Portainer >= 1.18.0.

NOTE: I'm using httpie to execute HTTP queries from the CLI.

Deploy a Portainer instance

# Note: I'm bind-mouting the Docker socket to be able to manage the local engine where Portainer is running.
# You can skip the bind-mount if you want to manage a remote environment.

$ docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

Initialize the admin password

$ http POST :9000/api/users/admin/init Username="admin" Password="adminpassword"

Authenticate against the API using the admin account

$ http POST :9000/api/auth Username="admin" Password="adminpassword"

The response is a JSON object containing the JWT token inside the jwt field:

{
  "jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"
}

You need to retrieve this token. You will need to pass this token inside the Authorization header when executing an authentication query against the API.

The value of the Authorization header must be of the form Bearer <JWT_TOKEN>.

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE

NOTE: This token has a 8 hour validity, you'll need to generate another token to execute authenticated queries once this one expires.

Create a new endpoint

Here, I'll show how to create 3 different types of endpoints:

  • Local endpoint using Docker socket communication
  • Remote endpoint using TCP communication
  • Remote endpoint using TCP communication secured via TLS

Local endpoint via the Docker socket

This query will create an endpoint called test-local and will use the Docker socket to communicate with this environment.

NOTE: This example requires to you bind-mount the Docker socket when running Portainer.

$ http --form POST :9000/api/endpoints \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
Name="test-local" EndpointType=1

The response is a JSON object representing the endpoint:

{
    "AuthorizedTeams": [], 
    "AuthorizedUsers": [], 
    "Extensions": [], 
    "GroupId": 1, 
    "Id": 1, 
    "Name": "test-local", 
    "PublicURL": "",
    "Type": 1,
    "TLSConfig": {
        "TLS": false, 
        "TLSSkipVerify": false
    }, 
    "Type": 1, 
    "URL": "unix:///var/run/docker.sock"
}

Retrieve the value of the Id property, it will be used to execute queries against the Docker engine for that endpoint.

Remote endpoint

This query will create an endpoint called test-remote and will communicate with this environment over TCP using the IP address 10.0.7.10 and port 2375 (these are example values, ensure that you're using the correct IP & port).

NOTE: The Docker API must be exposed on that IP address & port. Please refer to the Docker documentation to check how to configure this.

$ http --form POST :9000/api/endpoints \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
Name="test-remote" URL="tcp://10.0.7.10:2375" EndpointType=1

The response is a JSON object representing the endpoint:

{
    "AuthorizedTeams": [], 
    "AuthorizedUsers": [], 
    "Extensions": [], 
    "GroupId": 1, 
    "Id": 1, 
    "Type": 1,
    "Name": "test-remote", 
    "PublicURL": "", 
    "TLSConfig": {
        "TLS": false, 
        "TLSSkipVerify": false
    }, 
    "Type": 1, 
    "URL": "tcp://10.0.7.10:2375"
}

Retrieve the value of the Id property, it will be used to execute queries against the Docker engine for that endpoint.

Remote endpoint secured using TLS

This query will create an endpoint called test-remote-tls and will communicate with this environment over TCP (secured with TLS) using the IP address 10.0.7.10 and port 2376 (these are example values, ensure that you're using the correct IP & port).

NOTE: The Docker API must be exposed on that IP address & port. Please refer to the Docker documentation to check how to configure this.

$ http --form POST :9000/api/endpoints \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
Name="test-remote" URL="tcp://10.0.7.10:2376" EndpointType=1 TLS="true" TLSCACertFile@/path/to/ca.pem TLSCertFile@/path/to/cert.pem TLSKeyFile@/path/to/key.pem

The response is a JSON object representing the endpoint:

{
    "AuthorizedTeams": [], 
    "AuthorizedUsers": [], 
    "Extensions": [], 
    "GroupId": 1, 
    "Id": 1, 
    "Type": 1,
    "Name": "test-remote", 
    "PublicURL": "", 
    "TLSConfig": {
        "TLS": true, 
        "TLSCACert": "/data/tls/1/ca.pem", 
        "TLSCert": "/data/tls/1/cert.pem", 
        "TLSKey": "/data/tls/1/key.pem", 
        "TLSSkipVerify": false
    }, 
    "Type": 1, 
    "URL": "tcp://10.0.7.10:2376"
}

Retrieve this ID, it will be used to execute queries against the Docker engine for that endpoint.

Execute Docker queries against a specific endpoint

By using the following Portainer HTTP API endpoint /api/endpoints/<ENDPOINT_ID>/docker, you can now execute any of the Docker HTTP API requests.

This Portainer HTTP API endpoint acts as a reverse-proxy to the Docker HTTP API.

NOTE: You can refer to the Docker API documentation to get more information on how you can query the Docker engine.

As an example, here is how you can list all the containers available in a specific endpoint:

$ http GET :9000/api/endpoints/1/docker/containers/json \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
all==true

The response is exactly the same as returned by the ContainerList operation of the Docker API, see the documentation for the ContainerList operation.

Create a container

Here is how you can create a container in a specific endpoint using the Portainer HTTP API as a gateway.

This query will create a new Docker container inside the endpoint using the ID 1. The container will be named web01, use the nginx:latest Docker image and publish the container port 80 on via the 8080 port on the host.

See the link below to retrieve more information on how you can create a container using the Docker HTTP API.

$ http POST :9000/api/endpoints/1/docker/containers/create \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
name=="web01" Image="nginx:latest" \
ExposedPorts:='{ "80/tcp": {} }' \
HostConfig:='{ "PortBindings": { "80/tcp": [{ "HostPort": "8080" }] } }'

The response is exactly the same as returned by the ContainerCreate operation of the Docker API, see the documentation for the ContainerCreate operation.

Example response:

{
    "Id": "5fc2a93d7a3d426a1c3937436697fc5e5343cc375226f6110283200bede3b107",
    "Warnings": null
}

Retrieve the ID of the container, you will need it to execute actions against that container.

Start a container

You can now start the container that you previously created using the endpoint /api/endpoints/<ENDPOINT_ID>/docker/containers/<CONTAINER_ID>/start (ensure you retrieved the ID of the container created previsouly):

$ http POST :9000/api/endpoints/1/docker/containers/5fc2a93d7a3d426a1c3937436697fc5e5343cc375226f6110283200bede3b107/start \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"

The response is exactly the same as returned by the ContainerStart operation of the Docker API, see the documentation for the ContainerStart operation.

Delete a container

You can create a container using the following endpoint /api/endpoints/<ENDPOINT_ID>/docker/containers/<CONTAINER_ID>/remove:

$ http DELETE :9000/api/endpoints/1/docker/containers/5fc2a93d7a3d426a1c3937436697fc5e5343cc375226f6110283200bede3b107 \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE" \
force==true

The response is exactly the same as returned by the ContainerDelete operation of the Docker API, see the documentation for the ContainerDelete operation.

Manage Docker stacks in a Swarm environment

By using the following Portainer HTTP API endpoint /api/stacks, you can deploy and remove stack inside a specific Docker environment (Portainer endpoint).

In the following instructions, I'll assume that the endpoint using the ID 1 is connected to a Swarm cluster.

Before trying to create any stack, you need to retrieve the identifier of your Swarm cluster. It will be used to create stacks in the next steps.

$ http GET :9000/api/endpoints/1/docker/swarm \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"

In the response of this query, you'll find the identifier of the Swarm cluster inside the ID property:

{
  "CreatedAt": "2018-06-05T15:03:30.226627346Z", 
  "ID": "k427pd86wfkgp40ksrmbojrwq",
}

Deploy a new stack from a public Git repository

This query will create a new stack inside the endpoint using the ID 1. The stack will be named myTestStack, use the Stack file stored in the public Git repository https://github.com/portainer/templates under the path stacks/cockroachdb/docker-stack.yml.

$ http POST ':9000/api/stacks?method=repository&type=1&endpointId=1' \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTUyOTY3NDE1Mn0.wyyck_iktvOrYsuH0Xrvgifoi83emsszipSTYkDvuaE" \
Name="myTestStack" \
SwarmID="k427pd86wfkgp40ksrmbojrwq" \
RepositoryURL="https://github.com/portainer/templates" \
ComposeFilePathInRepository="stacks/cockroachdb/docker-stack.yml"

The response is a JSON object representing the newly created stack:

{
    "EndpointId": 1, 
    "EntryPoint": "stacks/cockroachdb/docker-stack.yml", 
    "Env": null, 
    "Id": 1, 
    "Name": "myTestStack", 
    "ProjectPath": "/data/compose/\u0002", 
    "SwarmId": "tdv7rl1u3965ml272o2q6d96z", 
    "Type": 1
}

Retrieve the stack identifier in the Id property, you'll need it to manage the stack.

Remove an existing stack

This query will remove the existing stack with the identifier 1 inside the endpoint using the ID 1.

$ http DELETE :9000/api/stacks/1?endpointId=1 \
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"
@ncorona

This comment has been minimized.

Copy link

@ncorona ncorona commented Sep 28, 2017

Hi! I tried to init the admin user using the REST API (as reported in this readme), but it results in a:
HTTP/1.1 400 Bad Request
{ "err": "Invalid request data format" }

After some debug I figured out that it is necessary to provide also the Username parameter inside the body request.
The correct httpie command should be:
http POST :9000/api/users/admin/init Username="admin" Password="adminpassword"

PS: I used the portainer docker image (version 1.14.2)

Best regards

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Nov 16, 2017

Thanks for the report @ncorona, the documentation has been updated :-)

@ransunak

This comment has been minimized.

Copy link

@ransunak ransunak commented Dec 6, 2017

Hi, i tried to query running containers form the api provided as above. I am getting 502 Bad gateway.
Note: I haven't done this part "Remote endpoint secured using TLS". Can i get any input on this please

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Jan 8, 2018

@ransunak if you're having troubles, please open an issue in https://github.com/portainer/portainer/issues or tell us about it in our Slack channel.

@SuperJojo2001

This comment has been minimized.

Copy link

@SuperJojo2001 SuperJojo2001 commented Feb 12, 2018

I wonder if I can read out the portainer version that is running on the system via same http request method. We are running version 1.12.4 and I have seen that compared to the 1.14.x the API has been changed slightly. If I am able to read our the portainer version after a successful authentication I am able to switch the API calls from one version to the other.

@spotware-git

This comment has been minimized.

Copy link

@spotware-git spotware-git commented Mar 20, 2018

is it possible to change ownership via API? how to make all containers as "Administrator" restricted by default?

@vladbabii

This comment has been minimized.

Copy link

@vladbabii vladbabii commented Apr 13, 2018

Thank you for the inspiration. I created a bash script to update stacks by giving stack name and yml file - https://github.com/docker-how-to/portainer-bash-scripts

@zveronline

This comment has been minimized.

Copy link

@zveronline zveronline commented Jul 5, 2018

I created python script to recreate stack - https://git.zveronline.ru/Docker/portainer-api-scripts

@greenled

This comment has been minimized.

Copy link

@greenled greenled commented Nov 21, 2018

I also created some Bash scripts to deploy/update/undeploy stacks based on @vladbabii ones - https://github.com/greenled/portainer-stack-utils

@matzegebbe

This comment has been minimized.

Copy link

@matzegebbe matzegebbe commented Dec 14, 2018

Here are my bash script for updating images in services and stacks https://github.com/matzegebbe/portainer-service-image-update-bash

@dhonig

This comment has been minimized.

Copy link

@dhonig dhonig commented Dec 18, 2018

@matzegebbe nice work on the scripts they seem to have the simplest interface. I'll let you know if I come up with any suggestions.

@haroules

This comment has been minimized.

Copy link

@haroules haroules commented Jan 9, 2019

Couldn't find a simple curl example for retrieving the jwt token, without having to install/use all kinds of other tools. Posting this here in the hopes of saving someone else's effort trying to figure out how to do it:
curl --include --request POST http://localhost:9000/api/auth --data '{"Username":"admin","Password":"admin123"}'

@militarpancho

This comment has been minimized.

Copy link

@militarpancho militarpancho commented Jan 9, 2019

This works for me but I use cut command.

curl -s -X POST "$(DEPLOY_TARGET)/api/auth" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"Username\": \"$(PORTAINER_API_USER)\", \"Password\": \"$(PORTAINER_API_PASS)\"}" | cut -f4 -d'"')

Being DEPLOY_TARGET the IP of the cluster.

@xgenvn

This comment has been minimized.

Copy link

@xgenvn xgenvn commented Jan 16, 2019

Hi, is there any API document on upload image tar archive under /#/images/build? I searched the SwaggerHub but it's not listing there.

@rizwan92

This comment has been minimized.

Copy link

@rizwan92 rizwan92 commented Jul 1, 2019

there are no docs for WebSocket. I successfully connect with my portainer WebSocket. i send few commands like "ls", "cd" . am gettign output message is the same as input . for example

if i send ls i get ls
if i send cd i get cd

i am not getting data like ls

app.js          index.js      server      client
public          www           bin            dist    
@MAHESHGONDA

This comment has been minimized.

Copy link

@MAHESHGONDA MAHESHGONDA commented Sep 5, 2019

Hi ,
i was trying to automate deployment and communication process between Portainer and Edge Agent , so used "portainer rest api" for creating endpoints. When created endpoint with type "EndpointType: 4" , response contains details of endpoints with EdgeKey , not EdgeID not sure why!!! .

is there any way to get both details upon creation of endpoints and supply them while running/deploying Edge agent on remote machine to establish communication between Portainer and Edge Agent ?

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Sep 5, 2019

@MAHESHGONDA the EdgeID is not automatically generated by Portainer to allow you to specify any kind of ID. You can use uuidgen (that's what Portainer UI is doing) to generate one.

@MAHESHGONDA

This comment has been minimized.

Copy link

@MAHESHGONDA MAHESHGONDA commented Sep 6, 2019

Great!!
Thank you for the reply ,

I am exploring rest APIs so not using Portainer UI. It would be great if you could tell me how to use uuidgen through rest api or any other?

I tried following : "Remote endpoint" creation

$ http --form POST :9000/api/endpoints
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"
Name="test-remote" URL="tcp://10.0.7.10:2375" EndpointType=4

Response JSON :
{
. . .
"Id": 1,
"Name": "test-remote",
"EdgeKey":"aHR0cDoasdasdMDB8MTcyLjE2LjEuMasddzY6ODAwMHxiYjo1MTpkYTo4ZDpiYjoxNDo1YTpkODo2MTo3ZjowNjozOTphOTo5Yj
pkNjo0OHw2"
. . .
}

I struck here, since in response JSON there is no EDGE_ID like (EDGE_ID=84a5e608-542a-4874-55a2-0658208be4e6).

I will explore more about Portainer.
Thank you for the Great stuff (Portainer)

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Sep 6, 2019

uuidgen is a binary and should be installed on your machine (it's available in most of the Linux distributions).

@MAHESHGONDA

This comment has been minimized.

Copy link

@MAHESHGONDA MAHESHGONDA commented Sep 6, 2019

Thank you....
My issues is resolved

@catalinroweb

This comment has been minimized.

Copy link

@catalinroweb catalinroweb commented Nov 14, 2019

How i can use this example to update current endpoint IP? Thanks!

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Nov 14, 2019

@catalinroweb

You'll need to send a PUT request to the api/endpoints/:id endpoint.

Documentation for this API endpoint available here: https://app.swaggerhub.com/apis/deviantony/portainer/1.22.2#/endpoints/EndpointUpdate

@catalinroweb

This comment has been minimized.

Copy link

@catalinroweb catalinroweb commented Nov 15, 2019

Thank you @deviantony!

@fwarmuth

This comment has been minimized.

Copy link

@fwarmuth fwarmuth commented Mar 10, 2020

Hey i have a question, how do i add local endpoint using a custom socket path?
I can't figure out how to do that...

http --form POST :9000/api/endpoints \
"Authorization: Bearer MY TOKEN!!!!!!!!" \
Name="test-local" EndpointType=1 URL="unix:///var/run/myCustomDocker.sock"

when i set a URI within my request i get:


{
    "details": "Get unix:///var/run/myCustomDocker.sock/_ping: unsupported protocol scheme \"unix\"",
    "message": "Unable to ping Docker environment"
}

any ideas?
regards

@gitrobert42

This comment has been minimized.

Copy link

@gitrobert42 gitrobert42 commented Apr 16, 2020

@fwarmuth

I am not, sure but I think you could do it by changing your bind mount to something like

docker run -d -p 9000:9000 -v /var/run/myCustomDocker.sock:/var/run/docker.sock portainer/portainer

Then you shouldn't need the URL=... parameter in your http call.

@brgsousa

This comment has been minimized.

Copy link

@brgsousa brgsousa commented Dec 4, 2020

I guess is not possible to get custom templates using GET ​/templates ?

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Dec 6, 2020

@brgsousa our API documentation is not up to date yet but custom templates management via API is available under the /custom_templates API endpoint.

@brgsousa

This comment has been minimized.

Copy link

@brgsousa brgsousa commented Dec 8, 2020

@brgsousa our API documentation is not up to date yet but custom templates management via API is available under the /custom_templates API endpoint.

Thank you!

@brgsousa

This comment has been minimized.

Copy link

@brgsousa brgsousa commented Dec 11, 2020

I could not find at https://app.swaggerhub.com/apis/deviantony/Portainer/1.24.1#/stacks/StackCreate how to deploy a stack from a template or custom template. Is it possible?

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Dec 13, 2020

@brgsousa the stack deployment from a template or custom template is a front-end only feature at the moment, if you would like to have the ability to deploy it via the API please open a feature request at https://github.com/portainer/portainer/issues/new

@Maracko

This comment has been minimized.

Copy link

@Maracko Maracko commented Feb 3, 2021

Is it anyhow possible to update an existing container with a new image? Like what you would do in the UI with the duplicate/edit button and always pull image option turned on?

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Feb 3, 2021

@marcko Portainer do not expose an API to do this, instead it will orchestrate the Docker API in the frontend (stop old container, rename old container, pull image, create new container, etc...)

@timdonovanuk

This comment has been minimized.

Copy link

@timdonovanuk timdonovanuk commented Feb 8, 2021

I wish it was possible to call the API using username/password always. I want to give a friend access to start my game server but don't feel like paying $300 for role based access. A simple "browser based" rest call would have worked perfectly, but having them generate a token every time is not workable.

@salvationws

This comment has been minimized.

Copy link

@salvationws salvationws commented Feb 17, 2021

Hello, can I get information about running services and versions with http api?

@jessyjes

This comment has been minimized.

Copy link

@jessyjes jessyjes commented Apr 15, 2021

Hello
With portainer 2.1.1, to create a new endpoint with API, the property EndpointType has been renamed with EndpointCreationType

@McTristan

This comment has been minimized.

Copy link

@McTristan McTristan commented Apr 22, 2021

How would I update a service member access / owner access when the stack has not been created by portainer? The UI, though it says that managing is limited, allows changes to the access settings. Another option would be to simply inherit the settings from the endpoint - so a user which access to the endpoint could also access all stacks and services within this endpoint.

In my case I'm creating stacks via terraform and the only feature I'm missing is the access control. Each time we redeploy I have to assign the members again to each service. If there is no inheritance functionality in portainer I thought I might be able to automate this via the portainer api.

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Apr 22, 2021

@McTristan as the stack was created outside of Portainer we don't have much control over it so you won't be able to set access control on the stack itself to be inherited by all the components of the stack.

What you can do is set access control on each component of the stacks via the use of the Portainer API and the resource_controls operations.

Here is an example of request with payload you could send to set the access control on a service to a specific user:

POST /api/resource_controls

{
  AdministratorsOnly: false
  Public: false
  ResourceID: "m6nacjain1sb2n5ygmr8tudcd" (replace with the ID of the Docker Swarm service)
  SubResourceIds: []
  Teams: []
  Type: "service"
  Users: [2] (replace with the ID or IDs of the targeted user(s))
}
@McTristan

This comment has been minimized.

Copy link

@McTristan McTristan commented Apr 23, 2021

Thank you!
Sounds like a way to go - however I have some problems understanding the meaning of the property ResourceID.

We have several endpoints, most of them are Edge-Endpoints (which are deployed via terraform with an edge agent connecting to the main portainer instance). I can query them with /api/endpoints and a filter - it will return the correct endpoints.

However there seems to be no way of querying the services for (such?) an endpoint with the API thus I don't really know the ID of the docker swarm service or am I'm missing something here?

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Apr 23, 2021

@McTristan indeed you will need the service identifier (as provided by Docker Swarm) if you want to apply a resource control on a Docker resource.

This can be retrieved through the UI by inspecting the resource and retrieving the ID from the URL but it can also be done via API, although to do so you will need to use the Docker API.

See https://docs.docker.com/engine/api/v1.41/#operation/ServiceList

This requires you to send a GET request to /services, you can access the Docker API through Portainer via the following API endpoint:

/api/endpoints/<ENDPOINT_ID>/docker (replace <ENDPOINT_ID> with the actual ID of the endpoint that you want to query).

Ultimately, you'll want to query something like this:

GET <PORTAINER_URL>/api/endpoints/1/docker/services

That should return the Swarm services associated to that endpoint.

@McTristan

This comment has been minimized.

Copy link

@McTristan McTristan commented Apr 24, 2021

Excellent answer, thank you. I can successfully fetch the services now and hope to automate the rest via httpie / jq magic. Let's see.

@McTristan

This comment has been minimized.

Copy link

@McTristan McTristan commented Apr 24, 2021

it works!

@greenmind-sec

This comment has been minimized.

Copy link

@greenmind-sec greenmind-sec commented Apr 26, 2021

Hello friends, i am build one integration using python for auth.
My problem is for create the container.

import requests

argumentos = {
    'Username':'admin',
    'Password':'MyPasswordAdmin'
}
url='http://127.0.0.1:9000/api/auth'

x = requests.post(url,json=argumentos)
print(x.status_code)
print(x.json())
@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Apr 26, 2021

@greenmind-sec what's your problem?

@MisderGAO

This comment has been minimized.

Copy link

@MisderGAO MisderGAO commented May 19, 2021

Hello,
the field stackFileContent is strange, the example of API doc does not work.
how can I convert a yaml/json file to set this field?
or can you provide another field in 'PUT /stacks​/{id}' so that we can update a stack via a yaml file (eg, from git )?

@denzuko

This comment has been minimized.

Copy link

@denzuko denzuko commented May 21, 2021

@deviantony sounds like @greenmind-sec's issue is English is not his first language so reading the docs might not be easy for him.

@greenmind-sec
Try adding pyswagger into your code and keep in mind that once your authenticated one can then talk to the underlining docker (swarm and engine APIs)[ https://docs.docker.com/engine/api/v1.30/#operation/ContainerCreate] under the /endpoints/{id}/docker Portainer API endpoint which is a pass through end point from portainer to the container's docker socket.

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented May 21, 2021

Just an update for everyone following this feed, the work on our side to make it up to date and put this inside our documentation has made some progress and I'll keep you posted here when it is available!

@lmjlopes

This comment has been minimized.

Copy link

@lmjlopes lmjlopes commented May 23, 2021

Hi all,

I've successfully build some python code to start and stop containers using this API. But I've struggling without success to send commands to a running container. I didn't find anywhere an example to help me.
I'm trying to emulate in Python the behaviour of the Portainer page "Container Console", selecting "Use custom command".
Am I doing something wrong, missing something or is it not even possible?

`def get_container_exec(self):

    r=requests.post(self.portainer_endpoint+"/endpoints/2/docker/containers/" + self.portainer_container + "/exec", 
        headers={
            "Authorization": "Bearer {}".format(self.token),
            "Content-Type": "application/json"},
        json = {
            "Id": self.portainer_container,
            "AttachStderr": True,
            "AttachStdin": True,
            "AttachStdout": True,
            "Tty": True,
            "Cmd": ["python3", "test.py"]},
        verify=self.verifySSL,
        timeout = 5)`
@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented May 23, 2021

@lmjopes container exec will be harder to automate, it is using the websocket protocol not classic REST HTTP API.

@lmjlopes

This comment has been minimized.

Copy link

@lmjlopes lmjlopes commented May 24, 2021

@deviantony
Based on your response I rerouted this in another way. I managed sucessfully to do what I needed ( start, stop and send commands to a running container) using another container to act as a gateway, based on the container from "philhawthorne/ha-dockermon".
I was trying to make it simple and use just what I already had, Portainer.
Thanks anyway for your reply.

@filosof86

This comment has been minimized.

Copy link

@filosof86 filosof86 commented Jun 1, 2021

Hi @deviantony

Retrieving the user info (getting the list or the user's info), I do not see his password although the password field is described as the one which has to be returned https://app.swaggerhub.com/apis/deviantony/Portainer/2.0.1#/users/UserList

Parsed response

$VAR1 = { 
          'success' => 1,
          'response' => { 
                          'PortainerAuthorizations' => undef,
                          'Role' => 2,
                          'Id' => 2,
                          'EndpointAuthorizations' => undef,
                          'Username' => 'filosof'
                        },
          'return_code' => 200
        };

I just wanted to implement auto-login into the Portainer WI previously comparing the predefined list of the user names with the list defined in Portainer and if some username exists - take his credentials to log in.

Any chance for me to do that?

Thanks!

@deviantony

This comment has been minimized.

Copy link
Owner Author

@deviantony deviantony commented Jun 28, 2021

DEPRECATION NOTICE

This gist is now deprecated in favor of our official documentation: https://documentation.portainer.io/api/api-examples/ which contains up to date examples!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment