-
Notifications
You must be signed in to change notification settings - Fork 5
Build and publish Docker images #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
161e6ee to
b5b73cc
Compare
… TIGER_SECRET_KEY if present
b5b73cc to
62d8e57
Compare
Askir
left a comment
There was a problem hiding this 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]>
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 anytigercommand. TheTIGER_PUBLIC_KEYandTIGER_SECRET_KEYenv 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~/.pgpassfile and~/.config/tigerdirectory 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 thatTIGER_PASSWORD_STORAGE=pgpassinside 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_KEYandTIGER_SECRET_KEYenv vars if they're present. Previously, it only read from those env vars when runningtiger 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 runtiger auth loginand store credentials at all, which greatly simplifies things - i.e. no need for a special entrypoint script that first runstiger 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/infoendpoint (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 runningtiger 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.yamlfile I added to the root of the repo:You can run a test command with:
You can install the MCP server into Claude Code with:
Then start up Claude and run
/mcpto 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.yamlfile) by running the following command:Check the output for Docker info. Note that it builds the images with slightly different names when running in
--snapshotmode. See the GoReleaser docs for more info: https://goreleaser.com/customization/dockers_v2/