Skip to content
Please consider turning off your ad blocker to help encourage ethical advertising

Templates Explained

This page will go over building a template. The templates are all compatible with portainer v1 templates so you can always check that documentation too. All of the keys (type, name, title, etc.) are optional and will simply be blank if left empty.

Single app templates will be surrounded by {} as is standard for .json files. Multi app templates with consist of multiple {} sections (separated with a , after the } (ie. },) surrounded in [].

More info on writing JSON is available here

If you don't like writing in JSON another option is to use YAML. It's automatically converted into JSON in the backend so all of the options are the same.

Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{
  "type": 1,
  "title": "App Title",
  "name": "container-name",
  "description": "This is a description.",
  "logo": "https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/master/Images/transmission-icon.png",
  "image": "dev/application:latest",
  "note": "This is a note",
  "categories": [
    "Other",
    "Tools"
  ],
  "platform": "linux",
  "restart_policy": "unless-stopped",
  "ports": [
    "9091:9091/tcp",
    "9090:9090/tcp"
  ],
  "network_mode": "bridge",
  "volumes": [
    {
      "container": "/data",
      "bind": "!downloads"
    },
    {
      "container": "/etc/localtime",
      "bind": "!localtime"
    }
  ],
  "sysctls": [
    {
    "net.ipv6.conf.all.disable_ipv6": "0"
    }
  ],
  "cap_add": [
    "NET_ADMIN"
  ],
  "env": [
    {
      "name": "PUID",
      "label": "PUID",
      "default": "1000"
    },
    {
      "name": "PGID",
      "label": "PGID",
      "default": "1000"
    },
    {
      "name": "EnvWithDescription",
      "label": "EnvWithDescription",
      "description": "This is a description",
      "default": "default"
    }
  ]
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
---
type: 1
title: App Title
name: container-name
description: This is a description.
logo: https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/master/Images/transmission-icon.png
image: dev/application:latest
note: This is a note
categories:
- Other
- Tools
platform: linux
restart_policy: unless-stopped
ports:
- 9091:9091/tcp
- 9090:9090/tcp
network_mode: bridge
volumes:
- container: "/data"
  bind: "!downloads"
- container: "/etc/localtime"
  bind: "!localtime"
sysctls:
- net.ipv6.conf.all.disable_ipv6: '0'
cap_add:
- NET_ADMIN
env:
- name: PUID
  label: PUID
  default: '1000'
- name: PGID
  label: PGID
  default: '1000'
- name: EnvWithDescription
  label: EnvWithDescription
  description: This is a description
  default: default

This is what each section does:

* = required

type*

Code Example

{
  "type": 1,
}
type: 1

This currently isn't in use. It's just here to keep compatibility with portainer but is ignored.

title*

Example

{
  "title": "App Title",
}
title: App Title

This is what is displayed when in the apps list page. Punctuation is nice here and adds to the polish

name

Example

{
  "name": "app_name",
}
name: app_name

This is what the actual container is named. Information on this is here.

description

Example

{
  "description": "This is a description.",
}
description: This is a description.

This is the description that is shown in the app list. \n is interpreted as a newline character

Example

{
  "logo": "https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/master/   Images/transmission-icon.png",
}
logo: https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/master/Images/   transmission-icon.png

This is the logo that is show in the app list.

image*

Example

{
  "image": "haugene/transmission-openvpn:latest",
}
image: haugene/transmission-openvpn:latest

This is the image that's pulled from dockerhub. The tag (:latest) is optional.

note

Example

{
  "note": "List of supported providers available <a href='https://haugene.github.io/    docker-transmission-openvpn/supported-providers'/>here</a>.",
}
note: List of supported providers available <a href='https://haugene.github.io/   docker-transmission-openvpn/supported-providers'/>here</a>.,

This is shown when someone clicks on "VIEW" in the app list. It will render HTML appropriately.

categories

Example

{
  "categories": [
    "Other",
    "VPN",
    "Tools"
  ],
}
categories:
- Other
- VPN
- Tools
{
  "categories": ["Other", "VPN", "Tools"],
}

A list of categories associated with the application. This is optional but sorting/filtering by category will eventually be a feature.

platform*

Example

{
  "platform": "linux",
}
platform: linux,

The platform the image will run on. Haven't tested anything but linux.

restart_policy

Example

{
  "restart_policy": "unless-stopped",
}
restart_policy: unless-stopped

Define your restart policy. Info here.

ports

Example

{
  "ports": [
      "9091:9091/tcp",
      "9090:9090/tcp",
      "9092/tcp"
    ],
}
ports:
- 9091:9091/tcp
- 9090:9090/tcp
- 9092/tcp
{
  "ports": ["9091:9091/tcp", "9090:9090/tcp", "9092/tcp"]
}

Ports to be passed through. The host port is on the left of the : and the container port is on the right. Protocol is after the /. If no host port is specified a random one is used. I frequently leave out the host port on applications that use common ports.

Port Labels

Example

{
  "ports": [
    {
      "WebUI": "8096:8096/tcp",
      "HTTPS WebUI": "8920:8920/tcp",
      "DNLA": "1900:1900/udp",
      "Discovery": "7359:7359/udp"
    }
  ],
}
ports:
- WebUI: 8096:8096/tcp
- HTTPS WebUI: 8920:8920/tcp
- DNLA: 1900:1900/udp
- Discovery: 7359:7359/udp
{
  "ports": [{ "WebUI": "8096:8096/tcp", "HTTPS WebUI": "8920:8920/tcp",  "DNLA": "1900:1900/udp", "Discovery": "7359:7359/udp"}]
}

You can label ports for the services that are on them if you would like. This will auto-fill the label field in the deploy form and give users a better understanding of the applications they're running.

network_mode

Example

{
  "network_mode": "host"
}
network_mode: host

You can set a certain network mode if you're using a legacy application that requires it.

any ports mapped will not be passed through if you choose host as your networking mode and you cannot change the ports

volumes

Example

{
  "volumes": [
    {
      "container": "/data",
      "bind": "!downloads"
    },
    {
      "container": "/etc/localtime",
      "bind": "/etc/localtime"
    },
      "container": "/config",
      "bind": "app_config"
  ],
}
volumes:
- container: "/data"
  bind: "!downloads"
- container: "/etc/localtime"
  bind: "/etc/localtime"
- container: "/config"
  bind: "app_config"
{
  "volumes": [{ "container": /data, "bind": "!downloads" }, { "container": "/etc/localtime", "bind": "/etc/localtime" }, { "container": "/config", "bind": "app_config"}]
}

List of bind mounts. Container will mount inside of the container and bind will mount on the host. The bind section can utilize Template Variables in the users settings so if they're set they'll be replaced by what's there. You can use a named volume by using the name of the volume instead of a path (no / at the beginning).

sysctls

Example

{
  "sysctls": [
    {
    "net.ipv6.conf.all.disable_ipv6": "0"
    }
  ],
}
sysctls:
- net.ipv6.conf.all.disable_ipv6: '0'
{
  "sysctls": [ { "net.ipv6.conf.all.disable_ipv6": "0" } ]
}

Key value pair for sysctl options. More info available here

cap_add

Example

{
  "cap_add": [
    "NET_ADMIN"
  ],
}
cap_add:
- NET_ADMIN
{
  "cap_add": ["NET_ADMIN"]
}

Value of capabilities you want to add to a container. More info available here.

env

Example

{
  "env": [
    {
      "name": "PUID",
      "label": "PUID",
      "default": "1000"
    },
    {
      "name": "PGID",
      "label": "PGID",
      "default": "1000"
    },
    {
      "name": "EnvWithDescription",
      "label": "EnvWithDescription",
      "description": "This is a description",
      "default": "default"
    },
  ]
}
env:
- name: PUID
  label: PUID
  default: 1000
- name: PGID
  label: PGID
  default: 100
- name: EnvWithDescription
  label: EnvWithDescription
  description: This is a description
  default: defaullt
{
  "env": [{"name": "PUID","label": "PUID","default": "1000"},{"name": "PGID","label": "PGID","default": "1000"},{"name": "EnvWithDescription","label": "EnvWithDescription","description": "This is a description","default": "default"}]
}

Env is used to set environment variables within the docker container. The description and default are both optional. Label currently isn't used but will be what is shown as the name of the field in the deploy form.

labels

Example

{
"labels": [
  {
    "label": "local.yacht.label",
    "value": "this is a label"
  },
  {
    "label": "local.yacht.otherlabel",
    "value": "this is another label"
  }
]
}
labels:
- label: local.yacht.label
  value: this is a label
- label: local.yacht.otherlabel
  value: this is another label
{
  "labels": [{"label": "local.yacht.label","value": "this is a label"},{"label": "local.ycht.otherlabel","value": "this is another label"}]
}

Labels can be used for automating services like traefik automatically as well as store information about containers (this is where port descriptions are stored on containers). These will show up in the advanced section like sysctls and capabilities.

devices

Example

{
  "devices": [
    {
      "host": "/dev/null",
      "container": "/dev/null"
    }
  ]
}
devices:
- host: /dev/null
  container: /dev/null
{
  "devices": [{"host": "/dev/null","container": "/dev/null"}]
}

Devices allow devices to be passed through containers for things like transcoding.


Last update: 2020-10-23