This Docker application was created by factoring out many reusable code artifacts from my various projects over a number of years. Since this work was not a part of a group effort, the test coverage is predictably abysmal 🤨 and Python documentation notably absent 😑. This package takes a submodule dependency on another one of my common packages. While this application is almost entirely boilerplate, it can run as a stand-alone application and serves the basis for any well-behaved Python application. The design is opinionated with the use of ZeroMQ but this is not a strict requirement. This project has a required dependency on 1Password for both build and run time (explained later). If this is unacceptable, you'll need to fork this project or send a pull request for a substitute like Bitwarden or equivalent.
Enough talk! What do I get?
- An Ubuntu-based Docker application specifically designed to act as a Docker base image for derived applications, or can be run standalone. This includes boilerplate entrypoint scripts (
base_entrypoint.sh,app_entrypoint.sh) that can be easily overridden. - Multi-language support: Python (with uv dependency management), Java (Amazon Corretto 25 via SDKMan), and Rust (workspace with
rappandrlibcrates). - Powerful threading and inter-thread data handling via ZeroMQ with significant resilience to unchecked thread death.
- Sample Healthchecks integration with built-in cron job orchestration.
- Pre-configured process control using supervisor.
- Automatic syslog configuration to log to the Docker host rsyslog.
- Support for AWS-CLI if appropriate AWS environment variables are present (e.g.,
AWS_DEFAULT_REGION). - Support for Cronitor health check monitoring via configuration.
The project is organized into multiple language components:
Python Application (app/)
- app.main.py: The primary application entrypoint using
asyncio. Demonstrates ZeroMQ-based inter-thread communication patterns.DataReader: Example thread that generates data and pushes it via ZeroMQDataRelay: Demonstrates theZmqRelaypattern for message transformationEventProcessor: Example consumer thread that receives and processes data
- Uses tailucas_pylib for common utilities including threading, configuration, credentials management, and ZeroMQ helpers
- Integrates Sentry for error tracking
- Managed dependencies via uv (see pyproject.toml)
Java Application (src/)
- Maven-based build using Java 25 (Amazon Corretto)
- Compiled as part of the Docker build into an executable JAR (
app.jar) - Example application in
src/main/java/tailucas/app/App.java
Rust Components (rapp/, rlib/)
rlib/: Shared Rust library with utility functionsrapp/: Example Rust application demonstrating library usage- Built as part of container initialization (see rust_setup.sh)
Configuration & Orchestration
config/supervisord.conf: Process supervision configuration for running multiple servicesconfig/app.conf: Application configuration with credential referencesconfig/cron/: Crontab entries for scheduled jobsentrypoint.sh: Orchestrates base setup, app setup, and supervisor startup
The sample Python application demonstrates key resilience patterns:
- Thread lifecycle management with automatic death tracking via
thread_nanny - ZeroMQ "lockless programming" for safe inter-thread communication
- Graceful shutdown with signal handling and socket cleanup
- Configuration and credential management via 1Password Secrets Automation
Technologies that help make this package useful:
Also:
Here is some detail about the intended use of this package.
Beyond the Python dependencies defined in the project configuration, the application has runtime dependencies on Sentry and 1Password for secrets management. The application also includes Java (using Amazon Corretto via SDKMan) and Rust components. Unless you want these integrations and are extending this base project, you're likely better off forking this package and cutting out what you do not need.
Install these tools and make sure that they are on the environment $PATH.
-
taskfor project build orchestration: https://taskfile.dev/installation/#install-script -
dockeranddocker-composefor container builds and execution: https://docs.docker.com/engine/install/ -
mvnMaven for Java build orchestration: https://maven.apache.org/download.cgi -
uvfor Python dependency management: https://docs.astral.sh/uv/getting-started/installation/ -
javaandjavacfor Java build and runtime: Amazon Corretto or similar JDK -
python3for Python runtime: https://www.python.org/downloads/ -
cargoandrustcfor Rust build and runtime: https://www.rust-lang.org/tools/install
-
🛑 This project uses 1Password Secrets Automation to store both application configuration and runtime secrets. It is assumed that the 1Password Connect server container is already running in your environment. If you do not want to use this, fork this package and adapt the configuration management accordingly. 1Password is a paid product with a free tier for secrets automation.
Your 1Password Secrets Automation vault must contain an entry called
ENV.base_appwith these minimum keys:DEVICE_NAME: For container naming. Default:base-appAPP_NAME: Application name for logging. Default:base_appOP_CONNECT_HOST,OP_CONNECT_TOKEN,OP_CONNECT_VAULT: 1Password Connect server configurationHC_PING_URL: Healthchecks URL for health check status reportingCRONITOR_MONITOR_KEY: Cronitor API key for cron job monitoring (optional)
Additionally, the application requires:
-
Clone the repo
git clone https://github.com/tailucas/base-app.git cd base-app -
Start the development container
make
This uses Dev Container CLI to set up a development environment with Python, Java, Rust, and Docker-in-Docker capabilities.
-
Inside the development container, build the project artifacts
task build
This builds Java components with Maven and prepares the Docker image.
-
Configure the application by generating the
.envfile with secrets from 1Passwordtask configure
This creates the runtime configuration needed by the application.
-
Run the application:
For foreground (interactive, see logs in real-time):
task run
For background (detached mode):
task rund
The background mode works with Docker-out-of-Docker, allowing you to exit the dev container without stopping the running application.
The project uses a task-based build system:
-
Taskfile.yml: Primary build orchestration using task. Key tasks:
task build: Build Docker container imagetask run: Run container in foreground with full outputtask rund: Run container detached in backgroundtask configure: Generate runtime.envfile from 1Password secretstask java: Build Java artifacts (requires Java 21+, Maven, andjavac)task python: Initialize Python virtual environment with uvtask datadir: Create and configure shared data directory
-
Makefile: Development container setup
make(ormake dev): Build and enter development containermake check: Verify required tools are installed
-
Dockerfile: Multi-stage Docker build
- Builder stage: Compiles Java artifacts using Maven and Amazon Corretto 25
- Runtime stage: Ubuntu-based with Java, Python 3.12+, Rust, supervisor, cron, and syslog support
- User
app(UID 999) runs the application with appropriate permissions
-
.devcontainer: VS Code dev container configuration with Docker-out-of-Docker, Python, Java, and Rust support
-
GitHub Actions (.github/workflows/main.yml): Automated multi-architecture builds
- Builds for
linux/amd64andlinux/arm64 - Pushes to Docker Hub (
docker.io/tailucas/base-app) and GitHub Container Registry (ghcr.io/tailucas/base-app) - Triggered on push to main branch or manual dispatch
- Builds for
I have various projects that extend this Docker application. This Base Project serves as my Docker base image from which other projects are derived. While I may briefly run it locally in order to get basic functions, it it usually built, tagged and pushed to Docker so that the other applications can extend the functionality as needed.
Distributed under the MIT License. See LICENSE for more information.