Is it possible to specify a Docker image build argument at pod creation time in Kubernetes?

3/11/2018

I have a Node.JS based application consisting of three services. One is a web application, and two are internal APIs. The web application needs to talk to the APIs to do its work, but I do not want to hard-code the IP address and ports of the other services into the codebase.

In my local environment I am using the nifty envify Node.JS module to fix this. Basically, I can pretend that I have access to environment variables while I'm writing the code, and then use the envify CLI tool to convert those variables to hard-coded strings in the final browserified file.

I would like to containerize this solution and deploy it to Kubernetes. This is where I run into issues...

I've defined a couple of ARG variables in my Docker image template. These get turned into environment variables via RUN export FOO=${FOO}, and after running npm run-script build I have the container I need. OK, so I can run:

docker build . -t residentmario/my_foo_app:latest --build-arg FOO=localhost:9000 BAR=localhost:3000

And then push that up to the registry with docker push.

My qualm with this approach is that I've only succeeded in punting having hard-coded variables to the container image. What I really want is to define the paths at pod initialization time. Is this possible?

-- Aleksey Bilogur
docker
kubernetes

1 Answer

3/11/2018

Edit: Here are two solutions.

PostStart

Kubernetes comes with a lifecycle hook called PostStart. This is described briefly in "Container Lifecycle Hooks".

This hook fires as soon as the container reaches ContainerCreated status, e.g. the container is done being pulled and is fully initialized. You can then use the hook to jump into the container and run arbitrary commands.

In our case, I can create a PostStart event that, when triggered, rebuilds the application with the correct paths.

Unless you created a Docker image that doesn't actually run anything (which seems wrong to me, but let me know if this is considered an OK practice), this does require some duplicate work: stopping the application, rerunning the build process, and starting the application up again.

Command

Per the comment below, this event doesn't necessarily fire at the right time. Here's another way to do it that's guaranteed to work (and hence, superior).

A useful Docker container ends with some variant on a CMD serving the application. You can overwrite this run command in Kubernetes, as explained in the "Define a Command and Arguments for a Container" section of the documentation.

So I added a command to the pod definition that ran a shell script that (1) rebuilt the application using the correct paths, provided as an environment variable to the pod and (2) started serving the application:

command: ["/bin/sh"]
args: ["./scripts/build.sh"]

Worked like a charm.

-- Aleksey Bilogur
Source: StackOverflow