I have a simple docker image for my webapp, now people are asking me to provide an option to change logo. How to provide an option to add a custom logo on the fly using Environment variables? Here is the Docker File
Since HTML will be interpreted on the client side, you either have to generate the HTML when the container starts or generate a json file and use JavaScript to change to logo.
To generate HTML you can create a custom command
CMD ["/start.sh"]
which would read the environment variable to generate the HTML and then sart nginx.
exec nginx -g "daemon off;"
First question you have to clarify yourself is where do you want the image to be hosted. Served by the container? Or you just need to change the URL that is pointing to an external service?
If pointing outside, pass the URL in the EVN var.
If hosted inside, then you need to clarify another question: How is the image going to be deployed inside the container? Via mounted volumes? Or copied inside the container filesystem at runtime?
Answering those questions will help in pointing you towards a specific answer.
@rimelek I was thinking about what he posted. Then Like @xavimontero saidā¦ I had several ideas about implementation, but not sure which is the best.
URL that is pointing to an external service may not be a good approach because this container will run behind corporate firewall or offline. Still itās better than nothing, it will work on public deployments.
passing the URL in the EVN var is a good option.
inside the container? Via mounted volumes? Or copied inside the container filesystem at runtime?
Can we pass the SVG file contents via EVN var.? ( SVG logo = few lines of text )
Then a shell script that replace it on the runtime.
These are the only two options (mounted volumes and copied inside the container filesystem at runtime) for putting SVG inside the HTML?
Can someone show an example shell script that can replace or delete few lines in a html?
There is no such thing as EVN var. @xavimontero just acidentally wrote EVN instead of ENV (environment).
Docker is not magic, so you are still working with the well-known HTML. Docker just creates an isolated environment so you can choose any solution that HTML supports including referring to an external file or embedding the svg in the HTML source as you do it now. If you want to make the logo available on the containerās filesystem, then you need to mount or copy it, there is no other option.
Anyone can easily deploy a small webserver in an offline environment and the URL you set in the environment variable does not need to be a public URL. It could point to the local webserver protected by the firewall.
You can also use base64 encoded image as a URL.
Yes, you can
environment:
SITE_LOGO: |-
<svg ....>
</svg>
Proper indentation is important. |-
is a yaml syntax to use multiline strings.
This is how I did it using sed, but I used it for a single line:
The switchModule
and switchConfig
functions are doing the same based on of the value of the second parameter.
And then I used awk for multiline contents:
The easisest way though is probably using envsubst
It works on files that donāt contain similar syntax. For example using variables in a PHP file would be very similar, so I wouldnāt replace content in a PHP file.
Definitively coding the SVG inside the config file is not a good idea.
You can do it. But itās an antipattern.
Look: What if the client passes you a new SVG file (imagine a themed logo for halloween, christmas or summer)? You have to open your config file, then copy-paste the original SVG in itā¦ too much error prone.
Before going ahead Im asking myself a few questions:
-
Are the clients running your image in their hostings by themselves? Or you are managing the docker run for them? Ie: The person that makes the
docker run
is you or them? -
Where and how are the original logos sent to whoever is the docker runner? Ie: Where is the āorigial fileā going to live before itās injected in the container?
-
What about copying the logo into the running container after itās been started? Is that āforbiddenā to be explored?
@xavimontero First of all, I am glad that you joined the conversation and hope you keep that good habit
Usually not the best idea, but sometimes choosing a more complicated solution is not worth it.
You know that we are discussing a logo of an open source internet speed tester, right?
If the SVG in the compose file is an antipattern, then copying a file into a container after starting it is 100% that too. You have to be able to remove the containers any time. You could of course create a script that starts the container and then runs the copy command, but it would just unnecessarily complicate things when you could just mount the file.
And of course creating a new Docker image based on the original image is always an option too. That would also work on Kubernetes or Swarm without any network filesystem, but in case of an internet speed tester, I think all the other solutions could be acceptable.
I was not aware that was for ātuningā an OpenSource project.
I was assuming @openspeedtest was a mere nick and that āI have a simple docker image for my webappā was meaning a privately-used web that maybe he was installing for some clients.
So, questions answered. When @openspeedtest says " people are asking me to provide an option to change logo" Iām assuming that those feature-requesters will be the ones taking care of doing the docker-run
.
So the focus needs to be āon the user sideā running the container. Make it ādevops friendlyā to help people use the image very easily.
Let me sleep with this (1:30 am here in Barcelona) and Iāll come back with some ideas tomorrow. Iāll think in the mood of āhow would Iād expect it to be if I was the user running itā.
See ya soon!
Yes, People who run this container need to use there own logo.
eg: an ISP running this container for its clients. They need to replace OpenSpeedTest logo with ISP logo. when they run this container.
ISPs will probably have a logo somewhere already so it shouldnāt be a problem to provide a variable only for changing the URL, but I donāt have experience with ISP requirements.
I feel the easiest solution for the user is
- to NOT inline it to the html and set a URL with an ENV var
- PLUS allow optionally to override a local icon.
If the env var is not set, itāll default to ālogo.svgā and you place the logo at the public root with the name logo.svg.
Imagine the var is named PUBLIC_LOGO_URL
4 scenarios:
- If one runs the container with NO configuration, the index will point to
logo.svg
and the default logo will be shown. - If one runs the container mounting a volume with
-v /some/where/my-logo.svg:/files/www/logo.svg
the new logo will be shown. - If they have the logo in PNG or JPG or other format they both mount the volume like
-v /some/where/my-logo.jpg:/files/www/new-logo.jpg
AND set the variablePUBLIC_LOGO_URL=new-logo.jpg
- Finally if they have the logo hosted somehwere, they only have to set the var, for example
PUBLIC_LOGO_URL=https://logos.example.com/nice-logo.jpg
How do you feel about this simple-yet-powerful solution?
I agree. It sounds like a perfect solution.
I volunteer to do it.
If @openspeedtest agrees too, Iāll open an issue in github mentioning this forum thread and telling Iāll implement it.
Iāve never installed this soft so maybe I need help in setting up the initial base-code, but Iām happy to help doing the change.
Iād takle it in 2 steps:
- Separate the current logo from the index, by setting a separate file (still nothing configurable).
- Once the file is separated, then make it configurable.
@openspeedtest => All okey on your side?
@xavimontero
The solution you provided is much simple and easy to use.
We are animating a single SVG file.
Recently I did a similar setup on my main website. Now UI Icons will load from main.svg when the page loads. It was to improve browser caching.
object data=ā/assets/images/main.svgā type=āimage/svg+xmlā onload=āthis.parentNode.replaceChild(this.contentDocument.documentElement, this);ā
This will work only if the main.SVG is called from the same domain name, meaning no CDN or External URLs will work. Even the subdomain or same domain with the CORS header will not work. Only paths to an SVG file will work. This is the default browser behavior. We cannot do anything here.
Also, we cannot use jpeg or png, maybe we can add it as a foreign object, but itās challenging to maintain. So I think itās better to support just SVG.
So, mounting the volume is the better approach. Because the logo hosted somewhere else will not work.
If they mount the logo, then we donāt need an Env variable like āPUBLIC_LOGO_URL=new-logo.jpgā ?
All they need to do is, modify index.html and mount it. Right?
I think itās better to write in documentation to replace L135 to L194 with your logo paths.
This is not an elegant solution.
Soon, I will separate the application UI elements into an external SVG file.
Like UI.svg and Logo.svg
Now, as you said, we can provide an Env like PUBLIC_LOGO_URL.
But again, we need a shell script that should download the SVG Logo and put it inside the container on the Fly.
or mount new logo.svg
Thanks @xavimontero @rimelek
Maybe as Iām not English native I am not exactly clear on if you ar OKEY with making the index to āloadā the logo as any regular HTML loading any regular image or not.
Should I proceed with ādetachingā the logo in SVG into a separated file? (expected answer datatype = bool hahahah).
Answer is YES!
But please wait for couple of days.
I am going to push a new update.
I think we need to rewrite UI / JS or need shell script.
see you soon.
@xavimontero updated to GitHub - openspeedtest/Speed-Test: Speed Test by OpenSpeedTestā¢ is a Free and Open-Source HTML5 Network Performance Estimation Tool Written in Vanilla Javascript and only uses built-in Web APIs like XMLHttpRequest (XHR), HTML, CSS, JS, & SVG. No Third-Party frameworks or libraries are Required. Started in 2011 and moved to OpenSpeedTest.com dedicated Project/Domain Name in 2013.