cobalt icon indicating copy to clipboard operation
cobalt copied to clipboard

Add a Docker image for the web instance

Open FixFever opened this issue 1 year ago • 17 comments

problem description

Information about selfhosting a web app has been removed from the manual. https://github.com/imputnet/cobalt/blob/main/docs/run-an-instance.md The old configuration now runs 2 instances of cobalt-api.

How to selfhost new version of web app?

your instance configuration

  cobalt_api:
    image: ghcr.io/imputnet/cobalt:latest
    container_name: cobalt_api
    ports:
      - 9002:9000/tcp
    environment:
      - API_URL=https://api.cobalt.${DOMAIN}/
    restart: unless-stopped
      
  cobalt:
    image: ghcr.io/imputnet/cobalt:latest
    container_name: cobalt
    ports:
      - 9003:9001/tcp
    environment:
      - WEB_URL=https://cobalt.${DOMAIN}/
      - API_URL=https://api.cobalt.${DOMAIN}/
    restart: unless-stopped

FixFever avatar Sep 09 '24 23:09 FixFever

They answered me in Discord: You can't as of right now.

You'd have to set your own instances (API) in this : https://cobalt.tools/settings/instances

I personally stay on v7 for now, waiting (hopefully) to have someone create a docker-compose for the web facing interface.

Write avatar Sep 10 '24 00:09 Write

Web must be run manually right now, but it does exist in the web directory, it's just not containerized.

JakeyPrime avatar Sep 10 '24 01:09 JakeyPrime

You can't as of right now.

who said that? you can host it as a static build (the same way we do). you can read everything you need to know in web's readme file: https://github.com/imputnet/cobalt/blob/main/web/README.md

wukko avatar Sep 10 '24 01:09 wukko

You can't as of right now.

who said that? you can host it as a static build (the same way we do). you can read everything you need to know in the web's readme file.

Not as a docker compose, I meant.

Write avatar Sep 10 '24 01:09 Write

it is also indeed better to use the main web app with your api instance: https://cobalt.tools/settings/instances

we don't track anything and it's one less thing for you to take care of.

wukko avatar Sep 10 '24 01:09 wukko

Not as a docker compose, I meant.

i don't think we'll be providing a docker image for frontend for now. if that ever changes, i'll try to remember to let you know.

wukko avatar Sep 10 '24 01:09 wukko

I'm unsure why it was appropiate to go this route especially considering that this was provided before without issue.

Would you consider a PR adding this back?

spectrapulse avatar Sep 11 '24 14:09 spectrapulse

Would you consider a PR adding this back?

hey, sure! if you would like to work on it, here is a general outline of how i'd envision for it to look:

  • the dockerfile would be configurable during build time using the same environment variables as listed in the web readme. it wouldn't have any runtime environment variables (since they wouldn't have any effect anyways)
  • the final docker image would ideally have no node.js runtime, and would just contain the build output + some lightweight web server like nginx:alpine
  • it would use the same dockerfile for caching as recommended in pnpm documentation

dumbmoron avatar Sep 11 '24 15:09 dumbmoron

Would you consider a PR adding this back?

hey, sure! if you would like to work on it, here is a general outline of how i'd envision for it to look:

  • the dockerfile would be configurable during build time using the same environment variables as listed in the web readme. it wouldn't have any runtime environment variables (since they wouldn't have any effect anyways)
  • the final docker image would ideally have no node.js runtime, and would just contain the build output + some lightweight web server like nginx:alpine
  • it would use the same dockerfile for caching as recommended in pnpm documentation

The last two points should be straightforward to implement.

The first point, however, could be tricky. It’s inconvenient to have to republish a self-built variant to another registry—especially if you're using Kubernetes or Docker Swarm. Keeping it up-to-date would also be a hassle, and it rules out tools like Watchtower unless you're hosting your own fork with changes.

I'm unsure of the best approach here, but maybe providing an additional image variant alongside the static web server image or just going the node image route with a reverse proxy like NGINX in front of node could work better.

If we do want to go with the static webserver route I might take inspiration from how Piped handles this in their frontend, but this wouldn't solve issues with environment variables other than WEB_HOST and WEB_DEFAULT_API for users who want to integrate Plausible or Turnstile. This would also be the most jank approach.

spectrapulse avatar Sep 11 '24 18:09 spectrapulse

@spectrapulse

[...] or just going the node image route with a reverse proxy like NGINX in front of node could work better.

one of the goals when rewriting the frontend was for it to be relatively small and simple to host from the server perspective (no processing required to serve frontend pages post-build), which unfortunately comes at the cost of runtime customizability (and i guess is also one of the reasons why there is no "official" dockerfile for it right now).

but if we once again bundle the entirety of the node project with the image (node_modules for web is ~100 MB on my machine) we are basically back to square 1, so that's why i wouldn't really consider this option to be "right" (in comparison, the static build output is just under 30 MB, and also vite mentions in their documentation explicitly not to use preview as a production server)

If we do want to go with the static webserver route I might take inspiration from how Piped handles this in their frontend, but this wouldn't solve issues with environment variables other than WEB_HOST and WEB_DEFAULT_API for users who want to integrate Plausible or Turnstile. This would also be the most jank approach.

i don't think this would work here since cobalt also uses these envs to include/omit certain parts of components (like hiding text that is not relevant if plausible is not enabled).

