Minimal Alpine container for the Ente CLI with configurable loop or cron scheduling for automated exports.
Built from source on every push via GitHub Actions and published to Docker Hub.
- Static
ente-clibinary built from the latestente-io/entesource - Loop-based scheduled exports by default
- Optional Alpine BusyBox cron scheduling (configurable via environment variables or a mounted crontab)
- Minimal image (~15 MB, Alpine + binary + BusyBox crond)
- No CGO dependencies
# Create directories
mkdir -p cli-data export
# Start
docker compose up -d
# One-time login
docker exec -it ente-cli /usr/local/bin/ente-cli account addThe following examples use the same data volumes and differ only in the
scheduler configuration. Use one of them as your compose.yaml.
This is the default. It runs an export immediately when the container starts, then waits six hours between runs.
services:
ente-cli:
image: wittchy/ente-cli:${IMAGE_TAG:-latest}
container_name: ente-cli
restart: unless-stopped
environment:
SCHEDULER: loop
LOOP_INTERVAL: 21600
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
- ${ENTE_DATA_PATH}/cli-data:/cli-data:rw
- ${ENTE_DATA_PATH}/data:/data:rw
networks:
- proxy
networks:
proxy:
external: trueThis uses Alpine BusyBox crond and runs exports at the scheduled clock times.
The container generates its crontab from CRON_SCHEDULE.
Cron runs one export immediately at container startup, then waits for the next
matching clock time. A schedule such as 0 */6 * * * therefore runs once on
startup and subsequently at six-hour boundaries.
services:
ente-cli:
image: wittchy/ente-cli:${IMAGE_TAG:-latest}
container_name: ente-cli
restart: unless-stopped
environment:
SCHEDULER: cron
CRON_SCHEDULE: "0 */6 * * *"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
- ${ENTE_DATA_PATH}/cli-data:/cli-data:rw
- ${ENTE_DATA_PATH}/data:/data:rw
networks:
- proxy
networks:
proxy:
external: trueFor the loop scheduler, set the interval in seconds:
environment:
SCHEDULER: loop
LOOP_INTERVAL: 21600For the cron scheduler, set a standard five-field cron expression:
environment:
SCHEDULER: cron
CRON_SCHEDULE: "0 */6 * * *"In cron mode, the container creates /etc/crontabs/root from
CRON_SCHEDULE when that file does not already exist. To manage the complete
crontab yourself, mount it at that path:
environment:
SCHEDULER: cron
volumes:
- ${ENTE_CRONTAB_PATH}:/etc/crontabs/root:roThe mounted file must contain the full BusyBox crontab entry, including the command. For example:
| Schedule | Crontab line |
|---|---|
| Daily at 2 AM | 0 2 * * * /entrypoint.sh --run-export >> /proc/1/fd/1 2>&1 |
| Every 6 hours | 0 */6 * * * /entrypoint.sh --run-export >> /proc/1/fd/1 2>&1 |
| Every 30 minutes | */30 * * * * /entrypoint.sh --run-export >> /proc/1/fd/1 2>&1 |
Full format:
0 */6 * * * /entrypoint.sh --run-export >> /proc/1/fd/1 2>&1
crond runs in the foreground in cron mode, so it remains the container's
main process. BusyBox scheduler diagnostics and both scheduler modes' export
start message, command output, and completion message are written to standard
output, so they are visible in Docker, Portainer, and Arcane live logs. BusyBox
cron uses the container's timezone; configure the timezone if local-time
scheduling is required.
At startup, the container also logs the selected scheduler, for example:
Selected scheduler: loop (every 21600 seconds)
or:
Selected scheduler: cron
Starting Alpine BusyBox crond in foreground (logging to stdout)...
# List accounts
docker exec -it ente-cli /usr/local/bin/ente-cli account list
# Run an export manually
docker exec -it ente-cli /usr/local/bin/ente-cli export
| Path | Purpose |
|---|---|
/cli-data |
Account credentials & config (persist across restarts) |
/data |
Export destination (decrypted files) |
/etc/crontabs/root |
Optional cron schedule (mounted read-only) |
The image is built automatically by GitHub Actions on every push to main and pushed to wittchy/ente-cli:latest on Docker Hub.
To build locally:
docker build -t wittchy/ente-cli:latest .- Exports are decrypted on disk — protect the
/dataand/cli-datavolumes - Back up
/cli-datato avoid re-authenticating - Do not expose the Docker host or Portainer to the internet
The ente-cli binary is licensed under AGPL-3.0.