diff --git a/ociclient/client.go b/ociclient/client.go index 3bbeba3..3b3c1bd 100644 --- a/ociclient/client.go +++ b/ociclient/client.go @@ -148,6 +148,13 @@ func descriptorFromResponse(resp *http.Response, knownDigest oci.Digest, require if contentType == "" { contentType = "application/octet-stream" } + if contentType == mediaTypeSchema1SignedManifest { + // [Client.read] always strips the signature envelope from signed + // schema1 manifests before returning them, so report the media + // type callers will actually see, even for a HEAD response that + // has no body to strip. + contentType = mediaTypeSchema1Manifest + } size := int64(0) if (require & requireSize) != 0 { if resp.StatusCode == http.StatusPartialContent { @@ -264,7 +271,8 @@ var knownManifestMediaTypes = []string{ oci.MediaTypeImageManifest, oci.MediaTypeImageIndex, "application/vnd.oci.artifact.manifest.v1+json", // deprecated. - "application/vnd.docker.distribution.manifest.v1+json", + mediaTypeSchema1Manifest, + mediaTypeSchema1SignedManifest, oci.MediaTypeDockerManifest, oci.MediaTypeDockerManifestList, // Technically this wildcard should be sufficient, but it isn't diff --git a/ociclient/reader.go b/ociclient/reader.go index 5ce9fa3..9e79a56 100644 --- a/ociclient/reader.go +++ b/ociclient/reader.go @@ -133,6 +133,31 @@ func (c *Client) read(req *http.Request, knownDigest oci.Digest, isManifest bool if err != nil { return nil, fmt.Errorf("invalid descriptor in response: %v", err) } + if resp.Header.Get("Content-Type") == mediaTypeSchema1SignedManifest { + // Legacy signed Docker schema1 manifest: strip the libtrust + // signature envelope here, once, so that the verification + // below (and every caller of this method) only ever sees a + // plain schema1 manifest whose bytes hash to desc.Digest, + // exactly like any other media type. See schema1Unsign. + if desc.Size > maxManifestSize { + return nil, fmt.Errorf("manifest size %d exceeds maximum size %d", desc.Size, maxManifestSize) + } + signed, err := io.ReadAll(io.LimitReader(resp.Body, maxManifestSize+1)) + if err != nil { + return nil, fmt.Errorf("failed to read signed schema1 manifest: %v", err) + } + resp.Body.Close() + if int64(len(signed)) != desc.Size { + return nil, fmt.Errorf("signed schema1 manifest size mismatch") + } + unsigned, err := schema1Unsign(signed) + if err != nil { + return nil, fmt.Errorf("cannot unsign schema1 manifest: %w", err) + } + desc.MediaType = mediaTypeSchema1Manifest + desc.Size = int64(len(unsigned)) + resp.Body = io.NopCloser(bytes.NewReader(unsigned)) + } if desc.Digest == "" { // Returning a digest isn't mandatory according to the spec, and // at least one registry (AWS's ECR) fails to return a digest diff --git a/ociclient/schema1.go b/ociclient/schema1.go new file mode 100644 index 0000000..ddfdc78 --- /dev/null +++ b/ociclient/schema1.go @@ -0,0 +1,98 @@ +// Copyright 2026 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ociclient + +import ( + "encoding/base64" + "encoding/json" + "fmt" +) + +// Legacy Docker Manifest v2 Schema 1 media types. +// +// Schema1 predates the OCI distribution spec and isn't otherwise supported +// by this module (see [oci.IndexOrManifest.Validate]), but some registries +// (notably Docker Hub) still serve very old images this way, so ociclient +// handles reading them. +// +// A schema1 manifest fetched from a registry always arrives wrapped in a +// legacy libtrust JWS-like signature envelope (mediaTypeSchema1SignedManifest), +// even when the content was never meaningfully "signed" (the signature +// algorithm is commonly "none"). The digest that registries and tags +// actually refer to is the digest of the envelope's content with the +// envelope stripped back off, not the digest of the bytes as delivered on +// the wire. ociclient strips this envelope itself (see schema1Unsign and +// its use in [Client.read]) so that everywhere else in this module - and +// every caller of it - only ever sees a plain, unsigned schema1 manifest +// whose bytes hash to the digest reported for it, exactly like every other +// media type. +// +// See https://github.com/tianon/oci-schema1 and +// https://github.com/moby/moby/commit/011bfd666eeb21a111ca450c42a3893ad03c9324 +// for more background. +const ( + mediaTypeSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+json" + mediaTypeSchema1SignedManifest = "application/vnd.docker.distribution.manifest.v1+prettyjws" +) + +// schema1ProtectedHeader is the JSON shape of the base64url-encoded +// "protected" field of each entry in a signed schema1 manifest's +// "signatures" array. FormatTail is base64-encoded (standard, padded +// encoding, as produced by Go's encoding/json for a []byte field) and, +// appended to the first FormatLength bytes of the signed manifest, +// reconstructs the unsigned manifest that the digest actually refers to. +type schema1ProtectedHeader struct { + FormatLength int `json:"formatLength"` + FormatTail []byte `json:"formatTail"` +} + +// schema1Unsign reconstructs the unsigned form of a signed Docker schema1 +// manifest (mediaTypeSchema1SignedManifest) from its raw signed bytes. The +// sha256 of the returned bytes is the digest that registries and tags refer +// to for this manifest. +func schema1Unsign(signed []byte) ([]byte, error) { + var m struct { + Signatures []struct { + Protected string `json:"protected"` + } `json:"signatures"` + } + if err := json.Unmarshal(signed, &m); err != nil { + return nil, fmt.Errorf("invalid schema1 manifest: %w", err) + } + if len(m.Signatures) == 0 { + return nil, fmt.Errorf("signed schema1 manifest has no signatures") + } + protected := m.Signatures[0].Protected + for _, s := range m.Signatures[1:] { + if s.Protected != protected { + return nil, fmt.Errorf("signed schema1 manifest has mismatched signatures") + } + } + hdrJSON, err := base64.RawURLEncoding.DecodeString(protected) + if err != nil { + return nil, fmt.Errorf("invalid schema1 signature protected header encoding: %w", err) + } + var hdr schema1ProtectedHeader + if err := json.Unmarshal(hdrJSON, &hdr); err != nil { + return nil, fmt.Errorf("invalid schema1 signature protected header: %w", err) + } + if hdr.FormatLength < 0 || hdr.FormatLength > len(signed) { + return nil, fmt.Errorf("schema1 signature formatLength %d out of range for %d-byte manifest", hdr.FormatLength, len(signed)) + } + unsigned := make([]byte, 0, hdr.FormatLength+len(hdr.FormatTail)) + unsigned = append(unsigned, signed[:hdr.FormatLength]...) + unsigned = append(unsigned, hdr.FormatTail...) + return unsigned, nil +} diff --git a/ociclient/schema1_reader_test.go b/ociclient/schema1_reader_test.go new file mode 100644 index 0000000..639e5d6 --- /dev/null +++ b/ociclient/schema1_reader_test.go @@ -0,0 +1,203 @@ +// Copyright 2026 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ociclient + +import ( + "bytes" + "context" + "encoding/json" + "io" + "net/http" + "os" + "testing" + + "github.com/docker/oci/ocidigest" + "github.com/stretchr/testify/require" +) + +// schema1TestDigest is the real Docker-Content-Digest Docker Hub returns +// for library/php:5.3, which is the digest of the *unsigned* form of the +// manifest, not of the signed bytes on the wire. +const schema1TestDigest = ocidigest.Digest("sha256:ba952a8970f2fc35e3703b2650495c64d6e015eb52a4ee03f750c69e863b3237") + +func readSchema1Fixture(t *testing.T) []byte { + t.Helper() + data, err := os.ReadFile("testdata/schema1-signed-manifest.json") + require.NoError(t, err) + return data +} + +func TestGetManifestSchema1Signed(t *testing.T) { + signed := readSchema1Fixture(t) + + c, err := New("registry.example", &Options{ + Transport: transportFunc(func(req *http.Request) (*http.Response, error) { + require.Equal(t, http.MethodGet, req.Method) + require.Equal(t, "/v2/library/php/manifests/"+schema1TestDigest.String(), req.URL.Path) + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + ContentLength: int64(len(signed)), + Header: http.Header{ + "Content-Type": {mediaTypeSchema1SignedManifest}, + "Docker-Content-Digest": {schema1TestDigest.String()}, + }, + Body: io.NopCloser(bytes.NewReader(signed)), + Request: req, + }, nil + }), + }) + require.NoError(t, err) + + r, err := c.GetManifest(context.Background(), "library/php", schema1TestDigest) + require.NoError(t, err) + defer r.Close() + + desc := r.Descriptor() + require.Equal(t, mediaTypeSchema1Manifest, desc.MediaType) + require.Equal(t, schema1TestDigest, desc.Digest) + + data, err := io.ReadAll(r) + require.NoError(t, err) + + // The bytes handed back must actually hash to the reported digest - + // the entire point of unsigning at read time. + require.Equal(t, schema1TestDigest, ocidigest.FromBytes(data)) + require.Equal(t, int64(len(data)), desc.Size) + require.Less(t, len(data), len(signed), "unsigned content should be smaller than the signed wire form") + + var m map[string]any + require.NoError(t, json.Unmarshal(data, &m)) + require.NotContains(t, m, "signatures") +} + +func TestGetTagSchema1Signed(t *testing.T) { + signed := readSchema1Fixture(t) + + c, err := New("registry.example", &Options{ + Transport: transportFunc(func(req *http.Request) (*http.Response, error) { + require.Equal(t, "/v2/library/php/manifests/5.3", req.URL.Path) + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + ContentLength: int64(len(signed)), + Header: http.Header{ + "Content-Type": {mediaTypeSchema1SignedManifest}, + "Docker-Content-Digest": {schema1TestDigest.String()}, + }, + Body: io.NopCloser(bytes.NewReader(signed)), + Request: req, + }, nil + }), + }) + require.NoError(t, err) + + r, err := c.GetTag(context.Background(), "library/php", "5.3") + require.NoError(t, err) + defer r.Close() + + data, err := io.ReadAll(r) + require.NoError(t, err) + require.Equal(t, schema1TestDigest, ocidigest.FromBytes(data)) + require.Equal(t, mediaTypeSchema1Manifest, r.Descriptor().MediaType) +} + +// TestGetTagSchema1SignedNoDigestHeader exercises registries (like AWS ECR, +// per the comment in [Client.read]) that omit Docker-Content-Digest on a +// tag GET: the digest must be derived from the unsigned content, not the +// signed wire bytes. +func TestGetTagSchema1SignedNoDigestHeader(t *testing.T) { + signed := readSchema1Fixture(t) + + c, err := New("registry.example", &Options{ + Transport: transportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + ContentLength: int64(len(signed)), + Header: http.Header{ + "Content-Type": {mediaTypeSchema1SignedManifest}, + }, + Body: io.NopCloser(bytes.NewReader(signed)), + Request: req, + }, nil + }), + }) + require.NoError(t, err) + + r, err := c.GetTag(context.Background(), "library/php", "5.3") + require.NoError(t, err) + defer r.Close() + + require.Equal(t, schema1TestDigest, r.Descriptor().Digest) + data, err := io.ReadAll(r) + require.NoError(t, err) + require.Equal(t, schema1TestDigest, ocidigest.FromBytes(data)) +} + +func TestGetManifestSchema1SignedDigestMismatch(t *testing.T) { + signed := readSchema1Fixture(t) + const wrongDigest = ocidigest.Digest("sha256:0000000000000000000000000000000000000000000000000000000000000000") + + c, err := New("registry.example", &Options{ + Transport: transportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + ContentLength: int64(len(signed)), + Header: http.Header{ + "Content-Type": {mediaTypeSchema1SignedManifest}, + "Docker-Content-Digest": {wrongDigest.String()}, + }, + Body: io.NopCloser(bytes.NewReader(signed)), + Request: req, + }, nil + }), + }) + require.NoError(t, err) + + r, err := c.GetManifest(context.Background(), "library/php", wrongDigest) + require.NoError(t, err) + _, err = io.ReadAll(r) + require.ErrorContains(t, err, "digest mismatch") +} + +func TestResolveManifestSchema1SignedNormalizesMediaType(t *testing.T) { + c, err := New("registry.example", &Options{ + Transport: transportFunc(func(req *http.Request) (*http.Response, error) { + require.Equal(t, http.MethodHead, req.Method) + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + ContentLength: 20841, + Header: http.Header{ + "Content-Type": {mediaTypeSchema1SignedManifest}, + "Docker-Content-Digest": {schema1TestDigest.String()}, + }, + Body: http.NoBody, + Request: req, + }, nil + }), + }) + require.NoError(t, err) + + desc, err := c.ResolveManifest(context.Background(), "library/php", schema1TestDigest) + require.NoError(t, err) + // HEAD has no body to unsign, but the reported media type is + // normalized to match what a subsequent GetManifest will return, + // so Resolve and Get stay consistent for callers. + require.Equal(t, mediaTypeSchema1Manifest, desc.MediaType) + require.Equal(t, schema1TestDigest, desc.Digest) +} diff --git a/ociclient/schema1_test.go b/ociclient/schema1_test.go new file mode 100644 index 0000000..87406e9 --- /dev/null +++ b/ociclient/schema1_test.go @@ -0,0 +1,146 @@ +// Copyright 2026 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ociclient + +import ( + "encoding/base64" + "encoding/json" + "os" + "testing" + + "github.com/docker/oci/ocidigest" + "github.com/stretchr/testify/require" +) + +// TestSchema1UnsignRealManifest is a golden test against a real signed +// schema1 manifest captured from Docker Hub's library/php:5.3, which is +// known to still be served in schema1 form. The expected digest below is +// the actual Docker-Content-Digest header Docker Hub returned for it. +func TestSchema1UnsignRealManifest(t *testing.T) { + signed, err := os.ReadFile("testdata/schema1-signed-manifest.json") + require.NoError(t, err) + + const wantDigest = ocidigest.Digest("sha256:ba952a8970f2fc35e3703b2650495c64d6e015eb52a4ee03f750c69e863b3237") + + unsigned, err := schema1Unsign(signed) + require.NoError(t, err) + require.Equal(t, wantDigest, ocidigest.FromBytes(unsigned)) + + // The raw signed bytes must NOT hash to the same digest: this is + // the whole reason schema1Unsign exists. + require.NotEqual(t, wantDigest, ocidigest.FromBytes(signed)) + + // The unsigned form must itself be valid JSON with no "signatures" key. + var m map[string]any + require.NoError(t, json.Unmarshal(unsigned, &m)) + require.NotContains(t, m, "signatures") +} + +// makeSigned builds a synthetic signed schema1 manifest from unsigned JSON +// content, using the same encoding conventions as real registries +// (base64url, unpadded, for the JWS "protected" header; base64 standard, +// padded, for the "formatTail" field within it, matching Go's +// encoding/json behavior for a []byte field). +func makeSigned(t *testing.T, unsigned []byte, extraSignatures ...string) []byte { + t.Helper() + require.True(t, len(unsigned) > 0 && unsigned[len(unsigned)-1] == '}', "unsigned fixture must end in '}'") + formatLength := len(unsigned) - 1 + formatTail := unsigned[formatLength:] // "}" + + hdr, err := json.Marshal(schema1ProtectedHeader{ + FormatLength: formatLength, + FormatTail: formatTail, + }) + require.NoError(t, err) + protected := base64.RawURLEncoding.EncodeToString(hdr) + + sigs := `{"header":{"alg":"none"},"protected":"` + protected + `","signature":""}` + for _, extra := range extraSignatures { + sigs += "," + extra + } + var signed []byte + signed = append(signed, unsigned[:formatLength]...) + signed = append(signed, []byte(`,"signatures":[`+sigs+`]}`)...) + return signed +} + +func TestSchema1UnsignSynthetic(t *testing.T) { + unsigned := []byte(`{"schemaVersion":1,"name":"foo","tag":"bar","fsLayers":[],"history":[]}`) + signed := makeSigned(t, unsigned) + + got, err := schema1Unsign(signed) + require.NoError(t, err) + require.Equal(t, unsigned, got) +} + +func TestSchema1UnsignMultipleAgreeingSignatures(t *testing.T) { + unsigned := []byte(`{"schemaVersion":1,"name":"foo","tag":"bar","fsLayers":[],"history":[]}`) + + // Build a first signed copy just to steal its "protected" value for + // a second, distinct signature entry that otherwise agrees. + first := makeSigned(t, unsigned) + var m struct { + Signatures []struct { + Protected string `json:"protected"` + } `json:"signatures"` + } + require.NoError(t, json.Unmarshal(first, &m)) + extra := `{"header":{"alg":"none"},"protected":"` + m.Signatures[0].Protected + `","signature":"different"}` + + signed := makeSigned(t, unsigned, extra) + got, err := schema1Unsign(signed) + require.NoError(t, err) + require.Equal(t, unsigned, got) +} + +func TestSchema1UnsignErrors(t *testing.T) { + unsigned := []byte(`{"schemaVersion":1,"name":"foo","tag":"bar","fsLayers":[],"history":[]}`) + valid := makeSigned(t, unsigned) + + t.Run("not JSON", func(t *testing.T) { + _, err := schema1Unsign([]byte("not json")) + require.Error(t, err) + }) + t.Run("no signatures field", func(t *testing.T) { + _, err := schema1Unsign([]byte(`{"schemaVersion":1}`)) + require.ErrorContains(t, err, "no signatures") + }) + t.Run("empty signatures array", func(t *testing.T) { + _, err := schema1Unsign([]byte(`{"schemaVersion":1,"signatures":[]}`)) + require.ErrorContains(t, err, "no signatures") + }) + t.Run("mismatched signatures", func(t *testing.T) { + _, err := schema1Unsign([]byte(`{"schemaVersion":1,"signatures":[ + {"protected":"aaaa","signature":""}, + {"protected":"bbbb","signature":""} + ]}`)) + require.ErrorContains(t, err, "mismatched signatures") + }) + t.Run("invalid protected encoding", func(t *testing.T) { + _, err := schema1Unsign([]byte(`{"schemaVersion":1,"signatures":[{"protected":"not-valid-base64!!","signature":""}]}`)) + require.Error(t, err) + }) + t.Run("formatLength out of range", func(t *testing.T) { + hdr, err := json.Marshal(schema1ProtectedHeader{FormatLength: 1 << 20, FormatTail: []byte("}")}) + require.NoError(t, err) + protected := base64.RawURLEncoding.EncodeToString(hdr) + _, err = schema1Unsign([]byte(`{"signatures":[{"protected":"` + protected + `","signature":""}]}`)) + require.ErrorContains(t, err, "out of range") + }) + t.Run("valid input sanity check", func(t *testing.T) { + _, err := schema1Unsign(valid) + require.NoError(t, err) + }) +} diff --git a/ociclient/testdata/schema1-signed-manifest.json b/ociclient/testdata/schema1-signed-manifest.json new file mode 100644 index 0000000..8024ee3 --- /dev/null +++ b/ociclient/testdata/schema1-signed-manifest.json @@ -0,0 +1,77 @@ +{ + "name": "library/php", + "tag": "5.3", + "architecture": "amd64", + "fsLayers": [ + { + "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + }, + { + "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + }, + { + "blobSum": "sha256:4f591d797078c8cce8750f2c965dd896419b2bb7d49ba3136a5ccb5d25a57ce3" + }, + { + "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + }, + { + "blobSum": "sha256:a10575de529ce1315c0a3f9b518443b6b878d43bed2d0d894623f65c2a907cca" + }, + { + "blobSum": "sha256:c025cfddd505fbe36c94aa3ccf933d92c98062675d8e818c1d9b1887e31d51b5" + }, + { + "blobSum": "sha256:cad84e43249c24d3c818202568a2ef1c9064c57c681beb3baee0cf08fdc6db58" + }, + { + "blobSum": "sha256:614879c30ef309d95bb9f31ed3c9f24e83a79748f702cdc33841f6a9a133bedd" + }, + { + "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + }, + { + "blobSum": "sha256:e31c7da51bce1efc20a4f17c64bec70be21c7e2039275d37d092c3821bb72fb1" + }, + { + "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + } + ], + "history": [ + { + "v1Compatibility": "{\"id\":\"6b3a85e4a74a8691cc185386458dfbb756bede175ef6cda919c96e4b8af09212\",\"parent\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"created\":\"2014-10-09T00:22:39.422383391Z\",\"container\":\"091f2a1fd97fc25c98feb5c36ec4f4b6be77cfe1e0acd7073306e05433933700\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [php -a]\"],\"Image\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"php\",\"-a\"],\"Image\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" + }, + { + "v1Compatibility": "{\"id\":\"6b3a85e4a74a8691cc185386458dfbb756bede175ef6cda919c96e4b8af09212\",\"parent\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"created\":\"2014-10-09T00:22:39.422383391Z\",\"container\":\"091f2a1fd97fc25c98feb5c36ec4f4b6be77cfe1e0acd7073306e05433933700\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [php -a]\"],\"Image\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"php\",\"-a\"],\"Image\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" + }, + { + "v1Compatibility": "{\"id\":\"7a81cf682147ea044601100682ed41005a516245bcae45f86d3e8548c0d37faf\",\"parent\":\"db0c0c37fac7eb7f272f8c58997fa2fa0bca302724d3be7c1265d53100f5fef5\",\"created\":\"2014-10-09T00:22:37.436305653Z\",\"container\":\"6a330c315872d15288fcc0a13e1afa455af35f376f622f0a0d048f5622ea0c1d\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"set -x \\u0026\\u0026 apt-get update \\u0026\\u0026 apt-get install -y autoconf2.13 \\u0026\\u0026 rm -r /var/lib/apt/lists/* \\u0026\\u0026 curl -SLO http://launchpadlibrarian.net/140087283/libbison-dev_2.7.1.dfsg-1_amd64.deb \\u0026\\u0026 curl -SLO http://launchpadlibrarian.net/140087282/bison_2.7.1.dfsg-1_amd64.deb \\u0026\\u0026 dpkg -i libbison-dev_2.7.1.dfsg-1_amd64.deb \\u0026\\u0026 dpkg -i bison_2.7.1.dfsg-1_amd64.deb \\u0026\\u0026 rm *.deb \\u0026\\u0026 curl -SL \\\"http://php.net/get/php-$PHP_VERSION.tar.bz2/from/this/mirror\\\" -o php.tar.bz2 \\u0026\\u0026 curl -SL \\\"http://php.net/get/php-$PHP_VERSION.tar.bz2.asc/from/this/mirror\\\" -o php.tar.bz2.asc \\u0026\\u0026 gpg --verify php.tar.bz2.asc \\u0026\\u0026 mkdir -p /usr/src/php \\u0026\\u0026 tar -xf php.tar.bz2 -C /usr/src/php --strip-components=1 \\u0026\\u0026 rm php.tar.bz2* \\u0026\\u0026 cd /usr/src/php \\u0026\\u0026 ./buildconf --force \\u0026\\u0026 ./configure --disable-cgi $(command -v apxs2 \\u003e /dev/null 2\\u003e\\u00261 \\u0026\\u0026 echo '--with-apxs2' || true) --with-mysql --with-mysqli --with-pdo-mysql \\u0026\\u0026 make -j\\\"$(nproc)\\\" \\u0026\\u0026 make install \\u0026\\u0026 dpkg -r bison libbison-dev \\u0026\\u0026 apt-get purge -y --auto-remove autoconf2.13 \\u0026\\u0026 rm -r /usr/src/php\"],\"Image\":\"db0c0c37fac7eb7f272f8c58997fa2fa0bca302724d3be7c1265d53100f5fef5\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"db0c0c37fac7eb7f272f8c58997fa2fa0bca302724d3be7c1265d53100f5fef5\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":29965290}\n" + }, + { + "v1Compatibility": "{\"id\":\"db0c0c37fac7eb7f272f8c58997fa2fa0bca302724d3be7c1265d53100f5fef5\",\"parent\":\"edc00b58da03bc4e14910d502d134d4fc6ba2fd7a210a91df89e370edfafc7ca\",\"created\":\"2014-10-09T00:19:06.657209094Z\",\"container\":\"16de590a98b0401308c2d180683bfdc808bbeeee6222c793124ef40fd87ae90b\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENV PHP_VERSION=5.3.29\"],\"Image\":\"edc00b58da03bc4e14910d502d134d4fc6ba2fd7a210a91df89e370edfafc7ca\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"PHP_VERSION=5.3.29\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"edc00b58da03bc4e14910d502d134d4fc6ba2fd7a210a91df89e370edfafc7ca\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" + }, + { + "v1Compatibility": "{\"id\":\"edc00b58da03bc4e14910d502d134d4fc6ba2fd7a210a91df89e370edfafc7ca\",\"parent\":\"b37104e8e506056b6bdb97e1c2e9c0e93ade5f1e8b92a0ed8b08ca21ddb8e646\",\"created\":\"2014-10-09T00:19:05.906713679Z\",\"container\":\"578a3033f5062fa10bd307fb1ec209e14957a3ce1d4b8f75f4825f4ab0123330\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"gpg --keyserver pgp.mit.edu --recv-keys 0B96609E270F565C13292B24C13C70B87267B52D 0A95E9A026542D53835E3F3A7DEC4E69FC9C83D7\"],\"Image\":\"b37104e8e506056b6bdb97e1c2e9c0e93ade5f1e8b92a0ed8b08ca21ddb8e646\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"b37104e8e506056b6bdb97e1c2e9c0e93ade5f1e8b92a0ed8b08ca21ddb8e646\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":23424}\n" + }, + { + "v1Compatibility": "{\"id\":\"b37104e8e506056b6bdb97e1c2e9c0e93ade5f1e8b92a0ed8b08ca21ddb8e646\",\"parent\":\"7d2b41d8b63481696f0feddc568379f9263ed0be30ed0c944afaefd3ce7946b4\",\"created\":\"2014-10-09T00:19:02.083609086Z\",\"container\":\"dc5370ee6d673a26d788228f68f036ef0a12089f9599ada29fe6a8abe157922e\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"apt-get update \\u0026\\u0026 apt-get install -y curl \\u0026\\u0026 rm -r /var/lib/apt/lists/*\"],\"Image\":\"7d2b41d8b63481696f0feddc568379f9263ed0be30ed0c944afaefd3ce7946b4\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"7d2b41d8b63481696f0feddc568379f9263ed0be30ed0c944afaefd3ce7946b4\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":1442951}\n" + }, + { + "v1Compatibility": "{\"id\":\"7d2b41d8b63481696f0feddc568379f9263ed0be30ed0c944afaefd3ce7946b4\",\"parent\":\"71e62a8beff35bb692f64fb2e04bf1d6d19f5262500ad05dd95b1a95dcb5599d\",\"created\":\"2014-10-08T20:41:58.822820789Z\",\"container\":\"cf5f8abc87568e0947671f2fa9d41c12891cc397f7f478edfff3566430859608\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"apt-get update \\u0026\\u0026 apt-get install -y bzr cvs git mercurial subversion \\u0026\\u0026 rm -rf /var/lib/apt/lists/*\"],\"Image\":\"71e62a8beff35bb692f64fb2e04bf1d6d19f5262500ad05dd95b1a95dcb5599d\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"71e62a8beff35bb692f64fb2e04bf1d6d19f5262500ad05dd95b1a95dcb5599d\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":115429837}\n" + }, + { + "v1Compatibility": "{\"id\":\"71e62a8beff35bb692f64fb2e04bf1d6d19f5262500ad05dd95b1a95dcb5599d\",\"parent\":\"53f380325ee97bd72fc8c5d9da68bdd0b6ec904e2619e3c22739d026786309d6\",\"created\":\"2014-10-08T20:40:24.639064834Z\",\"container\":\"dcb0e8b85e7974130a0daff084f34dbdfc0449106cea7bfb079f20ff122266d0\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"apt-get update \\u0026\\u0026 apt-get install -y autoconf build-essential imagemagick libbz2-dev libcurl4-openssl-dev libevent-dev libffi-dev libglib2.0-dev libjpeg-dev libmagickcore-dev libmagickwand-dev libmysqlclient-dev libncurses-dev libpq-dev libreadline-dev libsqlite3-dev libssl-dev libxml2-dev libxslt-dev libyaml-dev zlib1g-dev \\u0026\\u0026 rm -rf /var/lib/apt/lists/*\"],\"Image\":\"53f380325ee97bd72fc8c5d9da68bdd0b6ec904e2619e3c22739d026786309d6\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"53f380325ee97bd72fc8c5d9da68bdd0b6ec904e2619e3c22739d026786309d6\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":461720194}\n" + }, + { + "v1Compatibility": "{\"id\":\"53f380325ee97bd72fc8c5d9da68bdd0b6ec904e2619e3c22739d026786309d6\",\"parent\":\"50215b109eda706ddb643cdfaa92b898e76ddc6a9f08c3ac93f179946471c199\",\"created\":\"2014-10-08T18:28:20.253482919Z\",\"container\":\"1d1847de5edcd2768cd12f9c3e7613b1a7776c7ece805a106bc784d30afc2334\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/bin/bash]\"],\"Image\":\"50215b109eda706ddb643cdfaa92b898e76ddc6a9f08c3ac93f179946471c199\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"50215b109eda706ddb643cdfaa92b898e76ddc6a9f08c3ac93f179946471c199\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" + }, + { + "v1Compatibility": "{\"id\":\"50215b109eda706ddb643cdfaa92b898e76ddc6a9f08c3ac93f179946471c199\",\"parent\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"created\":\"2014-10-08T18:28:17.921786688Z\",\"container\":\"e5474231b7cd2c966b85b55d0f2227fcd740474a73748d4155a5a600cf35ae4a\",\"container_config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:8a7172abb13515b8a842208596d673fc64c1207f2446f34c6f6d65ed1f08ec75 in /\"],\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"docker_version\":\"1.2.0\",\"config\":{\"Hostname\":\"e5474231b7cd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":120019535}\n" + }, + { + "v1Compatibility": "{\"id\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"comment\":\"Imported from -\",\"created\":\"2013-06-13T14:03:50.821769-07:00\",\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"0.4.0\",\"architecture\":\"x86_64\",\"Size\":0}\n" + } + ], + "schemaVersion": 1, + "signatures": [{"header":{"alg":"none"},"protected":"eyJmb3JtYXRMZW5ndGgiOjIwNTY3LCJmb3JtYXRUYWlsIjoiQ24wPSJ9","see":["https://github.com/moby/moby/commit/011bfd666eeb21a111ca450c42a3893ad03c9324","https://docs.docker.com/go/deprecated-image-specs/"],"signature":""}] +} \ No newline at end of file