Closed WesselAtWork closed 1 year ago
Does this syntax COPY --chmod='+x' src/somecmd /bin/somecmd Work on Docker?
Yes it does.
You need to enable build-kit with DOCKER_BUILDKIT=1
For me this isn't such a big issue. Using 755
is acceptable.
Did take my a little to figure out what was wrong though, my first Googling only showed using the +x
.
Eventually I noticed that 755
worked fine.
Interested in opening a PR for this?
@nalind @flouthoc Would this be easy to add?
Thinking about it, I would actually love to dig into the go code and learn how buildah functions!
Investigating the chmod spec for the +x
forms of the octal syntax also sounds cool!
I can also imagine setting up test cases with bats to compare the --chmod
functionality with the unix chmod
command...
Sadly I won't have too much free time in the next month or two.
For now I'll try to make some time but I won't be able to properly look at it until at least 2 months from now.
Probably involve creating a converter/checker type function to take a MaybeChmod
and interpret the content.
Should then return what os.FileMode() expects to see.
https://github.com/containers/buildah/blob/02db353d2beb30a28340cb7267f10adacdca9a70/add.go#L279-L286
I'm thinking:
if options.Chmod != "" {
p, err := lib.ParseChmod(options.Chmod) //lib placholder
if err != nil {
return fmt.Errorf("parsing chmod %q: %w", options.Chmod, err)
}
perm := os.FileMode(p)
chmodDirsFiles = &perm
}
The only issue then is getting the flag spec of what is allowed and not. Having a little trouble finding the full scope though.
Maybe drop it down a step?
if options.Chmod != "" {
perm, err := lib.ParseChmod(options.Chmod) //lib placholder
if err != nil {
return fmt.Errorf("parsing chmod %q: %w", options.Chmod, err)
}
chmodDirsFiles = &perm
}
Then ParseChmod
would be something like:
func ParseChmod(maybeChmod string) (FileMode, error) {
//parse parse parse...
return os.FileMode(p), nil
}
Not sure what is a better.
I think I ran into a limitation of the stdlib
I found a very helpful spec doc for the chmod formats.
The different formats are called Symbolic and Absolute.
Absolute is the 0755
format and Symbolic is the uo+rw
format.
The symbolic format has 3 directives:
+
-
=
Meaning you can specify things like:
u+r
(set the read bit on the user octet [xxx|1xx|xxx|xxx]) u-r
(unset the read bit on the user octet [xxx|0xx|xxx|xxx])u=r
(sets the user octet to only read, [xxx|100|xxx|xxx])The problem is that os.FileMode only deals in the absolute forms.
No biggy. That just means we have to stat the file beforehand and manually add
or subtract
the relevant bits.
Problem is that most things seem to assume Absolute mode.
For instance: here where you are setting the mode
in the header of a tar archive for a remote source:
https://github.com/containers/buildah/blob/02db353d2beb30a28340cb7267f10adacdca9a70/add.go#L143-L154
The documentation for tar.Header doesn't mention adding or subtracting from the mode specified, so I have to assume it's absolute.
What makes this even more annoying is that the tar command has a --mode
flag that accepts Symbolic form chmod arguments.
Might be possible to do something with the reader.Next() ?
For forward compatibility, users that retrieve a Header from Reader.Next, mutate it in some ways, and then pass it back to Writer.WriteHeader should do so by creating a new Header and copying the fields that they are interested in preserving.
The local case I am unsure. https://github.com/containers/buildah/blob/02db353d2beb30a28340cb7267f10adacdca9a70/add.go#L510-L523
The copier
code is big (I'd need more time to dig into it) but it looks to be possible (maybe).
For instance in the directory case:
You are already stat-ing the directory so applying additions and subtractions shouldn't be too difficult. e.g.
mode := ChmodVariable.apply(st.Mode())
This would require an non-insignificant amount of refactoring as far as I can tell.
Everywhere you are passing a naked os.FileMode
or uint64
/unit32
for the permisison mode
, you'd need to replace with a new type.
A custom Chmod
type, that has some kind of .apply()
method you could use to "apply" it to another mode.
This would probably require special handling in the case of directories. You'd have to manually iterate through the directory and stat the files to individually apply the modes.
If you know more about the code base or I missed something with the file mode please let me know. It doesn't feel like it should be this difficult.
It might not reject the syntax, but are we sure it works as intended? When I try it with 20.10.23 locally, the builder seems to just ignore "--chmod=+x" or "--chmod=u+wx".
A friendly reminder that this issue had no activity for 30 days.
Since we heard no further feedback and this does not seem to work on Docker, closing.
Hi all.
Just wanted to apologise for letting this die, got busy with other things.
Also wow that was a miss on my part. I just half checked that docker "worked" with the --chmod=+x
flag, missing that, without specifying anything, the file I used already had eXecute permissions.
Trying with -x
or with other combinations doesn't work and I should have maybe been a little more through.
Additionally, it seems docker
with buildkit is actually ignoring the flag
CACHED [2/2] COPY --chmod=+w ./sometext.sh /bin/somecmd
here I have changed from +x
to +w
and it used the cached layer which is not how that is supposed to work.
I've been trying to understand how I even though this was possible in docker in the first place. I think I found a SO that suggested using it but googling I can't find it again. It seems to just have popped into my head and I was convinced it was possible :P.
Feel free to open again if docker changes in the future.
Oh I actually did screw around with a helper library. GOLANG doesn't natively understand Chmod in the symbolic format and I couldn't find any "off the shelf" libraries to help (historically you should take this with a grain of salt :P). Feel free to look at this if you need to implement in the future.
I haven't really worked with GOLANG before so I apologise for the what-ever-the-heck pattern I tried to follow here. The most usefull thing from this should be the REGEX and the documentation which was the most difficult to obtain.
REGEX (single): ^(u?g?o?|a)([-+=])(\b)(r?w?x?X?s?t?u?g?o?)$
REGEX (mutiple): ^((u?g?o?|a)([-+=])(\b)(r?w?x?X?s?t?u?g?o?),?)+$
I think I was going to test out the bitwise operations but never got that far.
The apply
stuff is also very very WIP and actually wrong and I should stay in the model as long as possible, this was done quickly to test things out and should definitely be changed if you want to use this.
This was WIP so take it with a grain of salt.
I think you use this by:
chm, err := MaybeChmod("some input")
if err != null {
//tell someone they did it worng
}
//chmod is now valid and can be used without checking
fmt.printf("%s", chm.String)
fmt.printf("%s", chm.Apply( ChmodAbsoluteForm(0o0555) )
/kind bug
Description
--chmod
in the container files seems to only work with the chmod octal permissions (e.g.755
) and doesn't work with short chmod directives like+x
.Steps to reproduce the issue:
podman build .
Describe the results you received:
Describe the results you expected:
Expected it to work similiar to docker with BUILDKIT enabled which builds the Containerfile correctly.
DOCKER_BUILDKIT=1 docker build . -f ./Containerfile
**Output of
podman version