podman-compose
podman-compose copied to clipboard
podman-compose sets userns to container instead of pod
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
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
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
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.
@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 togetherThis is because
podman-composefirst 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 propertyuserns_modeis always passed topodmanthe 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-composearguments directly in the command line$ podman-compose --pod-args '--userns keep-id' upreferences:
- 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
...
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.
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: @.***>
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
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
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?
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]
To have the old non pod creating behavior you can also set --in-pod e.g. podman-compose --in-pod false up.
--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!