-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRI: Windows images created with "shell form" CMD in Dockerfile are broken #5067
Comments
The pull request opencontainers/image-spec#829 dealing with the specification as proposed above
was closed without merging. Are there currently any other ideas how to solve this? |
I need to update the issue description a bit here. After some internal discussion, we believe adding ArgsEscaped to the OCI spec directly is kind of a hacky fix, since the exact semantics of ArgsEscaped are not really what we want to support long-term. My current thinking here is to do two things:
|
This related to opencontainers/runtime-spec#998 ? |
Any update on this by chance? Note that its not just Shell form its also Exec form that is broken. And the fix proposed will only fix Shell form commands. (Which is better than no fix at all!). EX:
Which is encoded by Docker as: And
Which is encoded by Docker as: In either case its a length 1 array of a single string. Which if we pass as a I verified that this is easily fixed by adding the Thanks! |
Hi Justin :) Yes, unfortunately the issue here is a bit more widespread than I first realized. I'm hoping to get to work on this again soon. The idea was to make a change so containerd respects the existing |
Hey! :) This sounds good, do you want to do |
I didn't want to mess with changing the actual OCI image config definition, so the thought was to just add
|
My favorite part about unmarshalling JSON... Doing it twice :). Yes this would work great. We could for sure do it that way and that avoids the vendor problem as well so its a nice idea. |
I ran into this issue today while testing kubernetes 1.23 on AKS. In my case I'm simply trying to launch a local PowerShell script inside the container which used to work fine but not with the containerd runtime. As mentioned before both the exec and shell forms don't work anymore with containerd. Kubernetes is removing dockershim soon (in April in 1.24) this will probably affect a lot of Windows containers. The Kubernetes FAQ mentions that "All your existing images will still work exactly the same". Which is not true for probably a lot of Windows containers due to this issue. What is not clear to me is if there is any workaround that I can apply in my Dockerfile? As far as I have been testing there doesn't seem to be one. Which might make this issue more important. What used to work: Workarounds I tried but don't work: Any suggestion for a workaround? |
I would expect this form to work. Is it possible you have another If you don't want to rebuild your image, you can also work around this by overriding the image |
Today after restarting the cluster I tried the workarounds again and Somehow while testing my workarounds yesterday the cluster was in a weird state, it also gave different errors then the original issue did. Thanks @kevpar for pointing this out and indeed you can also override the |
Recommendation, get your container up and running first, with base image , public accessible, then exec into the container, and test the commands, parameters you want to use internally in the container, to confirm the right sintaxis accepted by your image, and or application. |
This impacts the RUN instruction as well which also has both SHELL and EXEC forms. |
Any progress on this? This appears to be affecting Windows container images deployed to Azure Container Instances. |
Suddenly we were affected by this issue on AKS. |
If it helps anyone I found this was my issue on AWS ECS when attempting to run a Windows image on Fargate. They must also be using containerd under the hood. |
@T-RN-R did you find a resolution to this issue in ACI? I've just run into it today when moving from command line deployed containers to YAML defined deployments. |
Resolved my issue in ACI's, the YAML command needed to be rewritten from command:
- "python"
- "file.py"
- "--flags" |
@stevenjh are you still actively hitting this problem? Are you using ACI? |
tl;dr
When Docker creates a Windows image with "shell form"
CMD
/ENTRYPOINT
in the Dockerfile, the args in the image config are formatted differently than CRI expects. This breaks running the image with CRI since the process args in the generated OCI runtime spec are incorrect. Docker works around this by using a non-standard image config fieldArgsEscaped
to indicate that different handling should be used for the args when the OCI spec is generated.I'm not sure if this is something we can fix easily in Docker's builder code. Even if that can be fixed, there are probably still many images out in the wild that are already affected. The easiest approach here is probably just getting
ArgsEscaped
added to the OCI spec, and updating containerd to use it.Background
On Windows, the command to execute in a container needs to be given as a single CommandLine string. This is different from Linux where an array of string args is given (as used by
execve
). In a Dockerfile, there are two directives to control what command is executed in the container:ENTRYPOINT
andCMD
. They are both affected by this issue, but we just focus onCMD
below for clarity.CMD
can be specified in either "exec" form:Or in "shell" form:
CMD foo.cmd
In “shell” form, there is a shell command prepended to the command (e.g.
cmd.exe /S /C
).In a container image, the default command to run is stored as a JSON array:
However, there is an issue with Docker-built images, where if using the “shell” form of the
CMD
directive, the args are all placed in a single array element:Now, when CRI generates an OCI runtime spec for the container, it needs to produce a single command line string. To do this from the args array, it enumerates the args and concatenates them, but first it escapes each item. This is important in case individual args container spaces:
becomes
However, this behavior is incorrect when working with a container image produced using the “shell” form of CMD:
becomes
(note the quotes)
This has the undesired effect of attempting to locate a binary named
cmd.exe /S /C foo.cmd
and run it, which fails with theThe system cannot find the file specified.
.Docker behavior
When Docker builds a Windows image with a "shell form"
CMD
orENTRYPOINT
, it puts all of the args into a single element in theCmd
field in the image config, and sets a non-standard fieldArgsEscaped
to true.At run time, the value of
ArgsEscaped
is used to determine how to format the process args in the OCI runtime spec. IfArgsEscaped
is false or not present, the standard behavior is used (spec.Process.Args
receives an array of args). However, ifArgsEscaped
is true, Docker instead populatesspec.Process.CommandLine
with a string containing the exact command line to run (CommandLine
is a Windows specific OCI runtime spec field).The Docker change to introduce this behavior was made in this commit: moby/moby@20833b0
The main point of interest is here: moby/moby@20833b0#diff-6688f4342adf127b206582942bc147a0efab01c2e376b8a1a81e62c4bfee3ce1R242-R249
Repro
This issue is fairly simple to repro.
Build an image in Docker that uses "shell form"
CMD
Dockerfile:
foo.cmd:
ping -t 127.0.0.1
Run build:
> docker build -t bug . [...] Successfully tagged bug:latest
Export the image from Docker and import into containerd
Run a container from the image
If we look at the image config we can see
ArgsEscaped
is set:Fix
We could potentially fix this for future images with a change to Docker to make it format args differently. However, I see two concerns with this approach:
The easiest fix here is probably to get
ArgsEscaped
added officially on the OCI image config, and then have containerd duplicate Docker's behavior in this regard.Interested in discussion on how else we might address this.
The text was updated successfully, but these errors were encountered: