A Docker container which runs the Joplin terminal client as a daemon with its web clipper service exposed on port 80.1
Synchronization, encryption, and other Joplin parameters may be configured by mounting a JSON config file to /run/secrets/joplin-config.json
or equivalently by creating a secret named joplin-config.json
in a docker-compose.yml
file.
Try out one of the tagged images from the container registry:
docker run --rm -p 3000:80 --name my_joplin_container jspiers/headless-joplin:2.12.1-node-18.18.0
Then, in another terminal, check that the Joplin Clipper server (i.e. Data API) is running from your host's command-line:
curl http://localhost:3000/ping
You should get a response of JoplinClipperServer
.
You can also open the Joplin terminal client running on the container to interactively view/edit notes:
docker exec -it my_joplin_container joplin
When done, stop the container by typing Ctrl-C. Because we specified the --rm
option when invoking docker run
above, the container is automatically deleted.
To persist Joplin data between runs of the Docker container, mount a volume at /home/node/.config/joplin
:
docker run --rm -p 3000:80 --name my_joplin_container -v joplin-data:/home/node/.config/joplin jspiers/headless-joplin:2.12.1-node-18.18.0
Set JOPLIN_LOG_ENABLED=true
to tell the container to display the contents of Joplin's log file (log.txt
) in the Docker logs in real time.
docker run --rm -p 3000:80 --name my_joplin_container -e JOPLIN_LOG_ENABLED=true jspiers/headless-joplin:2.12.1-node-18.18.0
The Joplin terminal client includes commands for importing and exporting its settings in JSON format:
joplin config --export > json-config.json
And then in another joplin instance:
joplin config --import-file json-config.json
See the official Joplin terminal documentation for supported JSON key/value pairs. Note: there are also several unofficial configuration keys, which can be exported/observed by adding the '-v' flag to the export command: joplin config --export -v
. For example, the encryption master password can be set via encryption.masterPassword
.
headless-joplin
leverages the Joplin terminal client's JSON configuration functionality to configure Joplin via three files:
- default settings suitable for most envisioned scenarios;
- an optional JSON configuration file which can either be provided as a Docker secret with the name
json-config.json
, or equivalently, by mounting a JSON file at a location specified via theJOPLIN_CONFIG_JSON
environment variable, which defaults to/run/secrets/joplin-config.json
; and - required settings expected by
headless-joplin
for its correct operation.2
For example, to load a joplin-config.json
file from your current directory:
docker run --rm -p 3000:80 --name my_joplin_container -v ${PWD}/joplin-config.json:/run/secrets/joplin-config.json jspiers/headless-joplin:2.12.1-node-18.18.0
In particular, consider specifying api.token
override the default value for the sake of security.
For most scenarios, it is more convenient to configure a headless-joplin
container via a docker-compose.yml
file.
See the examples subdirectory for docker-compose.yml
files suitable for a few scenarios.
If you clone the repo, you can also build the Docker image yourself:
docker build . -t headless-joplin
docker run --rm -p 3000:80 headless-joplin
docker build . -t headless-joplin --build-arg JOPLIN_VERSION=2.3.2 --build-arg NODE_VERSION=16
Joplin version should be set to one of the official joplin NPM package versions.
Node version should be one of the official node Docker image tags.
Just run the following in the root directory of the repo:
docker compose build
Communication with the headless-joplin
Data API on its exposed port 80 is via insecure HTTP. As such, care should be taken not to expose this port to public networks. The intended usage of headless-joplin
is to communicate with other containers via an internal network (e.g. declared with internal: true
in a docker-compose.yml
).
For scenarios where the headless-joplin
Data API is to be accessed via a public network, a reverse-proxy sidecar container (i.e. nginx, traefik, or Caddy) could be used to secure the connection.
The default configuration sets the api.token
to a value of mytoken
. This should be set to a secret value provided to the container via a JSON config file.
Footnotes
-
Because the Joplin terminal client Clipper Server is hard-coded to bind to localhost
127.0.0.1
, theheadless-joplin
container includes a background socat service which redirects to that localhost port from the container's external port0.0.0.0:80
↩ -
Special note regarding
sync.interval
: When running in server mode, the Joplin terminal client does not (as of Joplin version 2.12.1) perform any synchronization of its own, even if thesync.interval
is set to a non-zero value. To account for this, theheadless-joplin
container is designed to read thesync.interval
value from either the defaults or the user-provided JSON config file, and periodically invoke thejoplin sync
command as a background process. ↩