Description
Issue Description
When a (non-exception) path in a .containerignore starts with a /
, making it an absolute path, it is not ignored. The documentation states that it should be:
The CLI interprets the .containerignore or .dockerignore file as a newline-separated list of patterns similar to the file globs of Unix shells. For the purposes of matching, the root of the context is considered to be both the working and the root directory. For example, the patterns /foo/bar and foo/bar both exclude a file or directory named bar in the foo subdirectory of PATH or in the root of the git repository located at URL. Neither excludes anything else.
Steps to reproduce the issue
Steps to reproduce the issue
echo -e "FROM fedora:41\nCOPY * /tmp/context/\nRUN ls -lRa /tmp/context" > Containerfile
echo "/foo" > .containerignore
touch foo
- podman build --ignorefile .containerignore -t example .
echo "foo" > .containerignore
- podman build --ignorefile .containerignore -t example .
Describe the results you received
The build process included the file foo
in the output of the RUN ls -lRa /tmp/context
command for the first build, but not the second.
Describe the results you expected
The build process does not include the file foo
in the output of the RUN ls -lRa /tmp/context
command in either build.
podman info output
Client:
APIVersion: 5.4.1
BuildOrigin: brew
Built: 1741713733
BuiltTime: Tue Mar 11 10:22:13 2025
GitCommit: ""
GoVersion: go1.24.1
Os: darwin
OsArch: darwin/amd64
Version: 5.4.1
host:
arch: amd64
buildahVersion: 1.39.2
cgroupControllers:
- cpu
- io
- memory
- pids
cgroupManager: systemd
cgroupVersion: v2
conmon:
package: conmon-2.1.12-3.fc41.x86_64
path: /usr/bin/conmon
version: 'conmon version 2.1.12, commit: '
cpuUtilization:
idlePercent: 99.73
systemPercent: 0.16
userPercent: 0.11
cpus: 16
databaseBackend: sqlite
distribution:
distribution: fedora
variant: coreos
version: "41"
eventLogger: journald
freeLocks: 2046
hostname: localhost.localdomain
idMappings:
gidmap:
- container_id: 0
host_id: 1000
size: 1
- container_id: 1
host_id: 100000
size: 1000000
uidmap:
- container_id: 0
host_id: 501
size: 1
- container_id: 1
host_id: 100000
size: 1000000
kernel: 6.12.13-200.fc41.x86_64
linkmode: dynamic
logDriver: journald
memFree: 2560954368
memTotal: 3098730496
networkBackend: netavark
networkBackendInfo:
backend: netavark
dns:
package: aardvark-dns-1.14.0-1.fc41.x86_64
path: /usr/libexec/podman/aardvark-dns
version: aardvark-dns 1.14.0
package: netavark-1.14.0-1.fc41.x86_64
path: /usr/libexec/podman/netavark
version: netavark 1.14.0
ociRuntime:
name: crun
package: crun-1.20-2.fc41.x86_64
path: /usr/bin/crun
version: |-
crun version 1.20
commit: 9c9a76ac11994701dd666c4f0b869ceffb599a66
rundir: /run/user/501/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL
os: linux
pasta:
executable: /usr/bin/pasta
package: passt-0^20250121.g4f2c8e7-2.fc41.x86_64
version: |
pasta 0^20250121.g4f2c8e7-2.fc41.x86_64
Copyright Red Hat
GNU General Public License, version 2 or later
<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
remoteSocket:
exists: true
path: unix:///run/user/501/podman/podman.sock
rootlessNetworkCmd: pasta
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: true
serviceIsRemote: true
slirp4netns:
executable: /usr/bin/slirp4netns
package: slirp4netns-1.3.1-1.fc41.x86_64
version: |-
slirp4netns version 1.3.1
commit: e5e368c4f5db6ae75c2fce786e31eef9da6bf236
libslirp: 4.8.0
SLIRP_CONFIG_VERSION_MAX: 5
libseccomp: 2.5.5
swapFree: 0
swapTotal: 0
uptime: 0h 10m 51.00s
variant: ""
plugins:
authorization: null
log:
- k8s-file
- none
- passthrough
- journald
network:
- bridge
- macvlan
- ipvlan
volume:
- local
registries:
search:
- docker.io
store:
configFile: /var/home/core/.config/containers/storage.conf
containerStore:
number: 1
paused: 0
running: 0
stopped: 1
graphDriverName: overlay
graphOptions: {}
graphRoot: /var/home/core/.local/share/containers/storage
graphRootAllocated: 106521055232
graphRootUsed: 8161787904
graphStatus:
Backing Filesystem: xfs
Native Overlay Diff: "true"
Supports d_type: "true"
Supports shifting: "false"
Supports volatile: "true"
Using metacopy: "false"
imageCopyTmpDir: /var/tmp
imageStore:
number: 45
runRoot: /run/user/501/containers
transientStore: false
volumePath: /var/home/core/.local/share/containers/storage/volumes
version:
APIVersion: 5.4.1
BuildOrigin: Fedora Project
Built: 1741651200
BuiltTime: Tue Mar 11 00:00:00 2025
GitCommit: b79bc8afe796cba51dd906270a7e1056ccdfcf9e
GoVersion: go1.23.7
Os: linux
OsArch: linux/amd64
Version: 5.4.1
Podman in a container
No
Privileged Or Rootless
Rootless
Upstream Latest Release
Yes
Additional environment details
No response
Additional information
I believe this is an issue with NewPatternMatcher()
in github.com/containers/storage/pkg/fileutils
. There is code in the function to remove a leading /
if the rule is an exception, but not if the rule is an exclusion.
This looks to have been missed in containers/storage@94b63f0.
Docker uses github.com/moby/patternmatcher/ignorefile.ReadAll()
to read and clean the paths from an ignorefile. It looks like podman has two implementations, but both are missing some of the cleaning behaviors present in the .../patternmatcher/ignorefile
package's implementation.