saleor-dashboard
saleor-dashboard copied to clipboard
Distribute docker images and API_URL replacement in runtime
What I'm trying to achieve
Use a distributed, production ready docker images without having to re-build the image from source.
As of right now, saleor-dashboard is not distributed as a Docker image (for example like saleor/saleor).
If you are self-hosting, you must re-build an image with the Dockerfile provided in the root of this repository passing --build-arg API_URL="https://your-saleor-api-url.example.com/graphql/"
.
Unfortunately this is because API_URL
is used from process.env
and expanded by the bundler to the distribution files.
Having to make builds of third party software just makes users less likely to keep up with updates, and makes management more cumbersome.
Describe a proposed solution
I have been testing with different approaches, some require more effort like global variables in the window. But without making changes to the codebase, it is possible to distribute image with a little script that would replace the env var in the bundle:
./nginx/override-api-url-docker-entrypoint.sh
#!/bin/bash
# Replaces the original API_URL from the bundle files with the one in $API_URL_OVERRIDE
# This avoids having to rebuild the bundle, making it possible to use a distributed Docker image.
# This script is automatically picked up by the nginx entrypoint on startup.
set -e
ORIGINAL_API_URL="http://localhost:8000/graphql/"
BUNDLE_PATH="/app/dashboard"
escape_url() {
printf '%s\n' "$1" | sed -e 's/[\/&]/\\&/g'
}
if [[ "$API_URL" != "$ORIGINAL_API_URL" ]]; then
echo "Replacing API_URL with '$API_URL'"
escaped_original_api_url=$(escape_url "$ORIGINAL_API_URL")
escaped_api_url=$(escape_url "$API_URL")
find "$BUNDLE_PATH" \
-type f \
-name 'dashboard.*.js' \
-exec sed -i "s/$escaped_original_api_url/$escaped_api_url/g" {} \;
fi
This would be added in the Dockerfile with:
COPY ./nginx/override-api-url-docker-entrypoint.sh /docker-entrypoint.d/50-override-api-url.sh
Nginx's image will pick this automatically from their entrypoint script.
With this script, users would be able to run the docker image as distributed with API_URL
:
docker run --env API_URL="https://your-saleor-api-url.example.com/graphql/" ghcr.io/saleor/saleor-dashboard:3.7.6
(Obviously we can name this differently like API_URL_OVERRIDE
if we want to be more conservative. But I feel like API_URL
is quite simple and should not cause issues)
I am able to contribute with the script itself, documentation and GitHub actions workflow, following the practices from saleor/saleor/publish-containers.yml to make sure builds are published to the GitHub container registry.
What do you think about this? Does it sound too hacky? Or can I go ahead and open a pull request?
Even if we don't ship this script with the image, It would be really cool, if at least there was a distributed image in the GitHub package registry, like the one for Saleor core, with the hardcoded default API_URL.
Hi @tofran, really appreciate your proposed solution! We are discussing it right now. I'll keep you posted.
This looking good, I appreciate the effort in preparing such a script. It will do the job, however changing chunk files within runtime is a bit risky - one more word caught by sed and we break the app. Also, we must remember that chunks are being cached by the browser.
I would recommend exploring it, switching an API endpoint shouldn't be a that big deal.
@karolkielecki @andrzejewsky thank you for your feedback.
Yes I also feel that making a find-and-replace in the bundle is quite clunky. The sed can be controlled to only run for people that really want it, by using the override suggestion I gave above. The caching problem is really relevant, and I did not foresee it. If we were to ship this as suggested, we would clearly have to state that changing the env var would probably not work right away for clients that have visited the app. As the bundle is cached in the client side - only triggering a build changes the hash.
Please have a look into the pull request I have drafted #2281 I would suggest solving this in two steps:
- Improve the Dockerfile and add CI to distribute images (done in the pr)
- Find a way to dynamically change these values without too much impact on the codebase (right now I suggested that script and PR, but I'm open to try different things until we are satisfied - this can be merged afterwards in another PR)
Closed via #2523 Thank you everyone!