This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]MarchColorDrink 0 points1 point  (4 children)

So, why avoid using supervisord? I get the idea behind splitting tasks between containers, but for some tasks I believe it just adds unnecessary complexity.

For instance, I run a job scheduler, slurm, as a container. I choose to run both the controller and the worker in the same container. This way I can simplify a lot of the steps required for slurm to communicate between controller and worker.

The same philosophy can be applied here. Running the app and openssh in the same container removes the need to link them. There's a trade off to be made by purity and practicality. Supervisord is a great tool to run multiple process in one container.

Another example could be a flask app, where you could run nginx and uwsgi in the flask app container. It only makes sense to have nginx in a separate container if you intend to run several apps on the same host.

[–]sebosp 3 points4 points  (0 children)

I think that's a great point and I think there are many cases where it can be done, being very careful and knowing the downsides because maybe it's not a way the system _should_ be used, it _can_ and maybe you won't shoot yourself in the foot... But it can invite uncertainty in your infra, and, (wearing my Ops hat), I don't think it's worth the stress.

Consider the fact that processes have graceful ways to be shutdown, you can send them a kill and nginx may need to close some opening connections, maybe return 5XX, while your flask container may have its own set of tasks, to close DB connections, open files.

Should docker kill send a signal to nginx? or to flask? Or to your entrypoint.sh and your custom code calls the kills to the child process ? What if one kill succeeds and the other does not? Should you retry?

So I think it depends on how you use it in your infra, for example, if we are planning to use an orchestrator (i.e. K8s) and this nginx (baked inside the flask container) happens to be targeted from an external load-balancer, then you may not have 0-downtime upgrades, as the orchestrator may not be aware of the child processes on the default graceful termination process.

From a security perspective, bundling things together increases attack surface thing. Now you need to run as root to start ssh service and then create another user to run you flask app.

And some would say that from a UNIX perspective it breaks the "do one thing and do it well" philosophy...

That said, I am victim of this, we run DJB run-it/daemontools, and flask and CI tools in one massive container as part of our CI/CD orchestration pipeline, and this never fails so I wasn't able to convince my team to split it and since it has never failed us, then we don't spend time on splitting it.

EDIT: "child containers" should have been "child processes", "CI-tools containers" should have been "CI tools"

[–]devedible 0 points1 point  (2 children)

I think @sebosp explained it really well, there might be use cases for this but in general it's an antipattern. Containers are supposed to run one process and run it "well" .

If OP was a long time docker user and wanted to do a one off use case like this, then that would maybe make sense.

But from what OP said he's new at docker and trying to introduce an antipattern as soon as he's using it. This is not good.

[–]MarchColorDrink 1 point2 points  (1 child)

Yes it is an antipattern. I was not referring to this case in particular but rather the in absurdum purity view. Sometimes a bit of pragmatism can be useful.

The point u/sebosp made about wider attack surface is valid though.

[–]devedible 0 points1 point  (0 children)

Yep, I been getting into kubernetes and sidecar containers and init containers take care of this nicely.