Skip to content

Conversation

@nathanjcochran
Copy link
Member

@nathanjcochran nathanjcochran commented Dec 12, 2025

This PR wires up GoReleaser to build and push Docker images to the GitHub Container Registry (ghcr.io/timescale/tiger-cli). The Docker image is set up to run the MCP server with the stdio transport by default (i.e. tiger mcp start), but it can technically be used to run any tiger command. The TIGER_PUBLIC_KEY and TIGER_SECRET_KEY env vars are required, as there is no (easy) way to perform the interactive OAuth flow (which requires opening a browser and choosing a project via stdin) in Docker. Additionally, the ~/.pgpass file and ~/.config/tiger directory should be mounted into the container for database passwords and configuration to be stored and synced to the normal locations on the user's machine (note that TIGER_PASSWORD_STORAGE=pgpass inside the Docker image, since the keyring isn't available in Docker and file storage makes it significantly easier to sync the passwords in/out of the container).

I also updated Tiger CLI to always read credentials from the TIGER_PUBLIC_KEY and TIGER_SECRET_KEY env vars if they're present. Previously, it only read from those env vars when running tiger auth login - all of the other commands read the credentials from storage (either the system keyring or fallback file) unconditionally. This allows the Docker image to avoid having to run tiger auth login and store credentials at all, which greatly simplifies things - i.e. no need for a special entrypoint script that first runs tiger auth login (which would also complicate signal handling), worrying about the keyring not being available in Docker, etc. Note that when the credentials are pulled from the env vars instead of from storage, it first validates them by hitting the /auth/info endpoint (which is also how it figures out the project ID), and identifies the user for the sake of analytics by hitting /analytics/identify. Those operations are normally only done once when running tiger auth login, but they need to be done every time when credentials are provided via env vars. Additionally, in the process of making those changes, I created a new function that loads the config file, credentials, and API client and returns them all in a single struct, which really helps to DRY up the code, since those three functions were often called together throughout the codebase.

Note that this work is in preparation for publishing the MCP server to the Official MCP Registry, but I split that out into a separate PR (#129) so that we can test those changes to the release pipeline is isolation from the changes for building and pushing the Docker images.

See AGE-312

How to test

You can build the docker image via the docker-compose.yaml file I added to the root of the repo:

docker compose build

You can run a test command with:

docker compose run -e TIGER_PUBLIC_KEY=${YOUR_PUBLIC_KEY} -e TIGER_SECRET_KEY=${YOUR_SECRET_KEY} tiger-cli auth status

You can install the MCP server into Claude Code with:

claude mcp add tiger-docker -- docker run -i -e TIGER_PUBLIC_KEY=${YOUR_PUBLIC_KEY} -e TIGER_SECRET_KEY=${YOUR_SECRET_KEY} --mount type=bind,src=${HOME}/.config/tiger,dst=/home/tiger/.config/tiger --mount type=bind,src=${HOME}/.pgpass,dst=/home/tiger/.pgpass ghcr.io/timescale/tiger-cli:latest

Then start up Claude and run /mcp to make sure it started up successfully.

NOTE: I am aware this is not the most elegant command, but the env vars are required for authentication, and the bind mounts are required for persisting configuration and db passwords outside of the container. Also, the Official MCP Registry has options for specifying all of these various arguments so they could theoretically be configured automatically when a user installs the MCP server through a client that supports installing from the registry. See #129 for more info.

You can also verify that GoReleaser builds the Docker images correctly (as it does not use the docker-compose.yaml file) by running the following command:

goreleaser release --snapshot --clean

Check the output for Docker info. Note that it builds the images with slightly different names when running in --snapshot mode. See the GoReleaser docs for more info: https://goreleaser.com/customization/dockers_v2/

@nathanjcochran nathanjcochran marked this pull request as ready for review December 15, 2025 22:57
Copy link
Contributor

@Askir Askir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thanks for cleaning that up, now we only need the client to somehow keep track of the projectId so we don't have to keep passing both around :D

I think I can use the env vars in tests too in this PR instead of prioritizing the config dir? In fact maybe we remove the specific integration test env vars now and just use the generic ones you have added always?

VOLUME /home/tiger/.pgpass

# Copy binary to final image
COPY --from=binary_source /bin/tiger /usr/local/bin/tiger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take it that an env var isn't allowed here, to just use --from=${BINARY_SOURCE} and eliminate an extra stage? It's a weird looking dance.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's right, you can't use an env var in --from=. That was the first thing I tried, but Docker returned an error that specifically suggested I change it to this pattern 🤷‍♂️

Co-authored-by: Justin Murray <[email protected]>
Signed-off-by: Nathan Cochran <[email protected]>
@nathanjcochran nathanjcochran merged commit 690e344 into main Dec 16, 2025
2 checks passed
@nathanjcochran nathanjcochran deleted the nathan/docker branch December 16, 2025 16:09
@nathanjcochran nathanjcochran changed the title Build Docker images and publish to official MCP registry Build and publish Docker images Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants