chainguard-dev / apko

Build OCI images from APK packages directly without Dockerfile
https://apko.dev
Apache License 2.0
1.2k stars 122 forks source link

Build seems to fail when recursive path contains symlinks. #362

Open Wulfre opened 2 years ago

Wulfre commented 2 years ago
     _      ____    _  __   ___
    / \    |  _ \  | |/ /  / _ \
   / _ \   | |_) | | ' /  | | | |
  / ___ \  |  __/  | . \  | |_| |
 /_/   \_\ |_|     |_|\_\  \___/
apko

GitVersion:    v0.5.0-136-g51ec859
GitCommit:     51ec859d4c8bf8cc64994a3755ce17a1a72ab70d
GitTreeState:  clean
BuildDate:     '1970-01-01T00:00:00Z'
GoVersion:     go1.19.1
Compiler:      gc
Platform:      linux/amd64
contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/edge/main
  packages:
    - alpine-baselayout
    - nginx

accounts:
  groups:
    - groupname: nginx
      gid: 10000
  users:
    - username: nginx
      uid: 10000

paths:
  - path: /run/nginx
    type: directory
    uid: 10000
    gid: 10000
    permissions: 0o755
  - path: /var/lib/nginx
    type: directory
    uid: 10000
    gid: 10000
    permissions: 0o755
    recursive: true

entrypoint:
  type: service-bundle
  services:
    nginx: /usr/sbin/nginx -g "daemon off;"
Error: failed to build layer image: failed to mutate paths: chmod /tmp/apko-235336285/var/lib/nginx/logs: no such file or directory
2022/09/29 03:26:58 error during command execution: failed to build layer image: failed to mutate paths: chmod /tmp/apko-235336285/var/lib/nginx/logs: no such file or directory

Build is successful when the recursive tag is removed from the /var/lib/nginx path.

The directory in question looks like this when the image is loaded and inspected:

ab9bfa5d4136:/# ls /var/lib/nginx -Al
total 8
drwxr-xr-x    2 root     root          4096 Jan  1  1970 html
lrwxrwxrwx    1 root     root            14 Jan  1  1970 logs -> /var/log/nginx
lrwxrwxrwx    1 root     root            22 Jan  1  1970 modules -> /usr/lib/nginx/modules
lrwxrwxrwx    1 root     root            10 Jan  1  1970 run -> /run/nginx
drwx------    2 193      194           4096 Jan  1  1970 tmp

This leads me to believe that the error is occurring once the builder hits the first symlink in the directory.

Wulfre commented 2 years ago

I was just trying another use case that involves symlinks and I got the same error, so it definitely seems like something is wrong with symlinks in some capacity.

contents:
    repositories:
        - https://dl-cdn.alpinelinux.org/alpine/edge/main
        - https://dl-cdn.alpinelinux.org/alpine/edge/community
    packages:
        - alpine-baselayout
        - ca-certificates-bundle
        - php8
        - php8-phar

paths:
    - path: /usr/bin/php
      type: symlink
      source: /usr/bin/php8
Error: failed to build layer image: failed to mutate paths: chmod /tmp/apko-4048355998/usr/bin/php: no such file or directory
2022/09/29 14:31:35 error during command execution: failed to build layer image: failed to mutate paths: chmod /tmp/apko-4048355998/usr/bin/php: no such file or directory
kaniini commented 2 years ago

In the latter case, it might be because php8 is not actually in /usr/bin? Try inspecting the image without the symlink and see if everything lines up as it should.

Though in any case, symlinks are always 0777 permissions themselves, so trying to chmod them seems wrong.

Wulfre commented 2 years ago
d1e63bcccc7b:/usr/bin# ls -al | grep php
-rwxr-xr-x    1 root     root       8399048 Jan  1  1970 php8

It does look like php8 is where I was expecting it to be, so I think there is an issue in both cases.

troyfolger commented 1 year ago

I'm not able to get symlinks to work at all:

contents:
  repositories:
    - https://packages.wolfi.dev/os
    - '@local /work/packages'
  packages:
    - wolfi-baselayout
    - tzdata
    - glibc
    - busybox
    - strace
accounts:
  groups:
    - groupname: nonroot
      gid: 65532
  users:
    - username: nonroot
      uid: 65532
  run-as: 65532
paths:
  - path: /etc/localtime
    type: symlink
    source: /usr/share/zoneinfo/GMT
    uid: 0
    gid: 0
    permissions: 0o777
...
Jan 25 22:34:51.964 [INFO] [arch:x86_64] creating user 65532(nonroot)
Jan 25 22:34:51.964 [WARNING] [arch:x86_64] guessing unset GID for user {nonroot 65532 0}
Jan 25 22:34:51.964 [INFO] [arch:x86_64] creating group 65532(nonroot)
Error: failed to build layer image: failed to mutate paths: chmod /tmp/apko-1508917688/etc/localtime: no such file or directory
2023/01/25 22:34:51 error during command execution: failed to build layer image: failed to mutate paths: chmod /tmp/apko-1508917688/etc/localtime: no such file or directory
kaniini commented 1 year ago

As previously stated, symlinks themselves are always 777. In this case, it is probably because the path mutations are done from outside the container image FS. We should fix that.

troyfolger commented 1 year ago

Yeah, I saw your comment. However, for me it fails with or without the permissions: line.

kneufeld-pbp commented 3 months ago

I am having the same issues with symlink

If there is a file already present, it fails with: Error: building layers: building layers: for arch "amd64": failed to mutate paths: mutating path "/var/log/nginx/access.log": symlinking "/dev/stdout" -> "/var/log/nginx/access.log": file already exists

It would be nice to have an option to force the symlink

and when there is no file, it fails with: Error: building layers: building layers: for arch "amd64": failed to mutate paths: symlink mutation on /var/log/nginx/access.log: chmod "/var/log/nginx/access.log": file does not exist

apko details:

$ docker run --rm --workdir /work -v "$PWD":/work cgr.dev/chainguard/apko version                                                                                                        
     _      ____    _  __   ___
    / \    |  _ \  | |/ /  / _ \
   / _ \   | |_) | | ' /  | | | |
  / ___ \  |  __/  | . \  | |_| |
 /_/   \_\ |_|     |_|\_\  \___/
apko

GitVersion:    v0.17.0
GitCommit:     636d87f1c66181d4f1ff146595ddc157a033f723
GitTreeState:  clean
BuildDate:     '2024-07-24T20:01:00Z'
GoVersion:     go1.22.5
Compiler:      gc
Platform:      linux/amd64
contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/v3.20/main
    - https://dl-cdn.alpinelinux.org/alpine/v3.20/community
    - "@nginx https://nginx.org/packages/alpine/v3.20/main"
  keyring:
    - https://nginx.org/keys/nginx_signing.rsa.pub
  packages:
    - alpine-baselayout
    - tzdata
    - ca-certificates
    - nginx@nginx

archs:
  - x86_64

stop-signal: SIGQUIT
cmd: nginx -g "daemon off;"

# optional environment configuration
environment:
  PATH: /usr/sbin:/sbin:/usr/bin:/bin

# optional user mutations
accounts:
  groups:
    - groupname: nginx
      gid: 101
  users:
    - username: nginx
      uid: 101
# optional path mutations
paths:
  - path: /var/cache/nginx
    type: directory
  - path: /var/log/nginx
    type: directory
  - path: /var/log/nginx/access.log
    source: /dev/stdout
    type: symlink
    uid: 0
    gid: 0
    permissions: 0o777
  - path: /var/log/nginx/error.log
    source: /dev/stderr
    uid: 0
    gid: 0
    type: symlink
    permissions: 0o777