Azure / azure-cli

Azure Command-Line Interface
MIT License
4k stars 2.98k forks source link

--build-arg causes failed builds in Azure Container Registry #8305

Open rcarmo opened 5 years ago

rcarmo commented 5 years ago

I have been trying to use --build-arg to inject Git hashes and build dates like I do in local builds, but whenever I try to use it it inevitably gives me an error in the build agent:

An image does not exist locally with the tag: acmedockerimages.azurecr.io/youtube-dl
"docker build" requires exactly 1 argument.
See 'docker build --help'.

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Since the option is documented, I assume it works. So far I have tried:

local-build:
    docker build \
        --build-arg BUILD_DATE=$(BUILD_DATE) \
        --build-arg VCS_REF=$(VCS_REF) \
        -t $(LOCAL_IMAGE_NAME) .

cloud-build:
    az acr build \
        --registry $(REGISTRY_NAME) \
        --build-arg BUILD_DATE=$(BUILD_DATE) \
        --build-arg VCS_REF=$(VCS_REF) \
        --image $(CONTAINER_NAME) .

...and...

local-build:
    docker build \
        --build-arg BUILD_DATE=$(BUILD_DATE) \
        --build-arg VCS_REF=$(VCS_REF) \
        -t $(LOCAL_IMAGE_NAME) .

cloud-build:
    az acr build \
        --registry $(REGISTRY_NAME) \
        --build-arg "BUILD_DATE=$(BUILD_DATE)" \
        --build-arg "VCS_REF=$(VCS_REF)" \
        --image $(CONTAINER_NAME) .

but only this works:

cloud-build:
    az acr build \
        --registry $(REGISTRY_NAME) \
        --image $(CONTAINER_NAME) .

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

jontreynes commented 5 years ago

I am also coming across this issue:

az acr build --registry $ACR_NAME --build-arg BUILD_DATE=date -u +"%Y-%m-%dT%H:%M:%SZ" --build-arg VCS_REF=git rev-parse --short HEAD --build-arg IMAGE_TAG_REF=v1 --image test/node-web:v1 .

complains with "docker build" requires exactly 1 argument. See 'docker build --help'.

Usage: docker build [OPTIONS] PATH | URL | -

I can run the below, and it works fine: docker build --build-arg BUILD_DATE=date -u +"%Y-%m-%dT%H:%M:%SZ" --build-arg VCS_REF=git rev-parse --short HEAD --build-arg IMAGE_TAG_REF=v1 --image test/node-web:v1 .

ehotinger commented 5 years ago

In general this issue is because of quotes. We interpret the command as if it were written directly to a shell. So if there's a space, or a special character like &, then the shell interprets that and decides how to split args. We have a related issue over at https://github.com/Azure/acr-builder/issues/329 for possibly escaping these to make it easier. In general though you can fix all of these by doing something like foo='bar qux &'

tjprescott commented 5 years ago

Since this is a shell quoting issue, there is nothing that can be done from the CLI side as the shell interprets the command line before it reaches the CLI. Closing.

rcarmo commented 5 years ago

I would hesitate to close this without the appropriate notes in the docs to clarify the behaviour (and rationale for it).

tjprescott commented 5 years ago

I'll leave this to @ehotinger's discretion whether to take further action.

northtyphoon commented 4 years ago

We have released the fix to address the following datetime string parsing issue.

BUILD_DATE=date -u +"%Y-%m-%dT%H:%M:%SZ"

josiahlaivins commented 4 years ago

I want to also say that I am having issues with --build-arg.

Doing: az acr build --registry some_registry --image some_image ./modules/SomeModule --secret-build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" screws up the id_rsa in that somehow the \n new lines are being removed? (this eventually causes Invalid Format Errors)

I tested: docker build ./modules/SomeModule --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" and everything works. The id_rsa keeps its original formatting.

Why is there a difference? Is anyone able to add an rsa key to the module successfully using --build-args / --secrete-build-args?

northtyphoon commented 4 years ago

For now, I’d suggest you encode such value with multiple lines or spaces to single line base64 string (eg, base64 -w 0) and pass to —build-arg or —set. On your Dockerfile file or build script, decoded it to the original value.

piranna commented 4 years ago

I'm having the same issue with the PIP_EXTRA_INDEX_URL environment variable filled by the PipAuthenticateV0 task, seems like it's adding a whitespace in the front, but when executing the failed generated command and running in local in my laptop it works. Issue with the shell? I'm using bash in Ubuntu...

amrit143 commented 4 years ago

I'm facing the same problem while passing ssh private key as a build argument. Any solution or workaround to solve it ?

josiahls commented 4 years ago

Tried doing encoding / decoding base64 and still had formatting issues. The \n kept getting ignored. Opted to manually download rsa file and use that instead.

