podman-compose icon indicating copy to clipboard operation
podman-compose copied to clipboard

podman-compose sets userns to container instead of pod

Open hadmut opened this issue 2 years ago • 11 comments

Hi, using

  • Ubuntu 22.04
  • podman 3.4.4
  • today's developer version of podman-create https://github.com/containers/podman-compose/archive/devel.tar.gz

I found a problem with userns. I was debugging why I cannot connect to port of containers when running with userns = keep-id.

consider the following docker-compose.yaml

services:

application: image: alpine command: nc -n -l -p 9000 -v

userns_mode: keep-id

ports:
  - "9000:9000"

run with podman-compose up --force-recreate it works as expected: Listens on port 9000. Just run a date | nc 127.0.0.1 9000 on the host machine and the container will print the date and terminate.

In contrast, when setting environment variable PODMAN_USERNS=keep-id , the host cannot connect to the container for not obvious reasons.

But when uncommenting the userns_mode line in the example above instead of using the environment, the podman create command issued by podman-compose prints an error message:

Error: --userns and --pod cannot be set together

As far as I can see, the mistake (at least with podman 3.x) is that podman-compose attaches the --userns keep-id parameter to the podman command to create the container, where – as far as I can see – it must be used to create the pod, if a pod is used. For reasons I have not yet understood podman does not seem to deal correctly with then environment variable in this case.

regards

hadmut avatar Mar 30 '23 22:03 hadmut

Hi @hadmut,

I reproduced your error with the following compose file:

services:
  application:
    image: alpine
    command: nc -n -l -p 9000 -v
    userns_mode: keep-id
    ports:
    - "9000:9000"

The error is raised by podman:

Error: --userns and --pod cannot be set together

