Benvenuto π
Ogni blocco di codice ha il tasto Copia. I placeholder (PORTAINER, LA_TUA_CHIAVE, ENDPOINT_ID, ecc.) vengono sostituiti con i valori inseriti nel tab CRUD Cookbook. Tieni premuto Ctrl/β + K per cercare, G poi C per aprire il tab CRUD.
Il tema Giorno/Notte, l'ultimo tab e la configurazione vengono ricordati automaticamente.
Installare Docker (Ubuntu)
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Test
docker version && docker compose version
Avviare Portainer
mkdir -p ~/portainer && cd ~/portainer
cat > docker-compose.yml <<'YAML'
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
command: -H unix:///var/run/docker.sock
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./portainer_data:/data
restart: unless-stopped
YAML
docker compose up -d
# Apri http://IP:9000 e crea l'utenza admin
HTTPS con Caddy (consigliato)
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
command: -H unix:///var/run/docker.sock
expose:
- "9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./portainer_data:/data
restart: unless-stopped
caddy:
image: caddy:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
depends_on:
- portainer
restart: unless-stopped
# Caddyfile
portainer.tuodominio.it {
reverse_proxy portainer:9000
tls tuaemail@example.com
}
API Key
- Login in Portainer β My account β API keys.
- Genera la chiave e conservala.
- Autenticati sempre con header
X-API-Key: LA_TUA_CHIAVE.
Operazioni veloci
Crea volume
curl -X POST -H "Content-Type: application/json" -H "X-API-Key: LA_TUA_CHIAVE" \
-d '{"Name":"mio_volume","Driver":"local"}' \
https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/volumes/create
Crea+start container
# Create
curl -X POST -H "Content-Type: application/json" -H "X-API-Key: LA_TUA_CHIAVE" \
-d '{"Image":"nginx:alpine"}' \
"https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/create?name=web"
# Start
curl -X POST -H "X-API-Key: LA_TUA_CHIAVE" \
https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/web/start
Monitoraggio
# Stats singolo container (CPU/RAM/rete)
curl -H "X-API-Key: LA_TUA_CHIAVE" \
https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID_CONTAINER/stats?stream=false
Sicurezza minima
- Usa HTTPS con Caddy/Traefik o Tunnel.
- API Key con permessi minimi (RBAC).
- IP allow-list sul proxy verso la tua app.
- Non esporre porte 9000/9443 direttamente su internet.
π CRUD Cookbook β tutte le operazioni principali
Le ultime scelte vengono salvate e ripristinate. Ctrl/β+K per cercare i comandi.
Sezione pensata anche per soluzioni di vibe coding/noβcode: ogni blocco indica Metodo, URL, Header, Body JSON.
1) Container
Create
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/create?name=NOME
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{
"Image": "nginx:alpine",
"Env": [{"Name":"TZ","Value":"Europe/Rome"}],
"HostConfig": {
"PortBindings": {"80/tcp": [{"HostPort": "8080"}]},
"Binds": ["mio_volume:/usr/share/nginx/html"]
}
}
# Start
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/NOME/start
Header: X-API-Key
Read
# Lista
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/json
Header: X-API-Key
# Dettaglio
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID_CONTAINER/json
Header: X-API-Key
Update
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID_CONTAINER/update
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{
"Memory": 2147483648,
"NanoCPUs": 2000000000
}
Delete
DELETE https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID_CONTAINER?force=1
Header: X-API-Key
Extra utili
# Logs (ultimi 200)
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID/logs?stdout=1&stderr=1&tail=200
# Stats istantanee
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/containers/ID/stats?stream=false
# Start/Stop/Restart
POST .../containers/ID/start
POST .../containers/ID/stop
POST .../containers/ID/restart
2) Images
Create (pull)
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/images/create?fromImage=nginx&tag=alpine
Header: X-API-Key
Read
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/images/json
Header: X-API-Key
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/images/NAME/json
Header: X-API-Key
Delete
DELETE https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/images/NAME
Header: X-API-Key
3) Volumes
Create
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/volumes/create
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{ "Name":"mio_volume","Driver":"local" }
Read
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/volumes
Header: X-API-Key
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/volumes/NOME
Header: X-API-Key
Delete
DELETE https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/volumes/NOME
Header: X-API-Key
4) Network
Create
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks/create
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{ "Name":"mianet","Driver":"bridge" }
Read
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks
Header: X-API-Key
GET https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks/ID
Header: X-API-Key
Update (connect/disconnect)
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks/ID/connect
Header: X-API-Key
Body:
{ "Container":"ID_CONTAINER" }
POST https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks/ID/disconnect
Header: X-API-Key
Body:
{ "Container":"ID_CONTAINER" }
Delete
DELETE https://PORTAINER/api/endpoints/ENDPOINT_ID/docker/networks/ID
Header: X-API-Key
5) Stacks (Compose)
Create
POST https://PORTAINER/api/stacks?type=2&method=string&endpointId=ENDPOINT_ID
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{
"Name":"mystack",
"StackFileContent":"version: \"3.8\"\nservices:\n web:\n image: nginx:alpine\n ports:\n - \"8080:80\"\n"
}
Read
GET https://PORTAINER/api/stacks
Header: X-API-Key
GET https://PORTAINER/api/stacks/STACK_ID
Header: X-API-Key
Update
PUT https://PORTAINER/api/stacks/STACK_ID
Headers:
X-API-Key: LA_TUA_CHIAVE
Content-Type: application/json
Body:
{ "StackFileContent":"version: \"3.8\"\nservices:\n web:\n image: nginx:latest\n" }
Delete
DELETE https://PORTAINER/api/stacks/STACK_ID
Header: X-API-Key
Snippet "vibe coding" (Node fetch)
// Esempio generico per blocco HTTP (Node/fetch)
const base = "https://PORTAINER/api";
const token = process.env.PORTAINER_TOKEN; // imposta la tua chiave
async function http(path, opts={}){
const res = await fetch(base+path, {headers:{"X-API-Key":token,"Content-Type":"application/json",...(opts.headers||{})}, ...opts});
if(!res.ok) throw new Error(await res.text());
return res.json();
}
// Create volume
await http(`/endpoints/${ENDPOINT_ID}/docker/volumes/create`, {method:'POST', body: JSON.stringify({Name:'mio_volume'})});
// List containers
const containers = await http(`/endpoints/${ENDPOINT_ID}/docker/containers/json`);
Nei tool no/lowβcode imposta X-API-Key come header fisso nel connettore; poi riusa gli endpoint variando solo path e body.