fussybeaver / bollard

Docker daemon API in Rust
Apache License 2.0
847 stars 129 forks source link

Unable to anonymously pull an image from ghcr.io when using BuildKit #428

Closed 0xLE closed 1 month ago

0xLE commented 1 month ago

The issue

My goal is to build an image using BuildKit, which depends on a public image from ghcr.io.

Dockerfile:

FROM ghcr.io/astral-sh/uv:0.2.24 as uv

Code:

let docker = Docker::connect_with_local_defaults()?;

let opt = BuildImageOptions {
    t: "test",
    dockerfile: "Dockerfile",
    version: BuilderVersion::BuilderBuildKit,
    pull: true,
    rm: true,
    forcerm: true,
    session: Some("test".to_string()),
    ..Default::default()
};

let mut tar = tar::Builder::new(Vec::new());
tar.append_dir_all(".", ".")?;
tar.finish()?;
let tar = tar.into_inner()?;

let mut stream = docker.build_image(opt, None, Some(tar.into()));

Expected behavior

Since ghcr.io/astral-sh/uv:0.2.24 is publicly accessible, I expect to be able to build my image without authenticating to ghcr.io.

Observed Behavior

The build fails with the following status:

PermissionDenied: Could not find credentials for ghcr.io

StatusResponse { vertexes: [Vertex { digest: "sha256:d8db7818453e3b59cef448ef5de67325569c02cc6d8d0c54cc3b7035d3e9cf81", inputs: [], name: "[internal] load metadata for ghcr.io/astral-sh/uv:0.2.24", cached: false, started: Some(Timestamp { seconds: 1720776674, nanos: 963008275 }), completed: Some(Timestamp { seconds: 1720776675, nanos: 266195154 }), error: "PermissionDenied: Could not find credentials for ghcr.io", progress_group: None }], statuses: [], logs: [], warnings: [] }
fussybeaver commented 1 month ago

Do you want to pull an existing image that was built by someone else and stored on ghcr.io ? Then you would use create_image.

Otherwise, in your example you need to provide the contents of the Dockerfile, either through a string, or pointing to a remote location.

0xLE commented 1 month ago

Correct, I would like to pull an existing image built by someone else when I'm building the image using buildkit. I don't want to pull images individually, but rather automatically when building the image, just like docker build --pull .. However, I can't get bollard to pull these images from a public registry when building an image.

0xLE commented 1 month ago

@fussybeaver Are you able to triage whether this is bollard's issue or if this is something on my end? I'm considering whether bollard can be used for my use-case.

fussybeaver commented 1 month ago

Can confirm that it doesn't work... I haven't managed to confirm if this is with all ghcr.io images, or isolated to this case.

fussybeaver commented 1 month ago

I have managed to build a ghcr.io image by authenticating with a phony username and an empty password:

    let credentials = bollard::auth::DockerCredentials {
        username: Some("bollard".to_string()),
        password: Some(String::new()),
        ..Default::default()
    };
    let mut creds_hsh = std::collections::HashMap::new();
    creds_hsh.insert("ghcr.io".to_string(), credentials);

    let mut image_build_stream = docker.build_image(
        build_image_options,
        Some(creds_hsh),
        Some(tar.into()),
    );

Perhaps there's something we can change in the way credentials are seeded into the buildkit codepath to make that automatic.. although I'm not sure if there other (rate-limiting) ramifications around using a fixed username.

jzeuzs commented 1 month ago

+1 to this. For me it was the image node:alpine. Although it was working when authenticating with a phony username and an empty password as mentioned above.

Log:

StatusResponse { vertexes: [Vertex { digest: "sha256:440cd33ff514df5503750388d638f6b0bbb72e04f006adc8bd2850fc89ac6073", inputs: [], name: "[internal] load metadata for docker.io/library/node:alpine", cached: false, started: Some(Timestamp { seconds: 1721397382, nanos: 538202240 }), completed: Some(Timestamp { seconds: 1721397383, nanos: 310724355 }), error: "PermissionDenied: Could not find credentials for registry-1.docker.io", progress_group: None }], statuses: [], logs: [], warnings: [] }
fussybeaver commented 1 month ago

Made a small adjustment that should mean you don't need to auth anymore..