This is because podman-compose first creates an empty pod and creates the container within it afterwards (https://github.com/containers/podman-compose/blob/devel/podman_compose.py#L908). It might be indeed a bug as the container property userns_mode is always passed to podman the same way.

Workaround

As a workaround I managed to run your compose file by removing the userns_mode:

services:

  application:
    image: alpine
    command: nc -n -l -p 9000 -v
    ports:
    - "9000:9000"

and passing it as part of the podman-compose arguments directly in the command line

$ podman-compose --pod-args '--userns keep-id' up

references:

  • https://docs.podman.io/en/latest/markdown/options/userns.container.html#userns-mode

bugfest avatar Apr 07 '23 17:04 bugfest

consider this

I have a NodeJs service and a redis service I want userns to be passed to NodeJs so that my code is volume mounted inside the container and I use my IDE on my code but I don't want to set userns to redis service

the problem that podman does not let me set it per container if they are in one pod. which is strange

muayyad-alsadi avatar Apr 09 '23 11:04 muayyad-alsadi

The same problem seems to exist with the hostname. When using docker-compose.yaml, the hostname is set per container, and for some services it is necessary to give the container a particular hostname, which might be crucial for the service.

podman-compose + podman then issues

Error: invalid config provided: cannot set hostname when joining the pod UTS namespace: invalid configuration

so the hostname needs to be set in the pod instead of in the container as well.

hadmut avatar Apr 15 '23 19:04 hadmut

@bugfest

Hi @hadmut,

I reproduced your error with the following compose file:

services:
  application:
    image: alpine
    command: nc -n -l -p 9000 -v
    userns_mode: keep-id
    ports:
    - "9000:9000"

The error is raised by podman:

Error: --userns and --pod cannot be set together

This is because podman-compose first creates an empty pod and creates the container within it afterwards (https://github.com/containers/podman-compose/blob/devel/podman_compose.py#L908). It might be indeed a bug as the container property userns_mode is always passed to podman the same way.

Workaround

As a workaround I managed to run your compose file by removing the userns_mode:

services:

  application:
    image: alpine
    command: nc -n -l -p 9000 -v
    ports:
    - "9000:9000"

and passing it as part of the podman-compose arguments directly in the command line

$ podman-compose --pod-args '--userns keep-id' up

references:

  • https://docs.podman.io/en/latest/markdown/options/userns.container.html#userns-mode

Alternatively, instead of passing through command line args, you can specify the "PODMAN_USERNS" environment variable (https://docs.podman.io/en/v4.4/markdown/options/userns.container.html#userns-mode) directly in the docker-compose.yml file.

Specifying through this environment variable makes it easy for teardown with podman-compose down.

Here is an example of my docker-compose.yml file

...
    environment:
      PODMAN_USERNS: "keep-id:uid=${MY_UID}:1000,gid=${MY_GID}:1000" # Define in .env
...

andrew-ma avatar May 26 '24 08:05 andrew-ma

Workaround: Putting PODMAN_USERNS=keep-id in .env instead of userns_mode: "keep-id" inside the compose file.

...
    environment:
      PODMAN_USERNS: "keep-id:uid=${MY_UID}:1000,gid=${MY_GID}:1000" # Define in .env
...

@andrew-ma By doing this, the env var is forwarding inside the container podman -e .... Podman requires it outside of the scope of the container to take it in account as it is executed on the host.

Morikko avatar May 28 '24 16:05 Morikko

You sure, I tested it to map to 9999 for the uid and gid on the right side of the colon and it seemed to work fine. I am using 1.0.6 btw. Can you try this on your environment and see if it works on your end?

On Tue, May 28, 2024 at 12:18 PM Eric Masseran @.***> wrote:

Workaround: Putting PODMAN_USERNS=keep-id in .env instead of userns_mode: "keep-id" inside the compose file.

... environment: PODMAN_USERNS: "keep-id:uid=${MY_UID}:1000,gid=${MY_GID}:1000" # Define in .env ...

@andrew-ma https://github.com/andrew-ma By doing this, the env var is forwarding inside the container podman -e .... Podman requires it outside of the scope of the container to take it in account as it is executed on the host.

— Reply to this email directly, view it on GitHub https://github.com/containers/podman-compose/issues/654#issuecomment-2135644779, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEUJT4VGZOZTOT2BDNPD4KTZESU4RAVCNFSM6AAAAAAWN5JWJGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZVGY2DINZXHE . You are receiving this because you were mentioned.Message ID: @.***>

andrew-ma avatar May 29 '24 01:05 andrew-ma

How exactly does this workaround work?

edit:

I have created a .env file next to the compose.yaml, that contains

export PODMAN_USERNS=keep-id:uid=8983,gid=8983

This works. Also without export works.

PODMAN_USERNS=keep-id:uid=8983,gid=8983

white-gecko avatar Jun 25 '24 16:06 white-gecko

Upon updating podman-compose from v1.0.6 to v1.2.0 we have noticed that our previously working docker-compose.yml files are now throwing the following error that a few of you have been experiencing.

Error: --userns and --pod cannot be set together

What we have noticed is that v1.2.0 now introduces the creation of a pod before creating the container as well as the --pod flag being appended to the podman create step, ultimately causing the error previously mentioned.

Below is the diff of the two podman-compose up operations, as well as the docker-compose.yml file used.

--- compose-v1.0.6	2024-08-06 23:02:18.965427033 +0000
+++ compose-v1.2.0	2024-08-06 23:01:37.137009514 +0000
@@ -1,20 +1,23 @@
-docker compose up
+docker compose --verbose up
 >>>> Executing external compose provider "/usr/local/bin/podman-compose". Please refer to the documentation for details. <<<<
 
-podman-compose version: 1.0.6
 ['podman', '--version', '']
 using podman version: 5.1.2
-** excluding:  set()
+** excluding: set()
 ['podman', 'inspect', '-t', 'image', '-f', '{{.Id}}', 'my-ubuntu-devel:latest']
 ['podman', 'ps', '--filter', 'label=io.podman.compose.project=ubuntu-project', '-a', '--format', '{{ index .Labels "io.podman.compose.config-hash"}}']
+podman pod create --name=pod_ubuntu-project --infra=false --share=
+82ce365d1c34e9b0ef517110e047234e6f28219be2062fbe95ecfa5f8fcbfb17
+exit code: 0
 podman volume inspect ubuntu-project_vscode-config || podman volume create ubuntu-project_vscode-config
 ['podman', 'volume', 'inspect', 'ubuntu-project_vscode-config']
 ['podman', 'network', 'exists', 'ubuntu-project_nw']
 podman create 
     --name=ubuntu-devel 
-    --label io.podman.compose.config-hash=96277a074c9f1319b46ee0ee6ed685481235fe96a7e8d9fe1d8c3637eee04f2d 
+    --pod=pod_ubuntu-project 
+    --label io.podman.compose.config-hash=8d83065764f214a93bfdc9900771a834de5ae2cbbc81493afd523cc3357d6a1d 
     --label io.podman.compose.project=ubuntu-project 
-    --label io.podman.compose.version=1.0.6 
+    --label io.podman.compose.version=1.2.0 
     --label [email protected] 
     --label com.docker.compose.project=ubuntu-project 
     --label com.docker.compose.project.working_dir=/mnt/intA-ssdr1-480gb/groberts/dev/github/wcsng-admin-tools/docker-base-templates/example-project/ubuntu-project 
@@ -24,8 +27,14 @@
-    --net ubuntu-project_nw 
-    --network-alias ubuntu-devel -p 127.0.0.1:15488:5901 -p 127.0.0.1:15489:6080 
+    --network=ubuntu-project_nw 
+    --network-alias=ubuntu-devel -p 127.0.0.1:15488:5901 -p 127.0.0.1:15489:6080 
     --userns keep-id:uid=1000,gid=1000 -w /home/user/ProjDir my-ubuntu-devel:latest
-25e038c24d635017e283c968c9c26e91b622b00a45a1a57a91d0865451ffa0f7
-exit code: 0
+Error: --userns and --pod cannot be set together
+
+exit code: 125
+
+podman start -a ubuntu-devel
+[ubuntu-devel] | Error: no container with name or ID "ubuntu-devel" found: no such container
+
+exit code: 125
docker-compose.yml
version: "3.9"
services:
  ubuntu-devel:
    build:
      context: .
      dockerfile: ubuntu-devel.dockerfile
    image: my-ubuntu-devel:latest
    container_name: ubuntu-devel
    userns_mode: "keep-id:uid=1000,gid=1000"
    networks:
      - nw
    ports:
      - 127.0.0.1:15488:5901
      - 127.0.0.1:15489:6080

    working_dir: "/home/user/ProjDir"

volumes:
  vscode-config:
    driver: local
networks:
  nw:
    driver: bridge

empire-penguin avatar Aug 06 '24 23:08 empire-penguin

About the workaround when setting userns in an environment: This then applies to all containers/services started in the compose file, right? So when I start 3 services where only one needs the userns handling, now all 3 get it?

sothawo avatar Aug 21 '24 06:08 sothawo

Getting rid of pod creation steps in podman-compose.py reverts the behavior back to that of v1.0.6, which works as expected.

git apply the patch below to bypass the issue.

diff --git a/podman_compose.py b/podman_compose.py
index db6dc58..a849259 100755
--- a/podman_compose.py
+++ b/podman_compose.py
@@ -1045,8 +1045,6 @@ async def container_to_args(compose, cnt, detached=True):
     if detached:
         podman_args.append("-d")
 
-    if pod:
-        podman_args.append(f"--pod={pod}")
     deps = []
     for dep_srv in cnt.get("_deps", None) or []:
         deps.extend(compose.container_names_by_service.get(dep_srv, None) or [])
@@ -2538,7 +2536,6 @@ async def compose_up(compose: PodmanCompose, args):
 
     podman_command = "run" if args.detach and not args.no_start else "create"
 
-    await create_pods(compose, args)
     for cnt in compose.containers:
         if cnt["_service"] in excluded:
             log.debug("** skipping: %s", cnt["name"])
@@ -2694,8 +2691,6 @@ async def compose_down(compose: PodmanCompose, args):
 
     if excluded:
         return
-    for pod in compose.pods:
-        await compose.podman.run([], "pod", ["rm", pod["name"]])
     for network in await compose.podman.network_ls():
         await compose.podman.run([], "network", ["rm", network])
 
@@ -2721,7 +2716,6 @@ async def compose_ps(compose, args):
     "create a container similar to a service to run a one-off command",
 )
 async def compose_run(compose, args):
-    await create_pods(compose, args)
     compose.assert_services(args.service)
     container_names = compose.container_names_by_service[args.service]
     container_name = container_names[0]

sreevatsank1999 avatar Nov 01 '24 06:11 sreevatsank1999

To have the old non pod creating behavior you can also set --in-pod e.g. podman-compose --in-pod false up.

white-gecko avatar Nov 05 '24 09:11 white-gecko

--in-pod false

This was key when I upgraded from podman compose 1.0.x to 1.4 and noticed that I could no longer simply start podman compose with PODMAN_USERNS=keep-id set and use my host's uid / gid as defined in my compose.yml service's user field when operating on files bind mounted from the host.

Thank you!

qhaas avatar Jun 24 '25 19:06 qhaas