From 2fd7ff7ff0ba1e49c2f70ad557ab63786175f230 Mon Sep 17 00:00:00 2001 From: Petr Fedchenkov Date: Wed, 27 Jul 2022 13:46:41 +0300 Subject: [PATCH] Restart of the builder container We check only for existence of builder container and do not start it in case of not running state. We should start it for example after reboot of node to be able to build something. Signed-off-by: Petr Fedchenkov --- src/cmd/linuxkit/pkglib/docker.go | 79 +++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/src/cmd/linuxkit/pkglib/docker.go b/src/cmd/linuxkit/pkglib/docker.go index 4e60653d0..a3a11131d 100644 --- a/src/cmd/linuxkit/pkglib/docker.go +++ b/src/cmd/linuxkit/pkglib/docker.go @@ -253,10 +253,17 @@ func (dr *dockerRunnerImpl) builder(ctx context.Context, dockerContext, builderI func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, image, platform, dockerContext string, forceRestart bool) (*buildkitClient.Client, error) { // if no error, then we have a builder already // inspect it to make sure it is of the right type - var b bytes.Buffer + var ( + // recreate by default (true) unless we already have one that meets all of the requirements - image, permissions, etc. + recreate = true + // stop existing one + stop = false + remove = false + b bytes.Buffer + ) + if err := dr.command(nil, &b, ioutil.Discard, "--context", dockerContext, "container", "inspect", name); err == nil { // we already have a container named "linuxkit-builder" in the provided context. - var restart bool // get its state and config var containerJSON []types.ContainerJSON if err := json.Unmarshal(b.Bytes(), &containerJSON); err != nil || len(containerJSON) < 1 { @@ -264,42 +271,62 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im } existingImage := containerJSON[0].Config.Image + isRunning := containerJSON[0].State.Status == "running" switch { case forceRestart: - // if restart==true, we always restart, else we check if it matches our requirements + // if forceRestart==true, we always recreate, else we check if it matches our requirements fmt.Printf("told to force restart, replacing existing container %s\n", name) - restart = true + recreate = true + stop = isRunning + remove = true case existingImage != image: - // if image mismatches, restart + // if image mismatches, recreate fmt.Printf("existing container %s is running image %s instead of target %s, replacing\n", name, existingImage, image) - restart = true + recreate = true + stop = isRunning + remove = true case !containerJSON[0].HostConfig.Privileged: + // if unprivileged, we need to remove it and start a new container with the right permissions fmt.Printf("existing container %s is unprivileged, replacing\n", name) - restart = true - } - if !restart { + recreate = true + stop = isRunning + remove = true + case isRunning: + // if already running with the right image and permissions, just use it fmt.Printf("using existing container %s\n", name) return buildkitClient.New(ctx, fmt.Sprintf("docker-container://%s?context=%s", name, dockerContext)) - } - - // if we made it here, we need to stop and remove the container, either because of a config mismatch, - // or because we received the CLI option - if containerJSON[0].State.Status == "running" { - if err := dr.command(nil, ioutil.Discard, ioutil.Discard, "--context", dockerContext, "container", "stop", name); err != nil { - return nil, fmt.Errorf("failed to stop existing container %s", name) + default: + // we have an existing container, but it isn't running, so start it + fmt.Printf("starting existing container %s\n", name) + if err := dr.command(nil, ioutil.Discard, ioutil.Discard, "--context", dockerContext, "container", "start", name); err != nil { + return nil, fmt.Errorf("failed to start existing container %s", name) } + recreate = false + stop = false + remove = false } + } + // if we made it here, we need to stop and remove the container, either because of a config mismatch, + // or because we received the CLI option + if stop { + if err := dr.command(nil, ioutil.Discard, ioutil.Discard, "--context", dockerContext, "container", "stop", name); err != nil { + return nil, fmt.Errorf("failed to stop existing container %s", name) + } + } + if remove { if err := dr.command(nil, ioutil.Discard, ioutil.Discard, "--context", dockerContext, "container", "rm", name); err != nil { return nil, fmt.Errorf("failed to remove existing container %s", name) } } - // create the builder - args := []string{"container", "run", "-d", "--name", name, "--privileged", image, "--allow-insecure-entitlement", "network.host", "--addr", fmt.Sprintf("unix://%s", buildkitSocketPath), "--debug"} - msg := fmt.Sprintf("creating builder container '%s' in context '%s'", name, dockerContext) - fmt.Println(msg) - if err := dr.command(nil, ioutil.Discard, ioutil.Discard, args...); err != nil { - return nil, err + if recreate { + // create the builder + args := []string{"container", "run", "-d", "--name", name, "--privileged", image, "--allow-insecure-entitlement", "network.host", "--addr", fmt.Sprintf("unix://%s", buildkitSocketPath), "--debug"} + msg := fmt.Sprintf("creating builder container '%s' in context '%s'", name, dockerContext) + fmt.Println(msg) + if err := dr.command(nil, ioutil.Discard, ioutil.Discard, args...); err != nil { + return nil, err + } } // wait for buildkit socket to be ready up to the timeout fmt.Printf("waiting for buildkit builder to be ready, up to %d seconds\n", buildkitWaitServer) @@ -315,8 +342,12 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im case <-ticker: client, err := buildkitClient.New(ctx, fmt.Sprintf("docker-container://%s?context=%s", name, dockerContext)) if err == nil { - fmt.Println("buildkit builder ready!") - return client, nil + _, err = client.Info(ctx) + if err == nil { + fmt.Println("buildkit builder ready!") + return client, nil + } + _ = client.Close() } // got an error, wait 1 second and try again