maybe one approach (that i'm not sure how feasible would be) would be to build the frontend at startup and then get rid of the whole build environment and just serve the static files, which isn't really ideal, but it would work i guess

dumbmoron avatar Sep 11 '24 18:09 dumbmoron

In case anyone needs a docker image right now, I've made a basic one here: https://github.com/ggtylerr/globe/blob/master/services/cobalt-template/Dockerfile Do note that the copy paths would need to be changed if you aren't using the repo. It's just a matter of changing two lines.

It's probably not suitable for a PR but in case it's used as a base, I've addressed some of the points @dumbmoron made:

  • It simply uses ARG instead of environment variables. While this isn't suitable for any published images, it's straightforward when building (which we'll have to do anyways at this time.)
  • For simplicity's sake this Dockerfile uses http-server but it could probably be modified for nginx.
  • It's only for the web app at the moment but it could very easily be merged with the existing app Dockerfile.

ggtylerr avatar Sep 12 '24 00:09 ggtylerr

In case anyone needs a docker image right now, I've made a basic one here: https://github.com/ggtylerr/globe/blob/master/services/cobalt-template/Dockerfile Do note that the copy paths would need to be changed if you aren't using the repo. It's just a matter of changing two lines.

It's probably not suitable for a PR but in case it's used as a base, I've addressed some of the points @dumbmoron made:

  • It simply uses ARG instead of environment variables. While this isn't suitable for any published images, it's straightforward when building (which we'll have to do anyways at this time.)
  • For simplicity's sake this Dockerfile uses http-server but it could probably be modified for nginx.
  • It's only for the web app at the moment but it could very easily be merged with the existing app Dockerfile.

Yeah I've pretty much already made a local branch with the changes needed for the original requirements into the existing Dockerfile it's just that I'm still looking for a possible solution that would fit better with published images. I'm probably going to end up making a small pr that just adds this functionality which would require build-time args for plausible and turnstile but where u can still patch the domain without needing to make and host your image.

I think people who have the need for that "advanced usage" might be less bothered by having to host their own image but people who simply want to self-host cobalt for themselves won't be affected much by the current state of the project with these changes.

spectrapulse avatar Sep 12 '24 07:09 spectrapulse

In case anyone needs a docker image right now, I've made a basic one here: https://github.com/ggtylerr/globe/blob/master/services/cobalt-template/Dockerfile Do note that the copy paths would need to be changed if you aren't using the repo. It's just a matter of changing two lines.

It's probably not suitable for a PR but in case it's used as a base, I've addressed some of the points @dumbmoron made:

* It simply uses ARG instead of environment variables. While this isn't suitable for any published images, it's straightforward when building (which we'll have to do anyways at this time.)

* For simplicity's sake this Dockerfile uses `http-server` but it could probably be modified for nginx.

* It's only for the web app at the moment but it could very easily be merged with the existing app Dockerfile.

This was super handy, thanks for sharing.

I have automated the build for this image in a GitHub Actions workflow. At an interval, the workflow checks for updates to the version number inside of web/package.json within this repository, if it has changed, a new image is built and published to the GitHub container repository - tagged with the version number from package.json.

This makes it very easy to reference within a docker compose file, and image version monitoring software like renovate and watchtower will of course pick these up as normal:

  cobalt-web:
    container_name: cobalt-web
    depends_on:
      - cobalt-api
    image: ghcr.io/[your-github-user]/cobalt-web:10.4.4
    restart: unless-stopped

I hope at some point we can get an official image as it was a breeze back on v7.

ben-pearce avatar Dec 16 '24 22:12 ben-pearce

In this comment, I give a modified Dockerfile and a docker-compose.yml to self-host the frontend (works on latest 10.5.4): https://github.com/imputnet/cobalt/issues/768#issuecomment-2585195207.

AlexAltea avatar Jan 11 '25 10:01 AlexAltea

Could this thread be re-opened to keep track of docker-composerizing a self-hostable cobalt-web instance? Thanks! Or should we rename issue https://github.com/imputnet/cobalt/issues/768 to a more explicit title like Create docker-compose GHCR image for cobalt-web?

jo-chemla avatar Feb 19 '25 13:02 jo-chemla

Unsure why this was the choice that was made, considering a lot of people want to host both the api and the web instance on their own server.

andri1305 avatar Jun 03 '25 12:06 andri1305

you can still self-host the web instance, it's simply no longer a docker image, because it's a static web app: https://github.com/imputnet/cobalt/tree/main/web#cobalt-web

we're open to contributions of a docker image that has dynamic env variables and doesn't bake defaults into the image

wukko avatar Jun 03 '25 13:06 wukko

I gave it a try with the following PR https://github.com/imputnet/cobalt/pull/1366

The image runs fine, so it's already going in the right direction. ~~Cloudflare challenges fail though, probably because I have to use my own instance as per this comment https://github.com/imputnet/cobalt/issues/811#issuecomment-2751005075.~~ Would love some input, it's not yet parsing docker container env variables at runtime, & I could not find these variables already used in the frontend code.

Currently, vite still uses process.env env-vars at build time, so the docker container is not using those defined via placeholders in runtime-config.js

EDIT: running and linking my own cobalt:11 API instance to the web container image worked, no more cloudflare turnstile error! Should be good to go, please tell me if you want to handle env-vars differently and directions on how to do it.

jo-chemla avatar Jun 25 '25 10:06 jo-chemla