How to Change Logo Inside HTML file via Environment variables

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 ["/"]

which would read the environment variable to generate the HTML and then sart nginx.

exec nginx -g "daemon off;"
1 Like

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.

1 Like

@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

      SITE_LOGO: |-
        <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.

1 Like

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:

  1. 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?

  2. 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?

  3. What about copying the logo into the running container after it’s been started? Is that “forbidden” to be explored?

1 Like

@xavimontero First of all, I am glad that you joined the conversation and hope you keep that good habit :slight_smile:

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? :slight_smile:

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.

1 Like

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

  1. to NOT inline it to the html and set a URL with an ENV var
  2. 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 variable PUBLIC_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=

How do you feel about this simple-yet-powerful solution?

1 Like

I agree. It sounds like a perfect solution. :+1:

1 Like

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:

  1. Separate the current logo from the index, by setting a separate file (still nothing configurable).
  2. Once the file is separated, then make it configurable.

@openspeedtest => All okey on your side?

1 Like

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).

1 Like

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 dedicated Project/Domain Name in 2013.