containers / podman-compose

a script to run docker-compose.yml using podman
GNU General Public License v2.0
5.12k stars 486 forks source link

Detect case when port forwarding is used together with uid/gid mapping on Podman 3.4.x and issue warning #986

Open leiless opened 5 months ago

leiless commented 5 months ago

Describe the bug

I'm using podman-compose to deploy a simple app, but after the uid/gid mapping is set, the port forwarding is not working.

To Reproduce

The Dockerfile

FROM alpine:3.20

ARG NEW_UID=2000
ARG NEW_GID=2000

RUN set -eufxo pipefail && \
    apk add --no-cache curl darkhttpd iproute2-ss && \
    addgroup -g $NEW_GID nonroot && \
    adduser -D -s /bin/sh -u $NEW_UID -G nonroot nonroot

USER nonroot
WORKDIR /home/nonroot

docker-compose.yaml

version: '3.7'

services:
    app:
        image: local/podman-compose-uid-gid-maps-port-fwd-not-working
        build:
            context: .
        restart: "unless-stopped"
        user: "2000:2000"
        x-podman:
            uidmaps:
                - "0:1:2000"
                - "2000:0:1"
                - "2001:2001:63536"
            gidmaps:
                - "0:1:2000"
                - "2000:0:1"
                - "2001:2001:63536"
        ports:
            - 127.0.0.1:30020:8080/tcp
        #command: sleep infinity
        command: darkhttpd /etc --no-listing

networks:
    net:
        driver: bridge
        ipam:
            driver: default

Run

$ podman image rm local/podman-compose-uid-gid-maps-port-fwd-not-working || true
Error: local/podman-compose-uid-gid-maps-port-fwd-not-working: image not known

$ podman-compose version
podman-compose version: 1.0.7
['podman', '--version', '']
using podman version: 3.4.4
podman-compose version 1.0.7
podman --version
podman version 3.4.4
exit code: 0

