Ejemplo n.º 1
0
        private static async Task RunDockerBuild(
            string imageName, DockerBuildUnwrap build, string[]?cacheFrom, Resource logResource, string?target = null)
        {
            // Prepare the build arguments.
            var buildArgs = new List <string>(new[] { "build" });

            if (!string.IsNullOrEmpty(build.Dockerfile))
            {
                buildArgs.AddRange(new[] { "-f", build.Dockerfile }); // add a custom Dockerfile location.
            }
            if (build.Args != null)
            {
                foreach (var arg in build.Args.Keys)
                {
                    buildArgs.AddRange(new[] { "--build-arg", $"{arg}={build.Args[arg]}" });
                }
            }
            if (build.Target != null)
            {
                buildArgs.AddRange(new[] { "--target", build.Target });
            }
            if (build.CacheFrom != null)
            {
                var cacheFromImages = cacheFrom;
                if (cacheFromImages != null && cacheFromImages.Length > 0)
                {
                    buildArgs.AddRange(new[] { "--cache-from", string.Join("", cacheFromImages) });
                }
            }
            if (build.ExtraOptions != null)
            {
                buildArgs.AddRange(build.ExtraOptions);
            }
            buildArgs.Add(build.Context !);                // push the docker build context onto the path.

            buildArgs.AddRange(new[] { "-t", imageName }); // tag the image with the chosen name.
            if (target != null)
            {
                buildArgs.AddRange(new[] { "--target", target });
            }

            await RunCommandThatMustSucceed("docker", buildArgs.ToArray(), logResource,
                                            reportFullCommandLine : true, stdin : null, build.Env).ConfigureAwait(false);
        }
Ejemplo n.º 2
0
        private static async Task <(string imageId, string[] stages)> BuildImageAsync(
            string imageName, Union <string, DockerBuildUnwrap> pathOrBuild, Resource logResource, string[]?cacheFrom)
        {
            DockerBuildUnwrap build = pathOrBuild.IsT0 ? new DockerBuildUnwrap {
                Context = pathOrBuild.AsT0
            } : pathOrBuild.AsT1;

            // If the build context is missing, default it to the working directory.
            if (build.Context == null)
            {
                build.Context = ".";
            }

            Log.Info(
                $"Building container image '{imageName}': context={build.Context}" +
                (build.Dockerfile != null ? $", dockerfile={build.Dockerfile}" : "") +
                (build.Args != null ? $", args={JsonSerializer.Serialize(build.Args)}" : "") +
                (build.Target != null ? $", target={build.Target}" : ""),
                logResource, ephemeral: true);

            // If the container build specified build stages to cache, build each in turn.
            var stages = new List <string>();

            if (build.CacheFrom?.Stages != null)
            {
                foreach (var stage in build.CacheFrom.Stages)
                {
                    await RunDockerBuild(LocalStageImageName(imageName, stage),
                                         build, cacheFrom, logResource, stage).ConfigureAwait(false);

                    stages.Add(stage);
                }
            }

            //// Invoke Docker CLI commands to build.
            await RunDockerBuild(imageName, build, cacheFrom, logResource).ConfigureAwait(false);

            // Finally, inspect the image so we can return the SHA digest. Do not forward the output of this
            // command this to the CLI to show the user.
            var inspectResult = await RunCommandThatMustSucceed(
                "docker", new[] { "image", "inspect", "-f", "{{.Id}}", imageName }, logResource).ConfigureAwait(false);

            if (string.IsNullOrEmpty(inspectResult))
            {
                throw new ResourceException($"No digest available for image {imageName}", logResource);
            }

            // From https://docs.docker.com/registry/spec/api/#content-digests
            //
            // the image id will be a "algorithm:hex" pair.  We don't care about the algorithm part.  All we
            // want is the unique portion we can use elsewhere.  Since we are also going to place this in an
            // image tag, we also don't want the colon, as that's not legal there.  So simply grab the hex
            // portion after the colon and return that.

            var imageId    = inspectResult.Trim();
            var colonIndex = imageId.LastIndexOf(":");

            imageId = colonIndex < 0 ? imageId : imageId.Substring(colonIndex + 1);

            return(imageId, stages.ToArray());
        }