amrit143 commented 4 years ago

I tried building with docker build command and it ran successfully, so I re-tagged my docker image to acr registry name and then pushed it. This could be the one of the workaround until acr build command supports complex value in build arg parameter. What do you think about this approach ? @josiahls How do you manage to solve ? @josiahlaivins

josiahls commented 4 years ago

@amrit143 I think your way is about as good as mine in terms of complexity. I also did try docker build a while back and it succeeded. Best way might be avoiding acr build and just build docker, use build-args, then push to azure container registry.

If you are dying to use acr build, then my solution was to have a script that downloads the rsa key as a file then have a dockerfile add that file.

So basically, your solution is likely the most elagant. Build via docker and pass the rsa key via build-args (or secret-build-args? idk), then push to acr.

sktrinh12 commented 3 years ago

I couldn't get --secret-build-arg or --build-arg to work when passing id_rsa content to the az acr build command (in bash or powershell). I ended up just copying the id_rsa file from within the Dockerfile.

SebastianRoether commented 3 years ago

I tried adding a URL with sas-token as build-arg. Couldn't make it work due to the ampersand whatsoever and ended up dropping the build arg... (did't want to use base64 encoding)

surajssd commented 2 years ago

This is still an issue for me, any idea on what's going on with this issue?

lovettchris commented 2 years ago

I'm also hitting this and I think the only real solution is for you to fix your az acr build implementation so it packages up the arguments into a file that is then shipped to the server for execution so that any double quoting issues can be handled correctly on your side rather than allowing it to turn into an impossible to debug shell issue on the server side. For example I have this powershell code:

$rc = az acr build --image snpe/quantizer:v1 --registry $registry_name --resource-group $resource_group `
  --secret-build-arg MODEL_STORAGE_CONNECTION_STRING=$Env:MODEL_STORAGE_CONNECTION_STRING `
  --build-arg SNPE_SDK=$snpe_sdk_url --build-arg SNPE_SDK_FILENAME=$snpe_sdk_filename --build-arg SNPE_ROOT=/home/chris/$snpe_root `
  --build-arg ANDROID_NDK=$android_ndk_url --build-arg ANDROID_NDK_FILENAME=$android_ndk_filename --build-arg ANDROID_NDK_ROOT=/home/chris/$android_ndk_root `
  --secret-build-arg GITHUB_PAT=$Env:GITHUB_PAT .

And I get this completely useless and totally bogus error message:

"docker build" requires exactly 1 argument.
See 'docker build --help'.
Usage:  docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
/bin/sh: 1: --build-arg: not found]
charlie2clarke commented 2 years ago

Has there been any progression with this issue? Currently experiencing the same problem.

HDROZASR commented 1 year ago

Same problem here....any ETA to fix this issue?

XavierGeerinck commented 3 months ago

Hi All! We have the same issue and use the following workaround:

Simply wrap with "' instead of just ' or "

I.e., --build-arg DEMO_PARAM_1="my-value" becomes --build-arg DEMO_PARAM_1="'my-value'"

When debugging this through the --debug param, we can see this being passed as intended. The reason this works is because I assume the shell expansion is being done correctly now.

@ehotinger I am not sure where the shell expansion happens and how it happens, but this seems to be a JSON -> Bash parsing issue rather than a developer problem. If the JSON doesn't get quoted correctly, it goes wrongly at your side. I would personally encode values BASE64 and then decode them on actual docker build reconstruction

{
  "type": "DockerBuildRequest",
  "isArchiveEnabled": false,
  "imageNames": [
    "my/demo/image:1"
  ],
  "isPushEnabled": true,
  "noCache": false,
  "dockerFilePath": "1394f4d81a514acbb3d5e8da7_Dockerfile",
  "arguments": [
    { "name": "DEMO_PARAM_1", "value": "'some_path.tar.gz'", "isSecret": false },
    { "name": "DEMO_PARAM_2", "value": "'My value that is with spaces'", "isSecret": false }
  ],
  "platform": { "os": "linux", "architecture": "amd64" },
  "sourceLocation": "source/masked/masked-cd07-4533-b96b-masked.tar.gz",
  "credentials": {}
}
ehotinger commented 3 months ago

I don't maintain this repository anymore (I haven't worked at Microsoft/Azure in 5 years!), but yes @XavierGeerinck that should work. The acr build command just gets whatever raw string you pass in and invokes a Linux or Windows shell with a quoted command from whatever string you pass in (you can check out the code at https://github.com/Azure/acr-builder/blob/main/builder/init_shell_linux.go#L7) for example. Wrapping in single quotes, base64 encoding, or escaping quotes in this pattern should all do the trick.

It's difficult / close to impossible to change this behavior without messing up other quoted input.