$ podman-compose up
podman-compose version: 1.0.7
['podman', '--version', '']
using podman version: 3.4.4
** excluding:  set()
['podman', 'inspect', '-t', 'image', '-f', '{{.Id}}', 'local/podman-compose-uid-gid-maps-port-fwd-not-working']
Error: error inspecting object: local/podman-compose-uid-gid-maps-port-fwd-not-working: image not known
podman build -f ./Dockerfile -t local/podman-compose-uid-gid-maps-port-fwd-not-working .
STEP 1/6: FROM alpine:3.20
STEP 2/6: ARG NEW_UID=2000
--> Using cache e03b56a5afc3faf786d227ba9baf869f66093c71da6a3abeb98068f7ddede06d
--> e03b56a5afc
STEP 3/6: ARG NEW_GID=2000
--> Using cache 7b12ebd82edc93140a88d04ec770c3c4f84ddad7070cd062f590edc11ceb23d8
--> 7b12ebd82ed
STEP 4/6: RUN set -eufxo pipefail &&     apk add --no-cache curl darkhttpd iproute2-ss &&     addgroup -g $NEW_GID nonroot &&     adduser -D -s /bin/sh -u $NEW_UID -G nonroot nonroot
+ apk add --no-cache curl darkhttpd iproute2-ss
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/14) Installing ca-certificates (20240226-r0)
(2/14) Installing brotli-libs (1.1.0-r2)
(3/14) Installing c-ares (1.28.1-r0)
(4/14) Installing libunistring (1.2-r0)
(5/14) Installing libidn2 (2.3.7-r0)
(6/14) Installing nghttp2-libs (1.62.1-r0)
(7/14) Installing libpsl (0.21.5-r1)
(8/14) Installing zstd-libs (1.5.6-r0)
(9/14) Installing libcurl (8.8.0-r0)
(10/14) Installing curl (8.8.0-r0)
(11/14) Installing darkhttpd (1.16-r0)
Executing darkhttpd-1.16-r0.pre-install
(12/14) Installing libcap2 (2.70-r0)
(13/14) Installing libmnl (1.0.5-r2)
(14/14) Installing iproute2-ss (6.9.0-r0)
Executing busybox-1.36.1-r29.trigger
Executing ca-certificates-20240226-r0.trigger
OK: 13 MiB in 28 packages
+ addgroup -g 2000 nonroot
+ adduser -D -s /bin/sh -u 2000 -G nonroot nonroot
--> f63d4c78b90
STEP 5/6: USER nonroot
--> bf49beaf33f
STEP 6/6: WORKDIR /home/nonroot
COMMIT local/podman-compose-uid-gid-maps-port-fwd-not-working
--> c9798460761
Successfully tagged localhost/local/podman-compose-uid-gid-maps-port-fwd-not-working:latest
c979846076162ecde05a2d2754239366165a61ab26896c89fb5a857d8e664dbd
exit code: 0
['podman', 'ps', '--filter', 'label=io.podman.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working', '-a', '--format', '{{ index .Labels "io.podman.compose.config-hash"}}']
podman pod create --name=pod_podman-compose-uid-gid-maps-port-fwd-not-working --infra=false --share=
2b58a56e13dab971372d1dce70922429981fd290485005cb37d32eb2225aca0c
exit code: 0
['podman', 'network', 'exists', 'podman-compose-uid-gid-maps-port-fwd-not-working_net']
podman create --name=podman-compose-uid-gid-maps-port-fwd-not-working_app_1 --pod=pod_podman-compose-uid-gid-maps-port-fwd-not-working --label io.podman.compose.config-hash=a4c59dd80db8e11022c65068660294de4ee02f7625030caa95f198af53bd56b9 --label io.podman.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working --label io.podman.compose.version=1.0.7 --label PODMAN_SYSTEMD_UNIT=podman-compose@podman-compose-uid-gid-maps-port-fwd-not-working.service --label com.docker.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working --label com.docker.compose.project.working_dir=/tmp/podman-compose-uid-gid-maps-port-fwd-not-working --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=app --net podman-compose-uid-gid-maps-port-fwd-not-working_net --network-alias app -p 127.0.0.1:30020:8080/tcp -u 2000:2000 --restart unless-stopped --uidmap 0:1:2000 --uidmap 2000:0:1 --uidmap 2001:2001:63536 --gidmap 0:1:2000 --gidmap 2000:0:1 --gidmap 2001:2001:63536 local/podman-compose-uid-gid-maps-port-fwd-not-working darkhttpd /etc --no-listing
4409502a0777254f7ee35233d75844643f18810d0f1ae3c39a646de9d0bf7f6d
exit code: 0
podman start -a podman-compose-uid-gid-maps-port-fwd-not-working_app_1
[app] | darkhttpd/1.16, copyright (c) 2003-2024 Emil Mikulic.

Expected behavior

The port forwarding 127.0.0.1:30020:8080/tcp should be working.

Actual behavior

The port forwarding 127.0.0.1:30020:8080/tcp is not working.

# On host machine
# Exit code: 1
$ sudo netstat -tulpn | grep containers

# On host machine
# Exit code: 1
$ sudo netstat -tulpn | grep 30020

$ docker ps
CONTAINER ID  IMAGE                                                                    COMMAND               CREATED        STATUS            PORTS                      NAMES
6cb5d796b042  localhost/local/podman-compose-uid-gid-maps-port-fwd-not-working:latest  darkhttpd /etc --...  3 minutes ago  Up 3 minutes ago  127.0.0.1:30020->8080/tcp  podman-compose-uid-gid-maps-port-fwd-not-working_app_1

$ docker exec -it podman-compose-uid-gid-maps-port-fwd-not-working_app_1 sh
~ $ ss -tlpn
State     Recv-Q     Send-Q         Local Address:Port         Peer Address:Port    Process
LISTEN    0          4096                 0.0.0.0:8080              0.0.0.0:*        users:(("darkhttpd",pid=1,fd=3))

