func (mb *configManifestBuilder) Build(ctx context.Context) (m distribution.Manifest, err error) {
	type imageRootFS struct {
		Type      string   `json:"type"`
		DiffIDs   []diffID `json:"diff_ids,omitempty"`
		BaseLayer string   `json:"base_layer,omitempty"`
	}
	type imageHistory struct {
		Created    time.Time `json:"created"`
		Author     string    `json:"author,omitempty"`
		CreatedBy  string    `json:"created_by,omitempty"`
		Comment    string    `json:"comment,omitempty"`
		EmptyLayer bool      `json:"empty_layer,omitempty"`
	}
	type imageConfig struct {
		RootFS       *imageRootFS   `json:"rootfs,omitempty"`
		History      []imageHistory `json:"history,omitempty"`
		Architecture string         `json:"architecture,omitempty"`
	}
	var img imageConfig
	if err := json.Unmarshal(mb.configJSON, &img); err != nil {
		return nil, err
	}
	if len(img.History) == 0 {
		return nil, errors.New("empty history when trying to create schema1 manifest")
	}
	if len(img.RootFS.DiffIDs) != len(mb.descriptors) {
		return nil, errors.New("number of descriptors and number of layers in rootfs must match")
	}
	type v1Compatibility struct {
		ID              string    `json:"id"`
		Parent          string    `json:"parent,omitempty"`
		Comment         string    `json:"comment,omitempty"`
		Created         time.Time `json:"created"`
		ContainerConfig struct {
			Cmd []string
		} `json:"container_config,omitempty"`
		Author    string `json:"author,omitempty"`
		ThrowAway bool   `json:"throwaway,omitempty"`
	}
	fsLayerList := make([]FSLayer, len(img.History))
	history := make([]History, len(img.History))
	parent := ""
	layerCounter := 0
	for i, h := range img.History[:len(img.History)-1] {
		var blobsum digest.Digest
		if h.EmptyLayer {
			if blobsum, err = mb.emptyTar(ctx); err != nil {
				return nil, err
			}
		} else {
			if len(img.RootFS.DiffIDs) <= layerCounter {
				return nil, errors.New("too many non-empty layers in History section")
			}
			blobsum = mb.descriptors[layerCounter].Digest
			layerCounter++
		}
		v1ID := digest.FromBytes([]byte(blobsum.Hex() + " " + parent)).Hex()
		if i == 0 && img.RootFS.BaseLayer != "" {
			baseID := sha512.Sum384([]byte(img.RootFS.BaseLayer))
			parent = fmt.Sprintf("%x", baseID[:32])
		}
		v1Compatibility := v1Compatibility{
			ID:      v1ID,
			Parent:  parent,
			Comment: h.Comment,
			Created: h.Created,
			Author:  h.Author,
		}
		v1Compatibility.ContainerConfig.Cmd = []string{img.History[i].CreatedBy}
		if h.EmptyLayer {
			v1Compatibility.ThrowAway = true
		}
		jsonBytes, err := json.Marshal(&v1Compatibility)
		if err != nil {
			return nil, err
		}
		reversedIndex := len(img.History) - i - 1
		history[reversedIndex].V1Compatibility = string(jsonBytes)
		fsLayerList[reversedIndex] = FSLayer{BlobSum: blobsum}
		parent = v1ID
	}
	latestHistory := img.History[len(img.History)-1]
	var blobsum digest.Digest
	if latestHistory.EmptyLayer {
		if blobsum, err = mb.emptyTar(ctx); err != nil {
			return nil, err
		}
	} else {
		if len(img.RootFS.DiffIDs) <= layerCounter {
			return nil, errors.New("too many non-empty layers in History section")
		}
		blobsum = mb.descriptors[layerCounter].Digest
	}
	fsLayerList[0] = FSLayer{BlobSum: blobsum}
	dgst := digest.FromBytes([]byte(blobsum.Hex() + " " + parent + " " + string(mb.configJSON)))
	transformedConfig, err := MakeV1ConfigFromConfig(mb.configJSON, dgst.Hex(), parent, latestHistory.EmptyLayer)
	if err != nil {
		return nil, err
	}
	history[0].V1Compatibility = string(transformedConfig)
	tag := ""
	if tagged, isTagged := mb.ref.(reference.Tagged); isTagged {
		tag = tagged.Tag()
	}
	mfst := Manifest{
		Versioned: manifest.Versioned{
			SchemaVersion: 1,
		},
		Name:         mb.ref.Name(),
		Tag:          tag,
		Architecture: img.Architecture,
		FSLayers:     fsLayerList,
		History:      history,
	}
	return Sign(&mfst, mb.pk)
}
Build produces a final manifest from the given references
package schema1
import (
	"crypto/sha512"
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/reference"
	"github.com/docker/libtrust"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/manifest"
)
type diffID digest.Digest
var gzippedEmptyTar = []byte{
	31, 139, 8, 0, 0, 9, 110, 136, 0, 255, 98, 24, 5, 163, 96, 20, 140, 88,
	0, 8, 0, 0, 255, 255, 46, 175, 181, 239, 0, 4, 0, 0,
}
const digestSHA256GzippedEmptyTar = digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")
type configManifestBuilder struct {
	bs distribution.BlobService
	pk libtrust.PrivateKey
	configJSON []byte
	ref reference.Named
	descriptors []distribution.Descriptor
	emptyTarDigest digest.Digest
}
func NewConfigManifestBuilder(bs distribution.BlobService, pk libtrust.PrivateKey, ref reference.Named, configJSON []byte) distribution.ManifestBuilder {
	return &configManifestBuilder{
		bs:         bs,
		pk:         pk,
		configJSON: configJSON,
		ref:        ref,
	}
}