Skip to content

Instantly share code, notes, and snippets.

@proppy
Last active November 30, 2021 17:51

Revisions

  1. proppy revised this gist Feb 14, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion go2docker.go
    Original file line number Diff line number Diff line change
    @@ -121,7 +121,7 @@ func main() {
    imageJSON, err := json.Marshal(Image{
    ID: imageID,
    Created: time.Now().UTC(),
    DockerVersion: Version,
    DockerVersion: DockerVersion,
    Config: Config{
    Cmd: []string{"/" + basename},
    },
  2. proppy revised this gist Jan 30, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions go2docker.go
    Original file line number Diff line number Diff line change
    @@ -81,7 +81,7 @@ func main() {
    log.Fatalf("failed to create temp directory: %v", err)
    }
    aout := filepath.Join(tmpDir, basename)
    command := append([]string{"go", "build", "-o", aout, "-a", "-tags", "netgo", "-ldflags", "'-w'"}, args...)
    command := append([]string{"go", "build", "-o", aout, "-a", "-tags", "netgo", "-installsuffix", "netgo"}, args...)
    if _, err := exec.Command(command[0], command[1:]...).Output(); err != nil {
    log.Fatalf("failed to run command %q: %v", strings.Join(command, " "), err)
    }
    @@ -91,7 +91,7 @@ func main() {
    }
    imageID := hex.EncodeToString(imageIDBytes)
    repo := map[string]map[string]string{
    *image: map[string]string{
    *image: {
    "latest": imageID,
    },
    }
  3. proppy revised this gist Jan 29, 2015. 1 changed file with 13 additions and 3 deletions.
    16 changes: 13 additions & 3 deletions go2docker.go
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,16 @@
    // Copyright 2015 The Go Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style
    // license that can be found in the LICENSE file.
    // Copyright 2015 Google Inc. All Rights Reserved.
    //
    // 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.

    // The go2docker command compiles a go main package and forge a minimal
    // docker image from the resulting static binary.
  4. proppy created this gist Jan 29, 2015.
    167 changes: 167 additions & 0 deletions go2docker.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,167 @@
    // Copyright 2015 The Go Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style
    // license that can be found in the LICENSE file.

    // The go2docker command compiles a go main package and forge a minimal
    // docker image from the resulting static binary.
    //
    // usage: go2docker [-image namespace/basename] go/pkg/path | docker load
    package main

    import (
    "archive/tar"
    "bytes"
    "crypto/rand"
    "encoding/hex"
    "encoding/json"
    "flag"
    "io"
    "io/ioutil"
    "log"
    "os"
    "os/exec"
    "path"
    "path/filepath"
    "strings"
    "time"
    )

    type Config struct {
    Cmd []string `json:"Cmd"`
    }

    type Image struct {
    ID string `json:"id"`
    Created time.Time `json:"created"`
    DockerVersion string `json:"docker_version"`
    Config Config `json:"config"`
    Architecture string `json:"architecture"`
    OS string `json:"os"`
    }

    var image = flag.String("image", "", "namespace/name for the repository, default to go2docker/$(basename)")

    const (
    DockerVersion = "1.4.0"
    Arch = "amd64"
    OS = "linux"
    Version = "1.0"
    Namespace = "go2docker"
    )

    func main() {
    flag.Parse()
    args := []string{"."}
    if flag.NArg() > 0 {
    args = flag.Args()
    }

    fpath, err := filepath.Abs(args[0])
    ext := filepath.Ext(fpath)
    basename := filepath.Base(fpath[:len(fpath)-len(ext)])

    if *image == "" {
    if err != nil {
    log.Fatalf("failed to get absolute path: %v", err)
    }
    *image = path.Join(Namespace, basename)
    }
    tmpDir, err := ioutil.TempDir("", "")
    if err != nil {
    log.Fatalf("failed to create temp directory: %v", err)
    }
    aout := filepath.Join(tmpDir, basename)
    command := append([]string{"go", "build", "-o", aout, "-a", "-tags", "netgo", "-ldflags", "'-w'"}, args...)
    if _, err := exec.Command(command[0], command[1:]...).Output(); err != nil {
    log.Fatalf("failed to run command %q: %v", strings.Join(command, " "), err)
    }
    imageIDBytes := make([]byte, 32)
    if _, err := rand.Read(imageIDBytes); err != nil {
    log.Fatalf("failed to generate ID: %v")
    }
    imageID := hex.EncodeToString(imageIDBytes)
    repo := map[string]map[string]string{
    *image: map[string]string{
    "latest": imageID,
    },
    }
    repoJSON, err := json.Marshal(repo)
    if err != nil {
    log.Fatalf("failed to serialize repo %#v: %v", repo, err)
    }
    tw := tar.NewWriter(os.Stdout)
    if err := tw.WriteHeader(&tar.Header{
    Name: "repositories",
    Size: int64(len(repoJSON)),
    }); err != nil {
    log.Fatalf("failed to write /repository header: %v", err)
    }
    if _, err := tw.Write(repoJSON); err != nil {
    log.Fatalf(" failed to write /repository body: %v", err)
    }
    if err := tw.WriteHeader(&tar.Header{
    Name: imageID + "/VERSION",
    Size: int64(len(Version)),
    }); err != nil {
    log.Fatalf("failed to write /%s/VERSION header: %v", imageID, err)
    }
    if _, err := tw.Write([]byte(Version)); err != nil {
    log.Fatalf(" failed to write /%s/VERSION body: %v", imageID, err)
    }
    imageJSON, err := json.Marshal(Image{
    ID: imageID,
    Created: time.Now().UTC(),
    DockerVersion: Version,
    Config: Config{
    Cmd: []string{"/" + basename},
    },
    Architecture: Arch,
    OS: OS,
    })
    if err := tw.WriteHeader(&tar.Header{
    Name: imageID + "/json",
    Size: int64(len(imageJSON)),
    }); err != nil {
    log.Fatalf("failed to write /%s/json header: %v", imageID, err)
    }
    if _, err := tw.Write(imageJSON); err != nil {
    log.Fatalf("failed to write /%s/json body: %v", imageID, err)
    }
    var buf bytes.Buffer
    ftw := tar.NewWriter(&buf)
    file, err := os.Open(aout)
    if err != nil {
    log.Fatalf("failed to open %q: %v", aout, err)
    }
    finfo, err := file.Stat()
    if err != nil {
    log.Fatalf("failed to get file info %q: %v", aout, err)
    }
    fheader, err := tar.FileInfoHeader(finfo, "")
    if err != nil {
    log.Fatalf("failed to get file info header %q: %v", aout, err)
    }
    fheader.Name = basename
    if err := ftw.WriteHeader(fheader); err != nil {
    log.Fatalf("failed to write /%s header: %v", aout, err)
    }
    if _, err := io.Copy(ftw, file); err != nil {
    log.Fatalf("failed to write /%s body: %v", aout, err)
    }
    if err := ftw.Close(); err != nil {
    log.Fatalf("failed to close layer.tar: %v", err)
    }
    layerBytes := buf.Bytes()
    if err := tw.WriteHeader(&tar.Header{
    Name: imageID + "/layer.tar",
    Size: int64(len(layerBytes)),
    }); err != nil {
    log.Fatalf("failed to write /%s/layer.tar header: %v", imageID, err)
    }
    if _, err := tw.Write(layerBytes); err != nil {
    log.Fatalf("failed to write /%s/layer.tar body: %v", imageID, err)
    }
    if err := tw.Close(); err != nil {
    log.Fatalf("failed to close image.tar: %v", err)
    }
    }