On Thu, Feb 26, 2015 at 02:37:23PM +0100, Laurent Bercot wrote:
> On 26/02/2015 14:11, John Regan wrote:
> >Just to clarify," docker run" spins up a new container, so that wouldn't 
> >work for stopping a container. It would just spin up a new container running 
> >"s6-svscanctl -t service"
> >
> >To stop, you run "docker stop <container id>"
>  Ha! Shows how much I know about Docker.
>  I believe the idea is sound, though. And definitely implementable.

I figure this is also a good moment to go over ENTRYPOINT and CMD,
since that's come up a few times in the discussion.

When you build a Docker image, the ENTRYPOINT is what program you want
to run as PID1 by default. It can be the path to a program, along with some
arguments, or it can be null.

CMD is really just arguments to your ENTRYPOINT, unless ENTRYPOINT is
null, in which case it becomes your effective ENTRYPOINT.

At build-time, you can specify a default CMD, which is what gets run
if no arguments are passed to docker run.

When you do 'docker run imagename blah blah blah', the 'blah blah
blah' gets passed as arguments to ENTRYPOINT. If you want to specify a
different ENTRYPOINT at runtime, you need to use the --entrypoint

So, for example: the default ubuntu image has a null ENTRYPOINT, and
the default CMD is "/bin/bash". If I run `docker run ubuntu`, then
/bin/bash gets executed (and quits immediately, since it doesn't have
anything to do).

If I run `docker run ubuntu echo hello`, then /bin/echo is executed.

In my Ubuntu baseimage, I made the ENTRYPOINT "s6-svscan /etc/s6". In
hindsight, this probably wasn't the best idea. If the user types
"docker run jprjr/ubuntu-baseimage hey there", then the effective
command becomes "s6-svscan /etc/s6 hey there" - which goes against how
most other Docker images work.

So, if I pull up Laurent's earlier list of options for the client:

> * docker run image commandline
>   Runs commandline in the image without starting the supervision environment.
> * docker run image /init
>   Starts the supervision environment and lets it run forever.
> * docker run image /init commandline
>   Runs commandline in the fully operational supervision environment. When
>commandline exits, the supervision environment is stopped and cleaned up.

I'm going to call these case 1 (command with no supervision environment), case
2 (default supervision environment), and case 3 (supervision environment with
a provided command).

Here's a breakdown of each case's invocation, given a set ENTRYPOINT and CMD:

ENTRYPOINT = null, CMD = /init

* Case 1: `docker run image commandline`
* Case 2: `docker run image
* Case 3: `docker run image /init commandline`

ENTRYPOINT = /init, CMD = null

* Case 1: `docker run --entrypoint="" image commandline`
* Case 2: `docker run image`
* Case 3: `docker run image commandline`

Now, something worth noting is that none of these command run interactively -
to run interactively, you run something like 'docker run -ti ubuntu /bin/sh'.

-t allocates a TTY, and -i keeps STDIN open.

So, I think the right thing to do is make /init check if there's a TTY
allocated and that STDIN is open, and if so, just exec into the passed
arguments without starting the supervision tree.

I'm not going to lie, I don't know the details of how to actually do that.
Assuming that's possible, your use cases become this:

ENTRYPOINT = /init (with TTY/STDIN detection), CMD = null

* Case 1: `docker run -ti image commandline`
* Case 2: `docker run image`
* Case 3: `docker run image commandline`

So basically, if you want to run your command interactively with no execution
environment, you just pass '-ti' to 'docker run' like you normally do. If
you want it to run under the supervision tree, just don't pass the '-ti'
flags. This makes the image work like pretty much every image ever, and
the user doesn't ever need to type out "/init".

Laurent, how hard is it to check if you're attached to a TTY or not? This is
where we start getting into your area of expertise :)


Reply via email to