Remix.run Logo
▲ kvirani a day ago

Does Postman sidestep these weird things about Docker? Or just some of them?

▲thayne a day ago | parent | next [-]

I assume you mean podman?

The first two are just kind of the nature of containers on linux, and applies to any container technology.

Podman does allow you to run it as a non-root user (with some limitations), that was in fact one of the biggest motivations for making podman. This wasn't possible at all in the early days of docker, it wasn't until linux introduced user namespaces, where the root user inside the namespace mapped to a non-root user id outside the namespace that non-root conatiners were possible.

And podman, unfortunately IMO, is also written in go.

▲badreligion42 16 hours ago | parent [-]

> podman, unfortunately IMO, is also written in go.

Podman, by default, uses crun as the container runtime, which is written completely in C. Podman is basically just a frontend for managing running containers.

▲wolttam 14 hours ago | parent [-]

> Podman, by default, uses crun as the container runtime

Not anymore, they switched to runc (but it can use any OCI compliant runtime)

▲cdmckay 9 hours ago | parent [-]

I think you have that backwards. They switched from runc to crun.

▲cdmckay a day ago | parent | prev | next [-]

I switched to Podman because it’s daemon less (no resources are used unless a container is running) and it doesn’t need to run as root.

Otherwise it’s basically the same and you can continue using your Dockerfiles and Docker Compose files.

Unless you’re doing something really fancy it’s basically a drop-in replacement.

▲MereInterest 17 hours ago | parent [-]

The only issue I’ve run into with Podman is that, like docker, I can’t have the container’s process be part of my shell’s foreground process group. For docker the daemon (either rootful or rootless) makes that inevitable, but podman has better rootless support, so I’d been hoping.

Unfortunately, there’s an unconditional setsid during podman’s container setup, which as far as I could tell exists so that the container can be detachable.

(This was all so that I could have the same job management with Ctrl-Z, SIGSTOP, SIGTSTP, fg, and bg, regardless of whether the process I’m running starts up a container. The only way I’ve found to have that is by handling chroot/unshare myself.)

▲Joker_vD 14 hours ago | parent [-]

UNIX job management is fundamentally broken already in that it simply can't be properly nested, even with PID namespaces. If the "container’s process [is the] part of my shell’s foreground process group", then it can not, literally can not, job manage its children.

▲MereInterest 10 hours ago | parent [-]

Clearly, the solution is to extend the `kill` syscall to accept the PID as a Gaussian integer, with both real and imaginary components. That way, we can preserve the current behavior of `kill(+123, sig)` and `kill(-123, sig)` as sending a signal to a single process or to a process group, respectively, and will then allow `kill(+123*i, sig)` as sending a signal to all processes that are either within a process group have a direct or indirect parent within that process group. I don't know what we'd use the negative imaginary numbers for, but I'm sure we could think of something.

If not for the uncatchable SIGKILL/SIGSTOP, I'd say that any process that calls `setsid` is responsible for ensuring signal propagation across the pgid. But since those are uncatchable, I tend to shrug and figure that I'll avoid setsid wherever possible.

There was a proposal at one point that would have had `unshare(NEW_CGROUP)` place the process into a child cgroup, rather than merely changing the name of the current cgroup. This would have meant that cgroups could actually be used for nested process management. Unfortunately, there's no guarantee that a process can ever make nested cgroups it wouldn't be sound for all supported resource constraints, so that proposal never went in. But that would have been nice to actually have nestable job management.

▲Joker_vD 5 hours ago | parent [-]

> I'd say that any process that calls `setsid` is responsible for ensuring signal propagation across the pgid.

How?! After a process calls setsid(2), it becomes a leader of a new process group so it stops receiving signals from its former process group!

> But that would have been nice to actually have nestable job management.

Yes, it would be. Just imagine: a simple, straightforward way to group a bunch of processes (and their potential children, inescapably), signal them all at once, wait for them all at once, etc. Instead, we at best ended up with docker compose and k8s. And they kinda do solve that problem, no question about that but it's just so incredibly heavyweight...

▲MereInterest 4 hours ago | parent [-]

> How?! After a process calls setsid(2), it becomes a leader of a new process group so it stops receiving signals from its former process group!

By limiting its usage to the period between fork and exec, so that the process calling setsid knows that the parent process is propagating signals to it.

So, my phrasing was inaccurate to the point of being entirely incorrect. I should have said that any process that calls `setsid` is responsible for ensuring that signals are being propagated. (And saved! Definitely didn't make a mistake on the internet and then play it like I was right all along.)

▲Joker_vD 3 hours ago | parent [-]

> any process that calls `setsid` is responsible for ensuring that signals are being propagated.

Well, again, the process that calls setsid(2) ceases to receive the signals from its previous process group, so there is nothing for it to propagate. The only way this propagation can work is with cooperation from the parent process of the setsid-calling process: it will need to manually pass the group-wide signals to its setsid-calling child — which it can't reliably do for two obvious reasons.

> By limiting its usage to the period between fork and exec, so that the process calling setsid knows that the parent process is propagating signals to it.

Wait. Are you implying a scheme where the process A, that wants to do setsid(2), forks itself, and it's this child process B that does setsid(2) and all future actual work, while process A merely lives in a "while(1) { sig = sigwait(); signal(pidB, sig); }" loop forever? This almost works but doesn't survive SIGSTOP/SIGCONT/etc. and, of course, you can't propagate SIGKILL. And SIGKILL-propagation is arguably one of the main attraction of the process groups — you send SIGKILL to the process group (or a container, for that matter), and all of it dies with no further work on your part.

▲nocman a day ago | parent | prev | next [-]

I think you meant "Podman", but yes, Postman almost entirely sidesteps docker.

:D

▲tecleandor 19 hours ago | parent [-]

Sidesteps Docker, but the whole cgroups, namespacing and that kind of 'weird' stuff is still basically the same.

▲nocman 6 hours ago | parent [-]

I think you misread and/or misunderstood my reply.

▲asveikau a day ago | parent | prev [-]

I think the only thing in the "weird things" list that don't necessarily apply to another container system on linux would be the go-specific issues.

▲80fj0348i a day ago | parent [-]

Most of the other container runtimes don't require root for many of the use cases in which Docker does.

▲asveikau 13 hours ago | parent [-]

Care to give some examples?

A lot of the more important syscalls involved do require root.

▲80fj0348i 11 hours ago | parent [-]

I've used crun without root for a lot of practical use cases, if you are only doing limited use of the network and are careful with volume mounts it works pretty well.

Podman also has a fully rootless mode which can work for many uses: https://github.com/podman-container-tools/podman/blob/main/d...

▲asveikau 9 hours ago | parent [-]

I would guess that they do that by having a root daemon which authenticates requests from a unix domain socket, possibly using SO_PEERCRED.

Or a setuid binary

▲80fj0348i 3 hours ago | parent [-]

They mostly work by just implementing the functionality in userspace instead of using syscalls. No daemon needed.

▲asveikau 3 hours ago | parent [-]

That cannot be true. You need to tell the kernel about the namespaces, cgroups, and the new root. Otherwise it's not a container, and there is no reason or mechanism for a child proc to respect it. And if you let any old unprivileged process do this, you open up security problems.

▲80fj0348i 37 minutes ago | parent [-]

I've done this for practical use cases, like running a container inside another container that didn't have root privileges. It works fine for that use case. I'm not worried about restricting access of the process because it's already within a larger sandbox, I'm usually just trying to execute the command within the child container's filesystem (e.g. some vendor/partner software they ship as a container image).

I don't know why you're so shocked by this? This is all very basic use of the OCI spec.