On Fri, Feb 27, 2015 at 5:08 PM, John Regan <john_at_jrjrtech.com> wrote:
>> Let me explain my point by an example:
>>
>> I am writing an image for tvheadend server. The tvheadend program has
>> some default arguments, which almost always are:
>>
>> -u hts -g video -c /config
>>
>> So then after that we might append user-specifig flags. Which for my
>> personal use are:
>>
>> --satip_xml http://192.168.1.22:8080/desc.xml --bindaddr 192.168.2.218
>>
>> So those user flags become set in CMD. As a user I set from my
>> orchestration tool, which is crane. In a 'crane.yml' YAML user
>> configuration file. Then I type 'crane lift', which does the appending
>> (and overriding) of CMD at the end of 'docker run...'.
>>
>> Another user comes along. Their user-specific (last arguments) will be
>> entirely different. And they should naturally use CMD to set them.
>> This is all something you guys have already stated.
>>
>> BUT (as an image writer). I don't want them to wipe out (override) the
>> first "default" part:
>>
>> -u hts -g video -c /config
>>
>> Because the user name, group name, and "/config" configuration dir (a
>> VOLUME). Those choices were all hard-coded and backed into the
>> tvheadend image's Dockerfile. HOWEVER if some very few people do want
>> to override it, they can by setting --entrypoint=. For example to
>> start up an image as a different user.
>>
>> BUT because they are almost never changed. Then that's why they are
>> tacked onto the end of entrypoint instead. As that is the best place
>> to put them. It says every user repeating unnecessarily the same set
>> of default arguments every time in their CMD part. So as an image
>> writer of the tvheadend image, the image's default entry point and cmd
>> are:
>>
>> ENTRYPOINT ["/tvheadend","-u","hts","-g","video","-c","/config"]
>> CMD *nothing* (or else could be "--help")
>>
>> after converting it to use s6 will be:
>>
>> ENTRYPOINT ["/init", "/tvheadend","-u","hts","-g","video","-c","/config"]
>> CMD *nothing* (or else could be "--help")
>>
>> And it that that easy. After making such change then no user of my
>> tvheadend image will be affected… because users are only meant to
>> override CMD. And if they choose to override entrypoint (and
>> accidentally remove '/init') then they are entirely on their own.
>>
>
> Making the ENTRYPOINT have a bunch of defaults like this is actually
> exactly what you *shouldn't* do. Ideally, once you've created your
> baseimage, you shouldn't touch the ENTRYPOINT and CMD ever again in
> any derived image.
>
> So, first thing's first - if you're building an image with TVHeadEnd
> installed, you may as well take the time to write a script to run it
> in s6, which eliminates the need to change the ENTRYPOINT and CMD
Well you are then neglecting to see 2 other benefits which i neglected
to mention anywhere previously:
1) Is that anyone can just look in my Dockerfile and see the default
tvheadend arguments as-is. Without needing to go around chasing them
being embedded in some script (when only Dockerfile is published to
DockerHub, not such start scripts).
2) Is that when they run my image, they can do a 'docker ps' and see
the FULL tvheadend arguments, including the default ones in the entry
point component. Which is then behaving much more like regular 'ps'
command.
I actually like those benefits, and as the image writer have the
responsibility to ensure such things work properly, and to my own
liking.
> arguments in the first place. Your ENTRYPOINT just remains "/init",
> which will launch s6-svscan, which will launch TVHeadEnd. Your CMD
> array remains null.
>
> Now, conceptually, you can think of TVHeadEnd as requiring "system
> arguments" and "user arguments" -- "system arguments" being those
> defaults you mentioned.
Yeah - expect I don't actually want to do that, and Docker INC are
officially giving me the freedom to use both entrypoint + cmd in any
ways as I personally see fit.
>
> Now just make the TVHeadEnd `run` script something like:
vv that start script won't be published in 'Dockerfile' tab on
Dockerhub. Therefore, the more functionality I am pushing from the
Dockerfile into that script, then the harder my Dockerfile will be for
other people to understand.
It's a comletely valid way of doing things. I just don't think you
should try to enforce it as a hard rule in other people's images.
>
> ```
> #!/bin/sh
>
> DEFAULT_TVHEADEND_SYSTEM_ARGS="-u hts -g video -c /config"
> TVHEADEND_SYSTEM_ARGS=${TVHEADEND_SYSTEM_ARGS:-$DEFAULT_TVHEADEND_ARGS}
> # the above line will use TV_HEADEND_SYSTEM_ARGS if defined, otherwise
> # set TVHEADEND_SYSTEM_ARGS = DEFAULT_TVHEADEND_SYSTEM_ARGS
>
> exec tvheadend $TVHEADEND_SYSTEM_ARGS $TVHEADEND_USER_ARGS
> ```
>
> That's shell script, I'm sure you could do an execline
> implementation, that fact doesn't particularly matter.
>
> So now, the user can run:
>
> `docker run -e TVHEADEND_USER_ARGS="--satip_xml http:..." tvheadendimage`
>
> If they need to change the default/system arguments for some reason, they can
> do that, too:
>
> `docker run -e TVHEADEND_SYSTEM_ARGS="whatever" -e TVHEADEND_USER_ARGS="--satip_xml http:..." tvheadendimage`
>
> From (briefly) reading the crane documentation, that's totally
> possible. It would be something like:
>
> ```
> containers:
> tvheadend:
> image: tvheadendimage
> run:
> env:
> - "TVHEADEND_USER_ARGS=--satip_xml http.."
> - "TVHEADEND_SYSTEM_ARGS="whatever"
> ```
>
> This is exactly what environment variables are meant for in Docker,
> btw, and how most images for a service operate. You define some
> service-specific environment variables, and use those to setup the
> service at run-time. All those various orchestration tools support
> this.
Received on Fri Feb 27 2015 - 18:46:28 UTC