tugboat
Turn your Python/R analysis directory into a Docker image with minimal configuration.
Links
AI / Agents
Developers
Meta
Requires: Python >=3.12
Quickly containerize your Python and R (and hybrid) projects with minimal configuration. tugboat provides simple utilities to generate a Dockerfile from an analysis directory, build the corresponding Docker image, push the image to DockerHub, and publicly share the project via Binder.
tugboat automatically detects all the packages necessary to replicate your analysis and will generate a Dockerfile that contains an exact copy of your analysis directory with all the essential Python/R packages installed. tugboat uses uv and renv for Python and R dependency management, respectively. As a result, projects that already utilize uv or renv are tugboat compatible with no additional setup.
tugboat may be of use, for example, when preparing a replication package for research. With tugboat, you can take a directory on your local computer and quickly generate a corresponding Dockerfile and Docker image that contains all the code and the necessary software to reproduce your findings.
Installation
Install tugboat from PyPI:
pip install tugboat-clior install tugboat from GitHub:
pip install git+https://github.com/dmolitor/tugboat-cliUsage
The tugboat CLI has three primary commands; one to create a Dockerfile from your analysis directory, one to build the corresponding Docker image, and one to make your project ready to share and run in an online, interactive compute environment via Binder.
Create the Dockerfile
The primary command from tugboat is create. This command converts your analysis directory into a Dockerfile that includes all your code and essential Python packages.
This command scans all files in the analysis directory, detects all Python/R packages, and installs these packages in the resulting Docker image. It also copies the entire contents of the analysis directory into the Docker image. For example, if your analysis directory is named incredible_analysis, the corresponding location of your code and data files in the generated Docker image will be /incredible_analysis.
For the most common use-cases, there are a couple of arguments in this command that are particularly important:
--exclude/-e: A files or sub-directory in your analysis directory that should NOT be included in the Docker image. This is particularly important when you have, for example, a sub-directory with large data files that would make the resulting Docker image extremely large if included. You can tell tugboat to exclude this sub-directory and then simply mount it to a Docker container as needed. This argument can be provided as many times as necessary.--from: The base Docker image to build from. By default, tugboat will try to pick this intelligently. This allows the user to specify a base image that includes e.g. external software that is essential for the analysis, such as Stata.
Below I’ll outline a couple examples.
## The simplest scenario where your analysis directory is your current
## working directory, you are fine with the default base "python:3.x-slim"
## Docker image, and you want to include all files/directories:
tugboat create
## Suppose your analysis directory is actually a sub-directory of your
## main project directory:
tugboat create ./sub-directory
## Suppose that you specifically need a Docker base image that has uv
## installed. To do this, we will explicitly specify a different Docker
## base image using the `FROM` argument.
tugboat create --from ghcr.io/astral-sh/uv:latest .
## Finally, suppose that we want to include all files except a couple
## particularly data-heavy sub-directories:
tugboat create -e data/big_directory_1 -e data/big_directory_2 .Build the Docker image
Once the Dockerfile has been created, we can build the Docker image with the build command. By default this will assume the Dockerfile is located in the current working directory. This function assumes a little knowledge about Docker; if you aren’t sure where to start, this is a great starting point.
The following example will do the simplest thing and will build the image locally.
tugboat build --image-name awesome_analysisSuppose that, like above, your analysis directory is a sub-directory of your main project directory:
tugboat build -d ./sub-directory/Dockerfile --build-context ./sub-directory -n awesome_analysisPush to DockerHub
If, instead of just building the Docker image locally, you want to build the image and then push to DockerHub, you can make a couple small additions to the code above:
tugboat build \
-d ./sub-directory/Dockerfile \
--build-context ./sub-directory \
-n awesome_analysis \
--dh-username "$DH_USERNAME" \
--dh-password "$DH_PASSWORD" \
--pushNote: If you choose to push, you also need to provide your DockerHub username and password. Typically you don’t want to pass these in directly and should instead use environment variables (or a similar method) instead. tugboat will automatically use the environment variables DOCKERHUB_USERNAME and DOCKERHUB_PASSWORD if they are available.
Usage - Python package
tugboat is equally easy to use programmatically via the package interface. The following code translates the CLI usage above into the equivalent Python code.
from dotenv import load_dotenv
from tugboat_cli import binderize, build, create
import os
load_dotenv()
## Create the Dockerfile
create(
project=".",
exclude=["data/big_directory_1", "data/big_directory_2"]
)
## Build the image
build(
image_name="awesome_analysis",
push=True,
dh_username=os.env["DH_USERNAME"],
dh_password=os.env["DH_PASSWORD"]
)
## Prep for sharing on Binder
binderize(branch="main")Examples
For some very simple worked examples, see the examples/ directory.
Python and R packages
tugboat is built on Python- and R- specific packages that are available at tugboat-py and tugboat, respectively.