~ $ curl -v localhost:8080/alpine-release
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* connect to ::1 port 8080 from ::1 port 42796 failed: Connection refused
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080
> GET /alpine-release HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Wed, 03 Jul 2024 09:09:13 GMT
< Server: darkhttpd/1.16
< Accept-Ranges: bytes
< Keep-Alive: timeout=30
< Content-Length: 7
< Content-Type: application/octet-stream
< Last-Modified: Tue, 18 Jun 2024 14:15:41 GMT
<
3.20.1
* Connection #0 to host localhost left intact

# On host machine
$ curl -vL localhost:30020
*   Trying 127.0.0.1:30020...
* connect to 127.0.0.1 port 30020 failed: Connection refused
*   Trying ::1:30020...
* connect to ::1 port 30020 failed: Connection refused
* Failed to connect to localhost port 30020 after 0 ms: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 30020 after 0 ms: Connection refused

Environment:

I do NOT have any SELinux or AppArmor settings.

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

$ podman version
Version:      3.4.4
API Version:  3.4.4
Go Version:   go1.18.1
Built:        Thu Jan  1 08:00:00 1970
OS/Arch:      linux/amd64

$ podman info
host:
  arch: amd64
  buildahVersion: 1.23.1
  cgroupControllers: []
  cgroupManager: cgroupfs
  cgroupVersion: v1
  conmon:
    package: 'conmon: /usr/bin/conmon'
    path: /usr/bin/conmon
    version: 'conmon version 2.0.25, commit: unknown'
  cpus: 12
  distribution:
    codename: jammy
    distribution: ubuntu
    version: "22.04"
  eventLogger: journald
  hostname: DESKTOP-BNE42DB
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
  kernel: 5.15.133.1-microsoft-standard-WSL2
  linkmode: dynamic
  logDriver: journald
  memFree: 1260052480
  memTotal: 8159125504
  ociRuntime:
    name: crun
    package: 'crun: /usr/bin/crun'
    path: /usr/bin/crun
    version: |-
      crun version 0.17
      commit: 0e9229ae34caaebcb86f1fde18de3acaf18c6d9a
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL
  os: linux
  remoteSocket:
    exists: true
    path: /run/user/1000/podman/podman.sock
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    seccompProfilePath: /usr/share/containers/seccomp.json
    selinuxEnabled: false
  serviceIsRemote: false
  slirp4netns:
    executable: /usr/bin/slirp4netns
    package: 'slirp4netns: /usr/bin/slirp4netns'
    version: |-
      slirp4netns version 1.0.1
      commit: 6a7b16babc95b6a3056b33fb45b74a6f62262dd4
      libslirp: 4.6.1
  swapFree: 2147483648
  swapTotal: 2147483648
  uptime: 56h 2m 5.65s (Approximately 2.33 days)
plugins:
  log:
  - k8s-file
  - none
  - journald
  network:
  - bridge
  - macvlan
  volume:
  - local
registries: {}
store:
  configFile: /home/lei/.config/containers/storage.conf
  containerStore:
    number: 1
    paused: 0
    running: 1
    stopped: 0
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /home/lei/.local/share/containers/storage
  graphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Using metacopy: "false"
  imageStore:
    number: 206
  runRoot: /run/user/1000/containers
  volumePath: /home/lei/.local/share/containers/storage/volumes
version:
  APIVersion: 3.4.4
  Built: 0
  BuiltTime: Thu Jan  1 08:00:00 1970
  GitCommit: ""
  GoVersion: go1.18.1
  OsArch: linux/amd64
  Version: 3.4.4
leiless commented 5 months ago

If I do the following changes to the docker-compose.yaml, the port forwarding will work:

--- a/podman-compose-uid-gid-maps-port-fwd-not-working/docker-compose.yaml
+++ b/podman-compose-uid-gid-maps-port-fwd-not-working/docker-compose.yaml
@@ -7,15 +7,6 @@ services:
             context: .
         restart: "unless-stopped"
         user: "2000:2000"
