Transform any Docker container into a native desktop application using Tauri.
Dock2Tauri is a lightweight bridge that allows you to run any Docker container as a native desktop application. It provides a modern control panel interface and multiple ways to launch containerized applications with unified CLI across Bash, Python, and Node.js launchers.
--cross
)--config
; no mutations to src-tauri/tauri.conf.json
One-liner installation:
git clone https://github.com/digitaltwin-run/dock2tauri.git && cd dock2tauri && make install-deps YES=1
Quick usage:
./scripts/dock2tauri.sh nginx:alpine 8088 80
OR
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 --build
Full installation example:
git clone https://github.com/digitaltwin-run/dock2tauri.git
cd dock2tauri
make install
Cloning into 'dock2tauri'...
remote: Enumerating objects: 355, done.
remote: Counting objects: 100% (355/355), done.
remote: Compressing objects: 100% (248/248), done.
remote: Total 355 (delta 170), reused 281 (delta 96), pack-reused 0 (from 0)
Receiving objects: 100% (355/355), 628.14 KiB | 1.86 MiB/s, done.
Resolving deltas: 100% (170/170), done.
\033[0;34m๐ง Installing Dock2Tauri...\033[0m
\033[1;33mโ ๏ธ Rust not found. Installing...\033[0m
info: downloading installer
info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-gnu
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
927.4 KiB / 927.4 KiB (100 %) 866.4 KiB/s in 1s
info: latest update on 2025-08-07, rust version 1.89.0 (29483883e 2025-08-04)
info: downloading component 'cargo'
9.7 MiB / 9.7 MiB (100 %) 417.0 KiB/s in 16s
info: downloading component 'clippy'
4.3 MiB / 4.3 MiB (100 %) 381.6 KiB/s in 13s
info: downloading component 'rust-docs'
20.2 MiB / 20.2 MiB (100 %) 559.4 KiB/s in 52s
info: downloading component 'rust-std'
27.6 MiB / 27.6 MiB (100 %) 374.4 KiB/s in 1m 8s
info: downloading component 'rustc'
78.1 MiB / 78.1 MiB (100 %) 289.2 KiB/s in 3m 51s
info: downloading component 'rustfmt'
2.2 MiB / 2.2 MiB (100 %) 1.8 MiB/s in 1s
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
20.2 MiB / 20.2 MiB (100 %) 4.5 MiB/s in 3s
info: installing component 'rust-std'
27.6 MiB / 27.6 MiB (100 %) 19.6 MiB/s in 1s
info: installing component 'rustc'
78.1 MiB / 78.1 MiB (100 %) 21.5 MiB/s in 3s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'
stable-x86_64-unknown-linux-gnu installed - rustc 1.89.0 (29483883e 2025-08-04)
Rust is installed now. Great!
To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).
To configure your current shell, you need to source
the corresponding env file under $HOME/.cargo.
This is usually done by running one of the following (note the leading DOT):
. "$HOME/.cargo/env" # For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish" # For fish
source $"($nu.home-path)/.cargo/env.nu" # For nushell
\033[1;33m๐ฆ Installing Tauri CLI...\033[0m
/bin/sh: line 3: cargo: command not found
make: *** [Makefile:39: install] Error 127
โน๏ธ Building Docker image from ./examples/pwa-notes/Dockerfile (context: ./examples/pwa-notes) as dock2tauri-local-dockerfile-1755456008 ...
[+] Building 12.4s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 264B 0.0s
=> [internal] load metadata for docker.io/library/nginx:alpine 2.3s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/3] FROM docker.io/library/nginx:alpine@sha256:2459838ed006e699c252db374550c91490068bbf3b35fa8b9d29bfe0e31b8b95 9.7s
=> => resolve docker.io/library/nginx:alpine@sha256:2459838ed006e699c252db374550c91490068bbf3b35fa8b9d29bfe0e31b8b95 0.0s
=> => sha256:2459838ed006e699c252db374550c91490068bbf3b35fa8b9d29bfe0e31b8b95 10.33kB / 10.33kB 0.0s
=> => sha256:60e48a050b6408d0c5dd59b98b6e36bf0937a0bbe99304e3e9c0e63b7563443a 2.50kB / 2.50kB 0.0s
=> => sha256:6bc572a340ecbc60aca0c624f76b32de0b073d5efa4fa1e0b6d9da6405976946 1.81MB / 1.81MB 2.0s
=> => sha256:403e3f251637881bbdc5fb06df8da55c149c00ccb0addbcb7839fa4ad60dfd04 628B / 628B 0.4s
=> => sha256:4a86014ec6994761b7f3118cf47e4b4fd6bac15fc6fa262c4f356386bbc0e9d9 10.78kB / 10.78kB 0.0s
=> => sha256:9824c27679d3b27c5e1cb00a73adb6f4f8d556994111c12db3c5d61a0c843df8 3.80MB / 3.80MB 3.1s
=> => sha256:9adfbae99cb79774fdc14ca03a0a0154b8c199a69f69316bcfce64b07f80719f 955B / 955B 1.0s
=> => sha256:7a8a46741e18ed98437271669138116163f14596f411c1948fd7836e39f1afea 405B / 405B 1.4s
=> => sha256:c9ebe2ff2d2cd981811cefb6df49a116da6074c770c07ee86a6ae2ebe7eee926 1.21kB / 1.21kB 1.8s
=> => sha256:a992fbc61ecc9d8291c27f9add7b8a07d374c06a435d4734519b634762cf1c51 1.40kB / 1.40kB 2.2s
=> => sha256:cb1ff4086f82493a4b8b02ec71bfed092cad25bd5bf302aec78d4979895350cb 16.84MB / 16.84MB 9.3s
=> => extracting sha256:9824c27679d3b27c5e1cb00a73adb6f4f8d556994111c12db3c5d61a0c843df8 0.4s
=> => extracting sha256:6bc572a340ecbc60aca0c624f76b32de0b073d5efa4fa1e0b6d9da6405976946 0.0s
=> => extracting sha256:403e3f251637881bbdc5fb06df8da55c149c00ccb0addbcb7839fa4ad60dfd04 0.0s
=> => extracting sha256:9adfbae99cb79774fdc14ca03a0a0154b8c199a69f69316bcfce64b07f80719f 0.0s
=> => extracting sha256:7a8a46741e18ed98437271669138116163f14596f411c1948fd7836e39f1afea 0.0s
=> => extracting sha256:c9ebe2ff2d2cd981811cefb6df49a116da6074c770c07ee86a6ae2ebe7eee926 0.0s
=> => extracting sha256:a992fbc61ecc9d8291c27f9add7b8a07d374c06a435d4734519b634762cf1c51 0.0s
=> => extracting sha256:cb1ff4086f82493a4b8b02ec71bfed092cad25bd5bf302aec78d4979895350cb 0.2s
=> [internal] load build context 0.0s
=> => transferring context: 3.01kB 0.0s
=> [2/3] RUN rm -rf /usr/share/nginx/html/* 0.2s
=> [3/3] COPY app /usr/share/nginx/html 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:373e206df2a793df17d81f3418a59a5bc5edb1c80559b5055e1eccb43f191b19 0.0s
=> => naming to docker.io/library/dock2tauri-local-dockerfile-1755456008 0.0s
๐ณ๐ฆ Dock2Tauri - Docker to Desktop Bridge
==================================================
โน๏ธ Checking dependencies...
โ ๏ธ Rust/Cargo not found. Some features may not work.
โ
Dependencies check passed
โน๏ธ Preparing Tauri configuration (ephemeral)...
โ ๏ธ rpmbuild not found; skipping RPM bundle.
โ ๏ธ linuxdeploy/appimagetool not found; skipping AppImage bundle.
โ
Ephemeral Tauri configuration prepared at /tmp/tauri.conf.G6Bnui.json
โน๏ธ Building Tauri release bundles (multi-target export)...
โน๏ธ Checking for existing dock2tauri RPM packages...
โน๏ธ No existing dock2tauri packages found
โน๏ธ Building bundles for target: native ...
./scripts/dock2tauri.sh: line 465: cargo: command not found
โ ๏ธ Build failed for native target; exporting any bundles produced before failure.
โ ๏ธ No bundles found at ./dock2tauri/src-tauri/target/release/bundle
โน๏ธ Cross-target builds disabled by default. Use --cross to attempt them.
โ
All available bundles exported to: /dock2tauri/dist
โน๏ธ Cleaning up...
โ
Removed ephemeral Tauri config
If you prefer a single script to prepare your environment (system packages, Rust + Tauri CLI, and optionally Docker), use the installer:
# Install all dev dependencies required by Tauri/WebKitGTK
./scripts/install.sh
# Additionally install and enable Docker, and add current user to the docker group
./scripts/install.sh --with-docker
What it does:
After installation:
newgrp docker
docker --version
cargo --version
cargo tauri --version
Troubleshooting:
.pc
files (e.g. libsoup-2.4.pc
, javascriptcoregtk-4.0.pc
), ensure the dev packages above are installed by the script.PKG_CONFIG_PATH
to include the directory with the .pc
files, e.g.:export PKG_CONFIG_PATH=/custom/pc/dir:$PKG_CONFIG_PATH
Install AppImage tools (linuxdeploy, appimagetool) and FUSE runtime; optionally RPM tooling. Complements scripts/install.sh
.
# Install core deps + AppImage tools for current user (~/.local/bin)
./scripts/setup.sh
# System-wide AppImage tools (requires sudo) and RPM tooling
./scripts/setup.sh --system --rpm
# Include Docker installation via core installer
./scripts/setup.sh --with-docker
# Only AppImage tools (skip core deps)
./scripts/setup.sh --skip-core
Notes:
libfuse2
(installed by the script).linuxdeploy
and appimagetool
on PATH.rpmbuild
(Fedora: rpm-build
; Debian/Ubuntu: rpm
).For more granular control over system dependencies, use the new Makefile targets:
# Install system bundling dependencies only (no Rust/Tauri CLI)
make install-deps
# With AppImage tools and ARM64 cross toolchain
make install-deps APPIMAGE=1 ARM64=1 YES=1
# Dry-run (show what would be installed without changes)
make install-deps-dry-run
make install-deps-dry-run APPIMAGE=1 ARM64=1 YES=1
# Validate install scripts (syntax check + dry-run)
make test-install
Configuration flags:
APPIMAGE=1
โ Install linuxdeploy
and appimagetool
(optional, often fails without FUSE)ARM64=1
โ Install ARM64 cross toolchain (gcc-aarch64-linux-gnu
, pkg-config-aarch64-linux-gnu
)YES=1
โ Non-interactive mode (assume yes to prompts)The install script detects your package manager (apt/dnf/yum/pacman/zypper) and installs appropriate packages for Tauri bundling on Linux:
dpkg-deb
is usually available)rpm
/rpmbuild
)ARM64 cross-compilation notes: After installing ARM64 toolchain, you may need ARM64 dev libraries:
# Debian/Ubuntu multiarch setup
sudo dpkg --add-architecture arm64
sudo apt update
sudo apt install -y libgtk-3-dev:arm64 libglib2.0-dev:arm64 libpango1.0-dev:arm64 libcairo2-dev:arm64 libgdk-pixbuf-2.0-dev:arm64
# Set environment for ARM64 builds
export PKG_CONFIG=aarch64-linux-gnu-pkg-config
export PKG_CONFIG_SYSROOT_DIR=/
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig
Comprehensive documentation is available in the docs/
directory:
Dock2Tauri has received major enhancements for stability and user experience:
DOCK2TAURI_FORCE_APPIMAGE=1
)DOCK2TAURI_CROSS_TARGETS="x,y,z"
scripts/install_deps.sh
) supporting apt, dnf, yum, pacman, zyppermake install-deps APPIMAGE=1 ARM64=1 YES=1
Dock2Tauri provides convenient Makefile targets for common operations:
make help # Show all available commands with descriptions
make status # Display system status (Docker, Rust, Tauri, etc.)
make install # Full installation (Rust, Tauri CLI, system dependencies)
make install-deps # Install system bundling dependencies only
make install-deps-dry-run # Preview dependency installation
make test-install # Validate installation scripts
make nginx # Launch Nginx web server (port 8088)
make grafana # Launch Grafana dashboard (port 3001)
make jupyter # Launch Jupyter notebook (port 8888)
make portainer # Launch Portainer Docker UI (port 9000)
# Custom launch with parameters
make launch IMAGE=redis:alpine HOST_PORT=6379 CONTAINER_PORT=6379
make dev # Start development mode with hot reload
make build # Build production bundles
make run # Run latest built application (auto-detects OS and package type)
# Comprehensive Testing Suite
make test # Run all launcher tests (Bash, Python, Node.js)
make test-bash # Test Bash script validation and integration
make test-python # Test Python workflow automation
make test-rust # Test Rust backend Tauri commands
make test-playwright # Test UI interactions with Playwright (E2E)
make test-cypress # Test UI with Cypress (alternative E2E)
make test-all # Run complete test suite including E2E
# Docker Isolated Testing
make test-docker-build # Build Docker test environment
make test-docker # Run all tests in clean Docker container
make test-docker-shell # Open interactive shell in test container
# Test Setup and Maintenance
make test-setup # Install test dependencies (Playwright browsers, etc.)
make test-clean # Clean test outputs and dependencies
make list # List active dock2tauri containers
make logs # Show container logs
make stop-all # Stop and remove all dock2tauri containers
make clean # Clean build artifacts and stop containers
make examples # Show detailed usage examples
make help # List all available commands
Dock2Tauri now features a comprehensive .env-based configuration system for consistent settings across all components.
Copy .env.example
to .env
and customize as needed:
cp .env.example .env
Key configuration options:
# Development Configuration
DEV_PORT=8081 # Development server port
BUILD_TIMEOUT=600 # Build timeout in seconds
# Output and Naming Customization
OUTPUT_DIR=./dist # Custom output directory for binaries
CUSTOM_APP_NAME="" # Override auto-generated app name
CUSTOM_FILENAME="" # Custom filename prefix for packages
ADDITIONAL_OUTPUT_DIRS="" # Additional copy locations (comma-separated)
# RPM Package Management
RPM_CLEANUP_AUTO=true # Automatically remove conflicting packages
RPM_FORCE_INSTALL=true # Force RPM installation
# Docker Testing
TEST_TIMEOUT=300 # Test execution timeout
TEST_PARALLEL=true # Enable parallel test execution
All launchers now support custom binary paths and naming:
# Custom output directory and app name
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build \
--output-dir="/home/user/builds" \
--app-name="NginxDesktop"
# Custom filename prefix and multiple copy locations
./scripts/dock2tauri.sh grafana/grafana 3001 3000 --build \
--filename="grafana-v1" \
--copy-to="/opt/apps,/usr/local/bin"
# Complete customization example
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 --build \
--app-name="NotesApp" \
--filename="notes-desktop" \
--output-dir="/tmp/my-builds" \
--copy-to="/home/user/apps,/opt/dock2tauri"
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 โbuild
โapp-name=โNotesAppโ
โfilename=โnotes-desktopโ
โoutput-dir=โ/tmp/my-buildsโ
โcopy-to=โ/home/tom/buildsโ
check build files
ls -la /home/tom/builds
Dock2Tauri supports three main run modes across all launchers:
Runs cargo tauri dev
for development with hot reload:
./scripts/dock2tauri.sh nginx:alpine 8088 80
Builds distributable bundles (AppImage, .deb, .rpm, .msi, .dmg):
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build
On Linux, bundles are generated conditionally based on available system tools:
.deb
requires dpkg-deb
.rpm
requires rpmbuild
.AppImage
requires linuxdeploy
and appimagetool
If none are available, bundling is skipped to avoid failures.Builds for specific target architectures:
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build --target=x86_64-pc-windows-gnu
Enable best-effort cross-target builds with --cross
(Bash launcher). Cross builds require proper toolchains/sysroots and may fail without additional setup.
.env.example
template with automatic loading and defaultsOUTPUT_DIR
) and filename prefixes (CUSTOM_FILENAME
)CUSTOM_APP_NAME
for branded deploymentsADDITIONAL_OUTPUT_DIRS
# New command-line arguments for flexible workflows
--output-dir=/path/to/builds # Custom output directory
--app-name="CustomAppName" # Override app name
--filename="custom-prefix" # Custom filename prefix
--copy-to="/opt/apps,/usr/bin" # Copy to multiple locations
Dockerfile.test
)tauri.conf.json
syntax and HTTP server configurationThis repo ships with simple single-file PWA examples for validation and demos:
examples/pwa-hello/
examples/pwa-counter/
examples/pwa-notes/
Build and export bundles directly from a Dockerfile (served by nginx:alpine
):
# Development mode (default) - opens Tauri app window
./scripts/dock2tauri.sh ./examples/pwa-hello/Dockerfile 8088 80
./scripts/dock2tauri.sh ./examples/pwa-counter/Dockerfile 8089 80
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8090 80
# Build production bundles (.deb, .rpm, etc.)
./scripts/dock2tauri.sh ./examples/pwa-hello/Dockerfile 8088 80 --build
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 --build
# Build with cross-compilation (requires toolchains)
./scripts/dock2tauri.sh ./examples/pwa-hello/Dockerfile 8088 80 --build --cross
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 --build --cross
Note:
--build
is NOT provided, the Bash launcher defaults to building and exporting bundles into dist/
--cross
) automatically skips problematic targets and AppImage in cross-build modeDock2Tauri-dock2tauri-local-dockerfile-...
All three launchers (Bash, Python, Node.js) now support the same flags and functionality:
--build
/ -b
: Build Tauri release bundles instead of dev mode--target=<triple>
: Specify target architecture for cross-compilation--cross
(Bash only): Attempt best-effort cross-target builds (requires toolchains; may fail)--help
/ -h
: Show help information--health-url=<url>
: Override readiness URL (default: http://localhost:HOST_PORT
)--timeout=<seconds>
: Readiness timeout (default: 30
)All launchers can build and serve local Docker images from Dockerfiles:
# If first argument is a Dockerfile path, builds local image
./scripts/dock2tauri.sh ./Dockerfile 8088 80
The ./app
folder content will be served by the built container.
For the Bash launcher, if a Dockerfile path is provided and --build
is not specified, it will default to build and export bundles to dist/
.
For the Python CLI (taurido
), the same default applies: Dockerfile input without --build
triggers build + export.
# Basic usage
./scripts/dock2tauri.sh <docker-image|Dockerfile> <host-port> <container-port> [--build] [--target=<triple>] [--health-url=<url>] [--timeout=<seconds>]
# Examples
./scripts/dock2tauri.sh nginx:alpine 8088 80
./scripts/dock2tauri.sh ./Dockerfile 8088 80
./scripts/dock2tauri.sh grafana/grafana 3001 3000 --build
./scripts/dock2tauri.sh jupyter/scipy-notebook 8888 8888 --target=x86_64-pc-windows-gnu
./scripts/dock2tauri.sh grafana/grafana 3001 3000 --health-url=http://localhost:3001/login --timeout=60
./scripts/dock2tauri.sh ./examples/pwa-hello/Dockerfile 8088 80 --build --cross
./scripts/dock2tauri.sh ./examples/pwa-notes/Dockerfile 8088 80 --build --cross
The standalone Python package taurido
provides a CLI with the same behavior as the Bash launcher, including dynamic Linux bundler detection and defaults for Dockerfile input.
# From repo root (contains src-tauri/)
taurido ./examples/pwa-hello/Dockerfile 8088 80
# From another directory, point to project root explicitly
taurido --project-root ./dock2tauri ./examples/pwa-hello/Dockerfile 8088 80
# Or via environment variable
TAURIDO_PROJECT_ROOT=./dock2tauri taurido ./examples/pwa-hello/Dockerfile 8088 80
Notes:
--build
is NOT provided, taurido
defaults to building and exporting bundles into dist/
.--cross
is supported as best-effort when proper toolchains are installed.# Basic usage
python3 scripts/dock2tauri.py --image <image> --host-port <port> --container-port <port> [--build|-b] [--target <triple>] [--health-url <url>] [--timeout <seconds>]
# Examples
python3 scripts/dock2tauri.py --image nginx:alpine --host-port 8088 --container-port 80
python3 scripts/dock2tauri.py --image grafana/grafana --host-port 3001 --container-port 3000 --build
python3 scripts/dock2tauri.py --image jupyter/scipy-notebook --host-port 8888 --container-port 8888 --target x86_64-pc-windows-gnu
python3 scripts/dock2tauri.py -i grafana/grafana -p 3001 -c 3000 --health-url http://localhost:3001/login --timeout 60
# Basic usage
node scripts/dock2tauri.js [image|Dockerfile] [host-port] [container-port] [--build|-b] [--target=<triple>] [--health-url=<url>] [--timeout=<seconds>]
# Examples
node scripts/dock2tauri.js nginx:alpine 8088 80
node scripts/dock2tauri.js grafana/grafana 3001 3000 --build
node scripts/dock2tauri.js jupyter/scipy-notebook 8888 8888 --target=x86_64-pc-windows-gnu
node scripts/dock2tauri.js grafana/grafana 3001 3000 --health-url=http://localhost:3001/login --timeout=60
# Launch Nginx as desktop app
make nginx
# Launch Grafana dashboard
make grafana
# Launch custom container
make launch IMAGE=my-app:latest HOST_PORT=8088 CONTAINER_PORT=80
# Any launcher with --build flag
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build
python3 scripts/dock2tauri.py --image nginx:alpine --host-port 8088 --container-port 80 --build
node scripts/dock2tauri.js nginx:alpine 8088 80 --build
# Build for Windows from Linux/macOS
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build --target=x86_64-pc-windows-gnu
# Build for Linux ARM64
./scripts/dock2tauri.sh nginx:alpine 8088 80 --build --target=aarch64-unknown-linux-gnu
Built bundles are saved to:
src-tauri/target/release/bundle/
(native platform builds)src-tauri/target/<target-triple>/release/bundle/
(cross-platform builds)Additionally, the Bash and Python CLI export bundles to a friendly path under dist/<platform>/
(e.g., dist/linux-x64/
).
Supported bundle formats:
If Android SDK is detected (ANDROID_SDK_ROOT
or ANDROID_HOME
), the Bash and Python CLI attempt to build an Android APK automatically during --build
.
Output: dist/android-apk/
Requirements: Android SDK/NDK, Java (JDK), Gradle, and Tauri Mobile tooling.
On some Fedora systems, the Tauri CLI may not generate bundles despite successful builds. Use the manual packaging script as a workaround:
./scripts/build-bundles.sh
This script provides automatic fallback to manual AppImage and .deb creation.
You may see this warning during development - itโs harmless and can be ignored:
Gdk-Message: 15:34:22.123: Unable to load webkit2gtk-web-extension: ...
On some Fedora systems, the Tauri CLI may not generate bundles despite successful builds. Use the manual packaging script as a workaround.
All launchers generate valid Tauri v2 configuration with:
taurido
): chosen dynamically on Linux (DEB/RPM/AppImage) with FUSE-less AppImage support via APPIMAGE_EXTRACT_AND_RUN=1
; AppImage is skipped if tools are not runnablecargo tauri --config
without modifying src-tauri/tauri.conf.json
build.rs
to generate valid PNG icons automatically