Prefect: Remove hardcoded 'localhost' references in Prefect Server UI Vue Apollo JavaScript

Created on 1 Apr 2020  路  10Comments  路  Source: PrefectHQ/prefect

Current behavior

When deploying the Docker image for the ui component, it appears to be a simple nginx container serving static webpage assets (JavaScript, CSS, etc.).

The challenge comes when we want to customize the location of the Apollo service inside this Docker container. It seems at this location, it will attempt to read in an environment variable called VUE_APP_GRAPHQL_HTTP, but when that's not present, it'll simply default to http://localhost:4200/graphql/.
https://github.com/PrefectHQ/prefect/blob/master/server/services/ui/src/vue-apollo.js#L9

This prevents us from modifying the location of Apollo when running the ui Docker container.

To contrast this with running on the CLI, you can get around this by calling npm run serve and passing in the desired value for VUE_APP_GRAPHQL_HTTP (although it seems to also be hardcoded for localhost).
https://github.com/PrefectHQ/prefect/blob/master/server/src/prefect_server/cli/services.py#L73

Proposed behavior

It would be ideal to have the ability to pass in a dynamic location for VUE_APP_GRAPHQL_HTTP at runtime for the ui Docker container.

This way you can deploy the Prefect Server on a distributed compute platform to gain all the benefits of running on multiple servers, and you're not gated on a single point of failure.

Example

I hacked around the solution by modifying the entrypoint for the ui container, and executing this script to perform a string sub for the desired location of Apollo:
https://github.com/szelenka/prefect-ui/blob/gh-pages/prefect-ui/files/configmap/website_entrypoint.sh

This allows someone to specify the desired location via an environment variable, to dynamically adjust the location of this resource at runtime. Although I'm not sure if that's a valid solution.

enhancement

Most helpful comment

Quick update on this one: #2338 was merged which will point the UI to the GraphQL endpoint you've set in ~/.prefect/config.toml.

All 10 comments

+1, when you run Docker inside virtual machine (Windows 10 Home) you will not be able to access services using localhost hostname.

It's a tad more complicated than just changing the static localhost in the javascript files. It'd be possible (but a deviation from Cloud) to have some localstorage component to store the API url in the browser case, but that's kind of hacky.

To really provide a smooth experience, we'd also need to adjust the prefect backend server command to update the backend.toml with the specified addresses the user wants to use, other than localhost.

In the short term, it looks like prefect server is intended to run on a dedicated docker host.

:+1:

@adilkhash Thank you very much for opening this issue. You can use the compose file directly without the client. It makes a lot of things easier. I am using a modified version of the compose file now. Anyway, I don't understand why the client uses a hard-coded compose file. I would prefer a client which sends API requests to a specified backend. I'd like to use the CLI also from my laptop, not just on the machine where the backend is running. Is it a marketing thing for the cloud option?

Hi! In terms of the docker containers, we prioritized speed and first-time convenience for the user experience of prefect server start; one choice in that matter was that prefect server start utilizes the docker-compose file targeting our prebuilt images, and specifically for the UI that our docker-compose file uses an image where the UI is already compiled; so naturally when we build that UI image to distribute on docker hub it is built with the default config (aka localhost:4200/graphql) instead of any user config. The workaround by @szelenka (thanks for sharing!) to sed the dist files is definitely a tactic though talking to our UI team here it sounds like from our side we want to provide two ways to spin up the UI using Prefect provided docker images: the current one (fast to start because of being prebuilt, hardwired for local) and a development one (slower because it compiles on the fly (up to 10 minutes), but honors any/all user config) instead of maintain the find-and-replace style.

As a separate option we're also planning on publishing more how-tos about how to spin up the UI _without_ our docker containers, which @szelenka also mentions re running npm run serve. This is currently exposed on the CLI through the prefect-server services subcommand (ie prefect-server services ui) but we have mostly documented and shared the simpler prefect server start over the past week (which is dependent on our docker compose file, to your point @jloehel). I think we mostly need to be cleaning up our docs about installing the npm dependencies and using prefect-server services subcommand, but as you point out @szelenka I think the localhost hardcode in services.py must be relaxed to make that a workable option for people distributing their UI from their backend.

@lauralorenz Thanks for the long answer. To be clear here, I don't plan to deploy Prefect on bare-metal servers. I would prefer to deploy it in a swarm or k8s cluster. It would be nice to have Prefect running in k8s (helm chart) and using a k8s operator, something like eirini for cloudfoundry, to spawn light-weight containers in k8s itself for the tasks. But right now, I have the feeling, that the community setup is really tighten to the localhost. More like a dev setup. I am looking forward to seeing more deployment options soon. :-) Thanks again for the precise and honest answer.

This seems to be at the root of an issue I am seeing where no flows show up in the UI with the error message:
index.js:111 POST http://localhost:4200/graphql/ net::ERR_CONNECTION_REFUSED. I assume this is because I am running the prefect server on a vmware virtual linux server.

I also hit this issue when deploying server to an AWS ECS service. I'm using the public Docker images (prefecthq/ui), so my only option was to locally forward localhost:4200 to my_api_host:4200 with socat:

socat TCP-LISTEN:4200,fork,reuseaddr TCP:my.prefect.api.host:4200

@szelenka [鈥 It'd be possible (but a deviation from Cloud) to have some localstorage component to store the API url in the browser case, but that's kind of hacky.

This would be awesome for us. Even if there's no UI affordance, I'd be happy with writing a string to a localStorage key and have the UI code use it if it exists.

Quick update on this one: #2338 was merged which will point the UI to the GraphQL endpoint you've set in ~/.prefect/config.toml.

@znicholasbrown How exactly is this supposed to work?

My guess after reading the PR, was to have a ~/.prefect/config.toml looking like this:

config.server.ui.graphql_url = "http://my.server.url"
config.server.graphql.port = 4200

I've stopped and restarted the backend, but in the browser console logs (on a machine different than the server) I still see lots of network errors, because the browser is trying to connect to "localhost:4200".

I'm completely new to Prefect and ran into this problem after ~5 minutes, so adding something about it to the "Getting Started" documentation would certainly add to the newbie friendliness.

Hi @bluenote10 - we have some updates coming out in the next week or so that'll make this process much easier, let me circle back with you then to see if those solve your issue.

In the meantime, you'll want to set this in your ~/.prefect/config.toml instead of what you have (replacing <<>> and everything in between with your own endpoint):

[server.ui]
graphql_url="<<http://my.server.url>>:4200/graphql"
Was this page helpful?
0 / 5 - 0 ratings