Hosting a fully static site
- Nginx, using the default image
- git-sync, a tool to keep in sync with a git repository.
The git-sync tool pulls the resources from a git repository, and makes them available to Nginx, which takes care of making them available over HTTP. This is an example of a Pod with multiple containers; Nginx being the main container and git-sync a side car that supports the main container.
Using this approach we don’t need to build any Docker container, and we don’t need to re-deploy to Kubernetes upon changes. The git-sync container comes from te Kubernetes contrib project, but contains two issues (397 and 398) that I fixed. A Docker image containing these fixes is available as paulbakker/git-sync.
The git-sync and Nginx container must be able to share files. For this we can use a Kubernetes volume. Both containers mount the same volume, that way Nginx can serve files pulled by the git-sync tool. An example Pod definition in JSON looks as follows:
When the git repo is updated, the hosted site on Kubernetes will be automatically updated as well.
Hosting a UI that requires a build
The git-sync approach described above doesn’t really work in that case. It’s better to create a Docker image that contains the generated files from a build server. It turns out that building projects with all kind of Node modules reliably can be a bit of a challange on different environments. I found it to be easier to make the build part of the actual Docker image, so that it becomes more reproducable. There is already a standard Node Docker image that does this.
For the example, let’s assume our project has a project.json file.
To build the project we need to invoke the ‘tsc’ command. We can use the following Docker file to do so.
Of course the build could be more complicated, either using more npm scripts, or using something like Grunt. The Docker file above creates a container that just contains our generated files, it doesn’t actually contain a web server. We will use the same side-car approach to hook up these files to an Nginx container. Kubernetes doesn’t like containers that exit. That means we need to do something to keep the container alive, which explains the tail -f at the end of the Dockerfile.
Now let’s look at the Pod definition for this setup.
Again we’re using a standard Nginx image. The frontend image uses a lifecycle hook to copy the generated files to the shared volume. This is necessary because mounting an existing directory as a volume will empty it!
As an alternative you could make Nginx part of your own Docker image. That way we don’t need the side car approach, but the Dockerfile becomes a bit more complicated. Both approaches work well, it’s a matter of preference which approach to use.