-        x-podman:
-            uidmaps:
-                - "0:1:2000"
-                - "2000:0:1"
-                - "2001:2001:63536"
-            gidmaps:
-                - "0:1:2000"
-                - "2000:0:1"
-                - "2001:2001:63536"
         ports:
             - 127.0.0.1:30020:8080/tcp
         #command: sleep infinity
$ podman-compose up
podman-compose version: 1.0.7
['podman', '--version', '']
using podman version: 3.4.4
** excluding:  set()
['podman', 'inspect', '-t', 'image', '-f', '{{.Id}}', 'local/podman-compose-uid-gid-maps-port-fwd-not-working']
['podman', 'ps', '--filter', 'label=io.podman.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working', '-a', '--format', '{{ index .Labels "io.podman.compose.config-hash"}}']
podman pod create --name=pod_podman-compose-uid-gid-maps-port-fwd-not-working --infra=false --share=
b919e9cfe8d4c992b532ad48014468cbf961d684821b6d4a53c78338876073a6
exit code: 0
['podman', 'network', 'exists', 'podman-compose-uid-gid-maps-port-fwd-not-working_net']
podman create --name=podman-compose-uid-gid-maps-port-fwd-not-working_app_1 --pod=pod_podman-compose-uid-gid-maps-port-fwd-not-working --label io.podman.compose.config-hash=cb2cd1f4df19fc6ac17dd57e2fc757831b79e6100e25159fa949d04b23bf0f51 --label io.podman.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working --label io.podman.compose.version=1.0.7 --label PODMAN_SYSTEMD_UNIT=podman-compose@podman-compose-uid-gid-maps-port-fwd-not-working.service --label com.docker.compose.project=podman-compose-uid-gid-maps-port-fwd-not-working --label com.docker.compose.project.working_dir=/tmp/podman-compose-uid-gid-maps-port-fwd-not-working --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=app --net podman-compose-uid-gid-maps-port-fwd-not-working_net --network-alias app -p 127.0.0.1:30020:8080/tcp -u 2000:2000 --restart unless-stopped local/podman-compose-uid-gid-maps-port-fwd-not-working darkhttpd /etc --no-listing
7645da5d504e94d166e1debdf3c986adc85f966d3f5351c9a8bc13ea3e2ba89f
exit code: 0
podman start -a podman-compose-uid-gid-maps-port-fwd-not-working_app_1
[app] | darkhttpd/1.16, copyright (c) 2003-2024 Emil Mikulic.

$ docker ps
CONTAINER ID  IMAGE                                                                    COMMAND               CREATED        STATUS            PORTS                      NAMES
7645da5d504e  localhost/local/podman-compose-uid-gid-maps-port-fwd-not-working:latest  darkhttpd /etc --...  3 minutes ago  Up 3 minutes ago  127.0.0.1:30020->8080/tcp  podman-compose-uid-gid-maps-port-fwd-not-working_app_1

$ sudo netstat -tulpn | grep containers
tcp        0      0 127.0.0.1:30020         0.0.0.0:*               LISTEN      653780/containers-r

$ curl -vL localhost:30020/alpine-release
*   Trying 127.0.0.1:30020...
* Connected to localhost (127.0.0.1) port 30020 (#0)
> GET /alpine-release HTTP/1.1
> Host: localhost:30020
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 03 Jul 2024 09:22:30 GMT
< Server: darkhttpd/1.16
< Accept-Ranges: bytes
< Keep-Alive: timeout=30
< Content-Length: 7
< Content-Type: application/octet-stream
< Last-Modified: Tue, 18 Jun 2024 14:15:41 GMT
<
3.20.1
* Connection #0 to host localhost left intact
leiless commented 5 months ago

There might be an issue with how Podman 3.4.x handles port forwarding in conjunction with UID/GID mappings.

leiless commented 5 months ago

Closed, see: https://github.com/containers/podman/issues/23171

p12tic commented 4 months ago

I think podman-compose should detect this scenario and issue a warning. It's easy enough to do so and will save users' time.