You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Official postgres plugin for dokku. Currently defaults to installing postgres 18.6.
Requirements
dokku 0.35.x+
docker 1.8.x
Installation
# on 0.35.x+
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git --name postgres
Commands
postgres:app-links [<app>] # list all Postgres service links for a given app
postgres:backup <service> <bucket-name> [-u|--use-iam] # create a backup of the Postgres service to an existing s3 bucket
postgres:backup-auth <service> <aws-access-key-id> <aws-secret-access-key> <aws-default-region> <aws-signature-version> <endpoint-url> # set up authentication for backups on the Postgres service
postgres:backup-deauth <service> # remove backup authentication for the Postgres service
postgres:backup-schedule <service> <schedule> <bucket-name> [-u|--use-iam] # schedule a backup of the Postgres service
postgres:backup-schedule-cat <service> # cat the crontab line of the scheduled backup for the service
postgres:backup-set-encryption <service> <passphrase> # set encryption for all future backups of Postgres service
postgres:backup-set-public-key-encryption <service> <public-key-id> # set GPG Public Key encryption for all future backups of Postgres service
postgres:backup-unschedule <service> # unschedule the backup of the Postgres service
postgres:backup-unset-encryption <service> # unset encryption for future backups of the Postgres service
postgres:backup-unset-public-key-encryption <service> # unset GPG Public Key encryption for future backups of the Postgres service
postgres:certificate <service> # print the certificate the Postgres service encrypts connections with
postgres:clone <service> <new-service> [--clone-flags...] # create container <new-name> then copy data from <name> into <new-name>
postgres:connect <service> # connect to the service via the postgres connection tool
postgres:create <service> [--create-flags...] # create a Postgres service
postgres:destroy <service> [-f|--force] # delete the Postgres service/data/container if there are no links left
postgres:enter <service> # enter or run a command in a running Postgres service container
postgres:exists <service> # check if the Postgres service exists
postgres:export <service> [-f|--file <path>] [--force] [-- <export-args...>] # export a dump of the Postgres service database
postgres:expose <service> <ports...> # expose a Postgres service on custom host:port if provided (random port on the 0.0.0.0 interface if otherwise unspecified)
postgres:import <service> [-f|--file <path>] [-- <import-args...>] # import a dump into the Postgres service database
postgres:info [<service>] [--info-flags...] # print the service information
postgres:link <service> [<app>] [--link-flags...] # link the Postgres service to the app
postgres:linked <service> [<app>] # check if the Postgres service is linked to an app
postgres:links <service> # list all apps linked to the Postgres service
postgres:list # list all Postgres services
postgres:logs <service> [-t|--tail [<tail-num>]] # print the most recent log(s) for this service
postgres:mount [--replace] <service> <source:container-dir[:options]>... # mount a host path or docker volume into the service container
postgres:pause <service> # pause a running Postgres service
postgres:promote <service> [<app>] # promote service <service> as DATABASE_URL in <app>
postgres:reexpose <service> # reexpose a Postgres service, applying its expose settings
postgres:restart <service> # graceful shutdown and restart of the Postgres service container
postgres:set <service> <key> <value> # set or clear a property for a service
postgres:start <service> # start a previously stopped Postgres service
postgres:stop <service> # stop a running Postgres service
postgres:unexpose <service> # unexpose a previously exposed Postgres service
postgres:unlink <service> [<app>] [-n|--no-restart] # unlink the Postgres service from the app
postgres:unmount [--all] <service> [<source:container-dir>...] # remove one or all mounts from the service container
postgres:upgrade <service> [--upgrade-flags...] # upgrade service <service> to the specified versions
Usage
Help for any commands can be displayed by specifying the command as an argument to postgres:help. Plugin help output in conjunction with any files in the docs/ folder is used to generate the plugin documentation. Please consult the postgres:help command for any undocumented commands.
These images each have definitions of their own, one per major version, so a service on one is placed by the major its tag carries and has a version to fall back on.
The definition a service runs on decides where its data is mounted, and is otherwise worked out from the image and version. An image whose tags do not carry the major version can name one outright, and --image and --image-version are laid over the image and version it ships. The definitions are: postgres-17, postgres-18, postgres-pgvector-pg17, postgres-pgvector-pg18, postgres-postgis-pg17, postgres-postgis-pg18, postgres-timescaledb-pg17, postgres-timescaledb-pg18.
The container log is bounded by whatever dokku logs:set --global max-size says, and by dokku's own default where it says nothing, which a service may override for itself.
The service is waited on until it answers, for as long as the datastore's own default, which a slow host may raise for every service with POSTGRES_WAIT_TIMEOUT or a service may raise for itself.
dokku postgres:create lollipop --wait-timeout 120
The config options are handed to the process the container runs, not to docker, so a host path or docker volume is mounted with --volume, which may be repeated.
The definition's own volumes can be mounted at another path in the container, for an image that keeps its data somewhere else, with --volume-target, which may be repeated.
Official Postgres "$DOCKER_BIN" image ls does not include postgis extension (amongst others). The following example creates a new postgres service using postgis/postgis:13-3.1 image, which includes the postgis extension.
# use the appropriate image-version for your use-case
dokku postgres:create postgis-database --image "postgis/postgis" --image-version "13-3.1"
To use pgvector instead, run the following:
# use the appropriate image-version for your use-case
dokku postgres:create pgvector-database --image "pgvector/pgvector" --image-version "pg17"
delete the Postgres service/data/container if there are no links left
--backend: show the execution backend the service was created with
--backup-auth-fingerprint: show a sha256 fingerprint of the stored backup access key id and secret
--backup-authenticated: show whether backup credentials are stored for the service
--backup-bucket: show the bucket scheduled backups are shipped to
--backup-default-region: show the region backups authenticate against
--backup-encrypted: show whether scheduled backups are encrypted with a passphrase
--backup-encryption-fingerprint: show a sha256 fingerprint of the stored backup passphrase
--backup-endpoint-url: show the s3-compatible endpoint backups are shipped to
--backup-keyserver: show the keyserver backup public keys are fetched from
--backup-public-key-id: show the gpg public key id backups are encrypted with
--backup-schedule: show the cron schedule backups run on
--backup-signature-version: show the signature version backups authenticate with
--backup-storage-class: show the s3 storage class backups are uploaded with
--backup-use-iam: show whether scheduled backups authenticate with an instance role
--config-dir: show the service configuration directory
--config-options: show the config options the service container is run with
--custom-env: show the custom environment the service container is run with
--data-dir: show the service data directory
--database-name: show the name of the database inside the service
--definition: show the definition the service was created with
--dsn: show the service DSN
--export-args: show the extra arguments every export of the service is run with
--expose-host: show the host the exposed DSN names
--expose-mode: show whether exposed ports are published through an ambassador or directly by the service container
--exposed-dsn: show the DSN the service is reached at through its exposed ports
--exposed-ports: show service exposed ports
--id: show the service container id
--image: show the image the service runs
--image-version: show the image version the service was created with
--import-args: show the extra arguments every import into the service is run with
--initial-network: show the initial network being connected to
--internal-ip: show the service internal ip
--links: show the service app links
--log-driver: show the docker logging driver the service container is run with
--log-opt: show the docker log options the service container is run with
--memory: show the memory limit the service container is run with
--mounts: show the host paths and docker volumes mounted into the service container
--port-bind-address: show the address exposed ports without one of their own are bound on
--port-source-range: show the only range of client addresses the exposed ports accept
--post-create-network: show the networks to attach to after service container creation
--post-start-network: show the networks to attach to after service container start
--restart-policy: show the restart policy the service container is run with
--service: show the name of the service
--service-root: show the service root directory
--shm-size: show the shared memory size the service container is run with
--status: show the service running status
--version: show the service image version
--volume-targets: show the container paths the service's volumes are mounted at in place of the definition's
--wait-timeout: show the seconds the service is waited on to become ready
Get connection information as follows:
dokku postgres:info lollipop
Alongside the connection information this reports the properties set on the service, the state it was created with, and its backup settings. A property that was never set, or that was unset, reports as empty. Omit the service to report on every postgres service:
dokku postgres:info
The information can be read by machine, one json object per service:
dokku postgres:info lollipop --format json
You can also retrieve a specific piece of service info via a flag, which prints it on its own:
NOTE: a flag cannot be combined with --format, and only one may be given
The exposed dsn is the one a client off the host connects with. It names the expose-host, or the first global domain without one, and is empty until the service is exposed and there is a host to name:
dokku postgres:info lollipop --exposed-dsn
The properties postgres:set writes are reported under the names it takes, so a value read here can be written back:
The stored backup credentials and passphrase are never printed. Each is reported as a lowercase hex sha256 fingerprint of the stored value, with surrounding whitespace trimmed, so a copy of the values can be compared against it:
-a|--alias <string>: the prefix of the config variable the service url is set as on the app, which is suffixed with _URL
-e|--env-var <string>: the full name of the config variable the service url is set as on the app, used instead of an alias and not suffixed with _URL
-n|--no-restart: whether to skip restarting the app
-q|--querystring <string>: ampersand delimited querystring arguments to append to the service url after a ?
A postgres service can be linked to a container. This will use native docker links via the docker-options plugin. Here we link it to our playground app.
NOTE: this will restart your app
dokku postgres:link lollipop playground
The following environment variables will be set automatically by docker (not on the app itself, so they won’t be listed when calling dokku config):
The host exposed here only works internally in docker containers. If you want your container to be reachable from outside, you should use the expose subcommand. Another service can be linked to your app:
dokku postgres:link other_service playground
The url can be set under another name with the --alias flag. The value given is the prefix of the config variable, which is suffixed with _URL and holds the same url:
An alias whose variable is already set on the app is refused, and unlink removes the variable whatever alias it was set under. An app that expects the url under a name that does not end in _URL can be given that name in full with the --env-var flag, which cannot be combined with --alias:
It is possible to change the protocol for DATABASE_URL by setting the environment variable POSTGRES_DATABASE_SCHEME on the app. Link records the variable it set, so unlink still removes it after the scheme or querystring on it changes. A link made by an earlier version of the plugin is recorded the next time link or promote runs for it, and until then we advise you to unlink before changing the scheme.
-n|--no-restart: whether to skip restarting the app
You can unlink a postgres service:
NOTE: this will restart your app and unset related environment variables
dokku postgres:unlink lollipop playground
An app is still linked after its DATABASE_URL is changed to point elsewhere, and is unlinked the same way. The variable it now holds is not the service's, so it is left alone, nothing is unset, the app is not restarted, and a warning says so. A variable link set that has only had its scheme or querystring changed still points at the service, and is unset.
set or clear a property for a service
# usage
dokku postgres:set <service><key><value>
Set the network to attach after the service container is started:
Set the s3 storage class backups are uploaded with, one of STANDARD,REDUCED_REDUNDANCY,STANDARD_IA,ONEZONE_IA,INTELLIGENT_TIERING,GLACIER,DEEP_ARCHIVE or GLACIER_IR:
Name the host the exposed dsn points clients at, when they reach the server by a name or address other than its global domain. It does not change where the ports are bound:
Publish the exposed ports on the service container itself rather than through an ambassador container, which relays every connection. A port-source-range cannot be used with it:
dokku postgres:set lollipop expose-mode direct
Go back to publishing the exposed ports through an ambassador container:
dokku postgres:set lollipop expose-mode
Pass extra arguments to every export of the service, including the ones backups and clones make. The value follows -- so that its leading dash is not read as a flag, and an argument with a space in it is quoted:
Go back to importing with the datastore's own arguments alone:
dokku postgres:set lollipop import-args
Mount one of the definition's volumes at another path in the container, for an image that keeps its data somewhere else. Each volume is named by where it lives in the service directory (data, certs), and several are separated by spaces:
Go back to mounting every volume where the definition does:
dokku postgres:set lollipop volume-targets
NOTE: a log setting, a restart policy or a volume target reaches the container the next time one is built. postgres:restart keeps the container it has, so use postgres:stop and then postgres:start on a service that is already running.
NOTE: a port-bind-address or port-source-range reaches an exposed service with postgres:reexpose, which replaces the container publishing its ports and leaves the service container running.
NOTE: an expose-mode, or a port-bind-address for a service exposed directly, reaches an exposed service with postgres:reexpose, which stops and starts a running service after asking. It also reaches the service the next time it is restarted, or stopped and started.
mount a host path or docker volume into the service container
The source is an absolute host path, which must already exist, or the name of a docker volume. Options follow a second colon: ro or rw, docker's own mount options, volume-subpath= and volume-chown=:
A subpath mounts a directory within the source rather than the source itself. A docker volume mounted from a subpath needs Docker Engine 26.0 or newer, and takes no mount option but nocopy.
A chown hands the mounted directory to a user before the container is made: herokuish, heroku, paketo, root or a uid. It is only taken for a host path inside the service's own directory.
NOTE: a mount cannot land where one of the definition's volumes is mounted, which for a volume moved with the volume-targets property is where it was moved to.
NOTE: a mount reaches the container the next time one is built. postgres:restart keeps the container it has, so use postgres:stop and then postgres:start on a service that is already running.
remove one or all mounts from the service container
NOTE: the mount is removed from the container the next time one is built. postgres:restart keeps the container it has, so use postgres:stop and then postgres:start on a service that is already running.
Service Lifecycle
The lifecycle of each service can be managed through the following commands:
connect to the service via the postgres connection tool
# usage
dokku postgres:connect <service>
Connect to the service via the postgres connection tool:
NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098
dokku postgres:connect lollipop
The connection tool only shows a prompt when it is given a terminal, which ssh allocates when run with -t. Without a terminal, statements are read from stdin instead.
dokku postgres:connect lollipop < statements.txt
enter or run a command in a running Postgres service container
# usage
dokku postgres:enter <service>
A shell can be opened against a running service. Filesystem changes will not be saved to disk.
NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098
dokku postgres:enter lollipop
You may also run a command directly against the service. Filesystem changes will not be saved to disk.
dokku postgres:enter lollipop touch /tmp/test
expose a Postgres service on custom host:port if provided (random port on the 0.0.0.0 interface if otherwise unspecified)
# usage
dokku postgres:expose <service><ports...>
flags:
-f|--force: stop and start a running service without asking when its container has to publish other ports
Expose the service on the service's normal ports, allowing access to it from the public interface (0.0.0.0):
dokku postgres:expose lollipop 5432
Expose the service on the service's normal ports, with the first on a specified ip address (127.0.0.1):
dokku postgres:expose lollipop 127.0.0.1:5432
Expose the service on random ports on a single address, and only to clients in one network:
Expose the service by publishing its ports on the service container itself rather than through an ambassador container. A running service is stopped and started to publish them, after asking, or without asking when --force is given:
dokku postgres:set lollipop expose-mode direct
dokku postgres:expose lollipop --force
Print the dsn a client off the host connects with, which names the expose-host or the first global domain:
dokku postgres:info lollipop --exposed-dsn
unexpose a previously exposed Postgres service
# usage
dokku postgres:unexpose <service>
flags:
-f|--force: stop and start a running service without asking when its container has to publish other ports
Unexpose the service, removing access to it from the public interface (0.0.0.0):
dokku postgres:unexpose lollipop
Unexpose a running service exposed directly, stopping and starting it without asking so that its container stops publishing the ports:
dokku postgres:unexpose lollipop --force
reexpose a Postgres service, applying its expose settings
# usage
dokku postgres:reexpose <service>
flags:
-f|--force: stop and start a running service without asking when its container has to publish other ports
Apply a changed port-bind-address or port-source-range to an exposed service, on the ports it is already exposed on:
Move an exposed service between being published through an ambassador and directly, stopping and starting it without asking:
dokku postgres:set lollipop expose-mode direct
dokku postgres:reexpose lollipop --force
NOTE: a service published through an ambassador only has the ambassador replaced, so the service keeps running, though connections made through the exposed ports are dropped. An ambassador that already matches the service's settings and is publishing is left alone.
NOTE: a service whose container has to publish other ports, because it is exposed directly or is being moved between expose modes, is stopped and started. A running service is asked about first, and nothing is changed if the answer is no.
NOTE: A service that is not exposed is refused, as is one published through an ambassador that is not running.
promote service as DATABASE_URL in
# usage
dokku postgres:promote <service> [<app>]
If you have a postgres service linked to an app and try to link another postgres service another link environment variable will be generated automatically:
You can promote the new service to be the primary one:
NOTE: this will restart your app
dokku postgres:promote other_service playground
This will replace DATABASE_URL with the url from other_service and generate another environment variable to hold the previous value if necessary. You could end up with the following for example:
A service comes back on the version it was created with, or was last upgraded to, whatever version the plugin ships now. The image is fetched if the host no longer has it. A service that has never recorded a version and has no container left to read one from cannot be placed, and is reported rather than started on a guess. Use postgres:upgrade to say which version it should run.
stop a running Postgres service
# usage
dokku postgres:stop <service>
Stop the service and removes the running container:
dokku postgres:stop lollipop
pause a running Postgres service
# usage
dokku postgres:pause <service>
Pause the running container for the service:
dokku postgres:pause lollipop
graceful shutdown and restart of the Postgres service container
-c|--config-options <string>: extra arguments for the process the service container runs, not docker flags; use mount for mounts
-C|--custom-env <string>: semi-colon delimited environment variables to start the service with
--definition <string>: the definition to move the service onto, instead of the one its image and version resolve to
-i|--image <string>: the image to upgrade the service to
-I|--image-version <string>: the image version to upgrade the service to
-N|--initial-network <string>: the initial network to attach the service to
--log-driver <string>: the docker logging driver to run the service container with (default: the daemon's own)
--log-opt <strings>: a comma-separated list of key=value docker log options for the service container
-m|--memory <int>: container memory limit in megabytes, 0 for unlimited
-P|--post-create-network <strings>: a comma-separated list of networks to attach the service container to after service creation
-S|--post-start-network <strings>: a comma-separated list of networks to attach the service container to after service start
--restart <string>: the docker restart policy to run the service container with (default: always)
-R|--restart-apps: whether to stop and start the linked apps around the upgrade
-s|--shm-size <string>: override shared memory size for the service docker container
--volume <stringArray>: a host path or docker volume to mount into the service container, as :[:], repeatable
--volume-target <stringArray>: mount one of the definition's volumes at another container path, as =, repeatable
--wait-timeout <string>: seconds to wait for the service to become ready (default: the datastore's own)
You can upgrade an existing service to a new image or image-version:
dokku postgres:upgrade lollipop
This is the only command that changes the version a service runs. With no version named it moves to the newest the service's own major version ships, which leaves the data where it is.
Moving across a major version has to be asked for by name, because it is not a tag change: the data is mounted somewhere different under the new one, and pointing the version back does not undo it. A service can also be moved onto a definition by name, with --image and --image-version laid over the image and version it ships. This moves where the data is mounted in the same way, even when the image stays the same.
A service keeps the mounts it has unless --volume is passed, which replaces them, and each one is checked against the new container before the old one is taken away.
A service keeps the volume targets it has unless --volume-target is passed, which replaces them, and an upgrade onto a definition that does not mount a volume the service moved is refused before the old container is taken away. --volume-target "" puts every volume back where the new definition mounts it.
A service keeps its memory limit unless --memory is passed, and --memory 0 removes it.
dokku postgres:upgrade lollipop --memory 512
Postgres does not handle upgrading data for major versions automatically (eg. 11 => 12). Upgrades should be done manually. Users are encouraged to upgrade to the latest minor release for their postgres version before performing a major upgrade.
While there are many ways to upgrade a postgres database, for safety purposes, it is recommended that an upgrade is performed by exporting the data from an existing database and importing it into a new database. This also allows testing to ensure that applications interact with the database correctly after the upgrade, and can be used in a staging environment.
The following is an example of how to upgrade a postgres database named lollipop-11 from 11.13 to 12.8.
# stop any linked apps
dokku ps:stop linked-app
# export the database contents
dokku postgres:export lollipop-11 > /tmp/lollipop-11.export
# create a new database at the desired version
dokku postgres:create lollipop-12 --image-version 12.8
# import the export file
dokku postgres:import lollipop-12 < /tmp/lollipop-11.export
# run any sql tests against the new database to verify the import went smoothly# unlink the old database from your apps
dokku postgres:unlink lollipop-11 linked-app
# link the new database to your apps
dokku postgres:link lollipop-12 linked-app
# start the linked apps again
dokku ps:start linked-app
Service Automation
Service scripting can be executed using the following commands:
list all Postgres service links for a given app
# usage
dokku postgres:app-links [<app>]
List all postgres services that are linked to the playground app.
-c|--config-options <string>: extra arguments for the process the service container runs, not docker flags; use mount for mounts
-C|--custom-env <string>: semi-colon delimited environment variables to start the service with
-N|--initial-network <string>: the initial network to attach the service to
--log-driver <string>: the docker logging driver to run the service container with (default: the daemon's own)
--log-opt <strings>: a comma-separated list of key=value docker log options for the service container
-m|--memory <int>: container memory limit in megabytes (default: unlimited)
-p|--password <string>: override the user-level service password, for datastores that have one
-P|--post-create-network <strings>: a comma-separated list of networks to attach the service container to after service creation
-S|--post-start-network <strings>: a comma-separated list of networks to attach the service container to after service start
--restart <string>: the docker restart policy to run the service container with (default: always)
-r|--root-password <string>: override the root-level service password, for datastores that have one
-s|--shm-size <string>: override shared memory size for the service docker container
--volume <stringArray>: a host path or docker volume to mount into the service container, as :[:], repeatable
--volume-target <stringArray>: mount one of the definition's volumes at another container path, as =, repeatable
--wait-timeout <string>: seconds to wait for the service to become ready (default: the datastore's own)
You can clone an existing service to a new one:
dokku postgres:clone lollipop lollipop-2
The new service starts from the settings of the one it copies: its config options, custom env, memory, shm size, networks, log driver, log options, restart policy, mounts, volume targets, backup keyserver and backup storage class. A flag passed to clone overrides that one setting, and a flag passed empty clears it:
dokku postgres:clone lollipop lollipop-2 --restart no --custom-env ""
The password, exposed ports, links and backup credentials, schedule and encryption are not copied. The clone's passwords are generated unless they are given.
Note that the export will result in a file containing the binary postgres export data. It can be converted to plain text using pg_restore as follows
pg_restore data.dump -f plain.sql
Backups
Datastore backups are supported via AWS S3 and S3 compatible services like minio.
You may skip the backup-auth step if your dokku install is running within EC2 and has access to the bucket via an IAM profile. In that case, use the --use-iam option with the backup command.
If both passphrase and public key forms of encryption are set, the public key encryption will take precedence.
Backups are uploaded with the bucket's default storage class unless the service sets the backup-storage-class property with the set command.
The underlying core backup script is present here.
Scheduled backups are added to the dokku crontab, and are listed by dokku cron:list --global.
Backups can be performed using the backup commands:
set up authentication for backups on the Postgres service
-u|--use-iam: use the IAM profile associated with the current server
Schedule a backup:
'schedule' is a crontab expression, eg. "0 3 * * *" for each day at 3am, or a descriptor such as "@daily". A schedule cron cannot run is refused.
the backup is added to the dokku crontab through the cron-entries plugin trigger, so it is listed by "dokku cron:list --global" and its output is appended to /var/log/dokku/postgres.log
NOTE: dokku only writes a crontab when the global scheduler or at least one app uses the docker-local scheduler, so a scheduled backup does not run on a host that only uses k3s or null
Remove the scheduled backup from the dokku crontab:
dokku postgres:backup-unschedule lollipop
Custom Commands
This datastore adds the following commands of its own:
print the certificate the Postgres service encrypts connections with
# usage
dokku postgres:certificate <service>
Print the certificate the Postgres service encrypts connections with:
NOTE: the service must be running
dokku postgres:certificate lollipop
Save it to verify the server from a client off the host:
dokku postgres:certificate lollipop > server.crt
Limiting where and to whom a service is exposed
An exposed service's ports are published on every interface unless they are given an address of their own. To publish them on one address instead, set the service's port-bind-address property with dokku postgres:set, and to accept connections only from clients in one IP address or CIDR, set its port-source-range property. Either reaches a running service with dokku postgres:reexpose, which leaves the service running when its ports are published through an ambassador.
Only one source range can be given. The range is checked against the address a connection reaches the service from, which for a connection to the exposed port on the loopback interface, or an IPv6 connection to a service network without IPv6, is the docker network's gateway rather than the client, so with a range that leaves the gateway out, connecting to 127.0.0.1 from the dokku host itself is refused.
Exposing a service without an ambassador
An exposed service's ports are published by an ambassador, a container that relays every connection on to the service. The ambassador can be replaced without touching the service and can hold clients to a port-source-range, but relaying adds latency to every request.
To publish the ports on the service container itself instead, set the service's expose-mode property to direct with dokku postgres:set. Docker has no way of changing the ports a container publishes, so the container is made again whenever what it publishes changes: when the service is exposed or unexposed, when its port-bind-address changes, and when it moves between expose modes. For a running service, dokku postgres:expose, dokku postgres:unexpose and dokku postgres:reexpose ask before stopping and starting it, and change nothing if the answer is no. Pass --force to stop and start it without being asked. A change also reaches the service the next time it is restarted, or stopped and started.
A port-source-range cannot be enforced on a port the service container publishes itself, so it cannot be set on a service exposed directly, and a service with one cannot be exposed directly.
Connecting to an exposed service from outside the host
dokku postgres:info lollipop --exposed-dsn prints the dsn a client off the dokku host connects with. It is the dsn a linked app is handed, with the exposed ports in place of the container's and a public host in place of the service container's name, so it carries the same credentials. The host is the service's expose-host property, set with dokku postgres:set, or the first global domain when it has none. The port-bind-address, or an address given with a port, is never used as the host, since it is where the port is bound rather than where a client elsewhere reaches it. The dsn is empty until the service is exposed and there is a host to name.
Passing extra arguments to export and import
Arguments given to export or import after -- are appended to the ones the datastore's own tool is run with, for that run alone. To use them every time, set the service's export-args or import-args property with dokku postgres:set, giving the value after -- so that its leading dash is not read as a flag. The property is split the way a shell would split it, so an argument with a space in it is quoted, and a variable in it is refused rather than expanded.
Arguments given after -- replace the property rather than adding to it. Backups and clones are made with the property, and a clone is given the source's.
Waiting for a service to become ready
A service is waited on until it answers on its port after it is created, cloned, started, restarted, upgraded or exposed. If it takes longer than that to start - on a slow host, or with an image that does more on its first boot - the command fails with ERROR: unable to connect.
To wait longer for every postgres service on the host, set the POSTGRES_WAIT_TIMEOUT environment variable to a number of seconds. To wait longer for a single service, set its wait-timeout property with dokku postgres:set or pass --wait-timeout to create, clone or upgrade. The service's own setting is used first, then the environment variable, then the datastore's default.
Moving where a service's volumes are mounted
Each volume a service mounts is named by the directory it lives in under the service's own directory, and is mounted where the datastore's definition says. To mount one somewhere else in the container, for an image that keeps its data at another path, set the service's volume-targets property with dokku postgres:set, pass --volume-target to create, clone or upgrade, or set the POSTGRES_VOLUME_TARGETS environment variable before create. Each is written as <volume>=<container-path>, several separated by spaces, and dokku postgres:info lollipop --volume-targets shows the ones a service moved.
Definition
Volume
Mounted at
postgres-17
data
/var/lib/postgresql/data
postgres-17
certs
/certs
postgres-18
data
/var/lib/postgresql
postgres-18
certs
/certs
postgres-pgvector-pg17
data
/var/lib/postgresql/data
postgres-pgvector-pg17
certs
/certs
postgres-pgvector-pg18
data
/var/lib/postgresql
postgres-pgvector-pg18
certs
/certs
postgres-postgis-pg17
data
/var/lib/postgresql/data
postgres-postgis-pg17
certs
/certs
postgres-postgis-pg18
data
/var/lib/postgresql
postgres-postgis-pg18
certs
/certs
postgres-timescaledb-pg17
data
/var/lib/postgresql/data
postgres-timescaledb-pg17
certs
/certs
postgres-timescaledb-pg18
data
/var/lib/postgresql
postgres-timescaledb-pg18
certs
/certs
Moving a volume changes where it is mounted, not where the image reads and writes. The datastore's own commands and the paths it is started with follow the volume, but an image that keeps writing to its own path writes into the container rather than into the volume, and what it writes is lost when the container is rebuilt, so only move a volume to where the image expects its data. The data stays in the same directory on the host, and a move reaches the container the next time one is built, so use dokku postgres:stop and then dokku postgres:start on a running service. An upgrade onto a definition that does not mount a volume the service moved is refused until the move is cleared or replaced.
Reserved service names
A service's database is named after the service, with hyphens replaced by underscores. So that an app is never handed a database Postgres keeps for itself, dokku postgres:create and dokku postgres:clone refuse a name that is, or whose database would be, one of template0, template1, in any case. A service that already has such a name is not affected.
Encrypting connections with TLS
Every Postgres service is created with a self-signed certificate, and the server encrypts any connection whose client asks it to. The certificate and its key are kept in /var/lib/dokku/services/postgres/lollipop/certs, and are kept when the service is rebuilt or upgraded. Clients such as psql ask for an encrypted connection by default, but fall back to an unencrypted one when the server does not offer it. To refuse an unencrypted connection instead, add sslmode=require to the dsn the service is exposed at:
To also check that the client is talking to this service, save its certificate and have the client verify the server with it. The certificate names no host, so sslmode=verify-ca works where sslmode=verify-full does not:
To use a certificate of your own, write it and its key over the ones the service was created with as root, and restart the service. Writing over the files rather than replacing them keeps the owner and mode the server needs to read its key:
sudo sh -c 'cat server.crt > /var/lib/dokku/services/postgres/lollipop/certs/server.crt'
sudo sh -c 'cat server.key > /var/lib/dokku/services/postgres/lollipop/certs/server.key'
dokku postgres:restart lollipop
Disabling docker image pull calls
If you wish to disable the docker image pull calls that the plugin triggers, you may set the POSTGRES_DISABLE_PULL environment variable to true. Once disabled, you will need to pull the service image you wish to deploy as shown in the stderr output.
Please ensure the proper images are in place when docker image pull is disabled.