├── .dockerignore ├── .gitignore ├── 1-simple.dockerfile ├── 2-package-management.dockerfile ├── 3-live-reloading.dockerfile ├── 4-single-stage-prod.dockerfile ├── 5-multi-stage-prod.dockerfile ├── 6-multi-stage-prod-upx.dockerfile ├── 7-multi-stage-prod-upx-scratch.dockerfile ├── Dockerfile ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── README.md └── src └── main.go /.dockerignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | gin-bin 3 | -------------------------------------------------------------------------------- /1-simple.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie 2 | # create a working directory 3 | WORKDIR /go/src/app 4 | # add source code 5 | ADD src src 6 | # run main.go 7 | CMD ["go", "run", "src/main.go"] 8 | -------------------------------------------------------------------------------- /2-package-management.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie 2 | # install dep 3 | RUN go get github.com/golang/dep/cmd/dep 4 | # create a working directory 5 | WORKDIR /go/src/app 6 | # add Gopkg.toml and Gopkg.lock 7 | ADD Gopkg.toml Gopkg.toml 8 | ADD Gopkg.lock Gopkg.lock 9 | # install packages 10 | # --vendor-only is used to restrict dep from scanning source code 11 | # and finding dependencies 12 | RUN dep ensure --vendor-only 13 | # add source code 14 | ADD src src 15 | # run main.go 16 | CMD ["go", "run", "src/main.go"] 17 | -------------------------------------------------------------------------------- /3-live-reloading.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie 2 | # install dep 3 | RUN go get github.com/golang/dep/cmd/dep 4 | # install gin 5 | RUN go get github.com/codegangsta/gin 6 | # create a working directory 7 | WORKDIR /go/src/app 8 | # add Gopkg.toml and Gopkg.lock 9 | ADD Gopkg.toml Gopkg.toml 10 | ADD Gopkg.lock Gopkg.lock 11 | # install packages 12 | RUN dep ensure --vendor-only 13 | # add source code 14 | ADD src src 15 | # run main.go 16 | CMD ["go", "run", "src/main.go"] 17 | 18 | ## live reloading usage: 19 | ## $ docker build -f 3-live-reloading.dockerfile -t go-docker-dev . 20 | ## $ docker run --rm -it -p 8080:8080 -v $(pwd):/go/src/app go-docker-dev bash 21 | ## 22 | ## root@id:/go/src/app# gin --path src --port 8080 run main.go 23 | -------------------------------------------------------------------------------- /4-single-stage-prod.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie 2 | # install dep 3 | RUN go get github.com/golang/dep/cmd/dep 4 | # create a working directory 5 | WORKDIR /go/src/app 6 | # add Gopkg.toml and Gopkg.lock 7 | ADD Gopkg.toml Gopkg.toml 8 | ADD Gopkg.lock Gopkg.lock 9 | # install packages 10 | RUN dep ensure --vendor-only 11 | # add source code 12 | ADD src src 13 | # build main.go 14 | RUN go build src/main.go 15 | # run the binary 16 | CMD ["./main"] 17 | -------------------------------------------------------------------------------- /5-multi-stage-prod.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie as builder 2 | # install dep 3 | RUN go get github.com/golang/dep/cmd/dep 4 | # create a working directory 5 | WORKDIR /go/src/app 6 | # add Gopkg.toml and Gopkg.lock 7 | ADD Gopkg.toml Gopkg.toml 8 | ADD Gopkg.lock Gopkg.lock 9 | # install packages 10 | RUN dep ensure --vendor-only 11 | # add source code 12 | ADD src src 13 | # build the source 14 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go 15 | 16 | # use a minimal alpine image 17 | FROM alpine:3.7 18 | # add ca-certificates in case you need them 19 | RUN apk add --no-cache ca-certificates 20 | # set working directory 21 | WORKDIR /root 22 | # copy the binary from builder 23 | COPY --from=builder /go/src/app/main . 24 | # run the binary 25 | CMD ["./main"] 26 | -------------------------------------------------------------------------------- /6-multi-stage-prod-upx.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie as builder 2 | # install xz 3 | RUN apt-get update && apt-get install -y \ 4 | xz-utils \ 5 | && rm -rf /var/lib/apt/lists/* 6 | # install UPX 7 | ADD https://github.com/upx/upx/releases/download/v3.94/upx-3.94-amd64_linux.tar.xz /usr/local 8 | RUN xz -d -c /usr/local/upx-3.94-amd64_linux.tar.xz | \ 9 | tar -xOf - upx-3.94-amd64_linux/upx > /bin/upx && \ 10 | chmod a+x /bin/upx 11 | # install dep 12 | RUN go get github.com/golang/dep/cmd/dep 13 | # create a working directory 14 | WORKDIR /go/src/app 15 | # add Gopkg.toml and Gopkg.lock 16 | ADD Gopkg.toml Gopkg.toml 17 | ADD Gopkg.lock Gopkg.lock 18 | # install packages 19 | RUN dep ensure --vendor-only 20 | # add source code 21 | ADD src src 22 | # build the source 23 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go 24 | # strip and compress the binary 25 | RUN strip --strip-unneeded main 26 | RUN upx main 27 | 28 | # use a minimal alpine image 29 | FROM alpine:3.7 30 | # add ca-certificates in case you need them 31 | RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* 32 | # set working directory 33 | WORKDIR /root 34 | # copy the binary from builder 35 | COPY --from=builder /go/src/app/main . 36 | # run the binary 37 | CMD ["./main"] 38 | -------------------------------------------------------------------------------- /7-multi-stage-prod-upx-scratch.dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie as builder 2 | # install xz 3 | RUN apt-get update && apt-get install -y \ 4 | xz-utils \ 5 | && rm -rf /var/lib/apt/lists/* 6 | # install UPX 7 | ADD https://github.com/upx/upx/releases/download/v3.94/upx-3.94-amd64_linux.tar.xz /usr/local 8 | RUN xz -d -c /usr/local/upx-3.94-amd64_linux.tar.xz | \ 9 | tar -xOf - upx-3.94-amd64_linux/upx > /bin/upx && \ 10 | chmod a+x /bin/upx 11 | # install dep 12 | RUN go get github.com/golang/dep/cmd/dep 13 | # create a working directory 14 | WORKDIR /go/src/app 15 | # add Gopkg.toml and Gopkg.lock 16 | ADD Gopkg.toml Gopkg.toml 17 | ADD Gopkg.lock Gopkg.lock 18 | # install packages 19 | RUN dep ensure --vendor-only 20 | # add source code 21 | ADD src src 22 | # build the source 23 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go 24 | # strip and compress the binary 25 | RUN strip --strip-unneeded main 26 | RUN upx main 27 | 28 | # use scratch (base for a docker image) 29 | FROM scratch 30 | # set working directory 31 | WORKDIR /root 32 | # copy the binary from builder 33 | COPY --from=builder /go/src/app/main . 34 | # run the binary 35 | CMD ["./main"] 36 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8.5-jessie as builder 2 | # install xz 3 | RUN apt-get update && apt-get install -y \ 4 | xz-utils \ 5 | && rm -rf /var/lib/apt/lists/* 6 | # install UPX 7 | ADD https://github.com/upx/upx/releases/download/v3.94/upx-3.94-amd64_linux.tar.xz /usr/local 8 | RUN xz -d -c /usr/local/upx-3.94-amd64_linux.tar.xz | \ 9 | tar -xOf - upx-3.94-amd64_linux/upx > /bin/upx && \ 10 | chmod a+x /bin/upx 11 | # install dep 12 | RUN go get github.com/golang/dep/cmd/dep 13 | # create a working directory 14 | WORKDIR /go/src/app 15 | # add Gopkg.toml and Gopkg.lock 16 | ADD Gopkg.toml Gopkg.toml 17 | ADD Gopkg.lock Gopkg.lock 18 | # install packages 19 | RUN dep ensure --vendor-only 20 | # add source code 21 | ADD src src 22 | # build the source 23 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go 24 | # strip and compress the binary 25 | RUN strip --strip-unneeded main 26 | RUN upx main 27 | 28 | # use a minimal alpine image 29 | FROM alpine:3.7 30 | # add ca-certificates in case you need them 31 | RUN apk add --no-cache ca-certificates 32 | # set working directory 33 | WORKDIR /root 34 | # copy the binary from builder 35 | COPY --from=builder /go/src/app/main . 36 | # run the binary 37 | CMD ["./main"] 38 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | name = "github.com/sirupsen/logrus" 6 | packages = ["."] 7 | revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" 8 | version = "v1.0.4" 9 | 10 | [[projects]] 11 | branch = "master" 12 | name = "golang.org/x/crypto" 13 | packages = ["ssh/terminal"] 14 | revision = "49796115aa4b964c318aad4f3084fdb41e9aa067" 15 | 16 | [[projects]] 17 | branch = "master" 18 | name = "golang.org/x/sys" 19 | packages = [ 20 | "unix", 21 | "windows" 22 | ] 23 | revision = "88d2dcc510266da9f7f8c7f34e1940716cab5f5c" 24 | 25 | [solve-meta] 26 | analyzer-name = "dep" 27 | analyzer-version = 1 28 | inputs-digest = "97f3cd8b7a00b2b98fe58f834cf0d2f2c840a89809d15b451fdde156324ba6b1" 29 | solver-name = "gps-cdcl" 30 | solver-version = 1 31 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [prune] 29 | go-tests = true 30 | unused-packages = true 31 | 32 | [[constraint]] 33 | name = "github.com/sirupsen/logrus" 34 | version = "1.0.4" 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shahidh K Muhammed 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-docker 2 | 3 | A simple web app written in Go, with dockerfiles for development and production. 4 | 5 | Build and run using any dockerfile: 6 | 7 | ```bash 8 | $ docker build -f [dockerfile] -t go-docker . 9 | $ docker run --rm -it -p 8080:8080 go-docker 10 | ``` 11 | 12 | See branch [glide](https://github.com/shahidhk/go-docker/tree/glide) for glide based workflow instead of dep. 13 | -------------------------------------------------------------------------------- /src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | func sayHello(w http.ResponseWriter, r *http.Request) { 12 | fmt.Fprint(w, "Hello World") 13 | log.Println("said hello") 14 | } 15 | 16 | func sayPongJSON(w http.ResponseWriter, r *http.Request) { 17 | w.Header().Set("Content-Type", "application/json") 18 | fmt.Fprint(w, `{"message":"pong"}`) 19 | log.Println("said pong") 20 | } 21 | 22 | func main() { 23 | http.HandleFunc("/", sayHello) 24 | http.HandleFunc("/ping", sayPongJSON) 25 | 26 | // get port env var 27 | port := "8080" 28 | portEnv := os.Getenv("PORT") 29 | if len(portEnv) > 0 { 30 | port = portEnv 31 | } 32 | 33 | log.Printf("Listening on port %s...", port) 34 | log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) 35 | // listen and serve on 0.0.0.0:8080 by default 36 | // set environment variable PORT if you want to change port 37 | } 38 | --------------------------------------------------------------------------------