NickThorne123 / Go_Docker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Experiments with building Go in Docker on Mac

There are a number of examples knocking around, but piecing them together into something working took longer than it should've, hence this repo.

Non Docker build (don't try this at home)

First step is to read up a bit on how to build outside of Docker (but not actually install anything). Digital Ocean have a good intro here. This overview of the go command is useful to read too. And this about go get.

So the ubiquitous hello.go is:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Executed with

go run hello.go

which will fetch the packages needed and install them locally.

To create an executable:

go build hello.go

There's also a go install hello.go to put exe files into $GOPATH/bin etc

Note that you can follow these commands with ./.. which is like a Go / wildcard.

The hello.go example pulls in a library from "github.com/golang/example/stringutil" so we need to initialise a module before running with an extra go get hello or go mod init hello before the run command above.

Docker build (do try this at home)

So enough background, onto a much better way to build and run Go, using the containerisation powers of Docker. There are a few resources like the official golang image. There are some useful bits in here and here too.

This was probably the most useful Docker + Golang resource covering more of the cross-compilation options that will allow us to compile and build in Docker and generate a Mac/OSX executable.

First step is to create a Dockerfile. You can run the compile build etc commands from the Dockerfile (commented out in this repo), and then build the Docker image from the command line with

docker build . -t nicksgolang

Next run the image with

docker run -it --rm --name insert-random-container-name nicksgolang

This will open an interactive shell in the docker container based on the nicksgolang Docker image.

You can run the commands listed at the top of this README now .

We could install nano in the image to edit the hello.go inside the shell, or more easily mount the local drive and edit in eg VSCode on Mac. So to do this we instead run

docker run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp --name insert-random-container-name nicksgolang

Now we can edit the message in hello.go and rebuild in the Docker shell and see the change.

Incidentally inside the docker shell, you can see that go get hello pulls the stringutil and places it in /go/src/github.com/golang/example/stringutil.

We haven't specifically set a go path, so it defaults to /go.

Cross compiling Golang in a Docker image

You will have noticed that the Dockerfile has a couple of environment variables set, you can see these in the shell by entering printenv, they are GOOS and GOARCH.

We have them set to darwin and amd64 so the generated ./hello binary is executable in a Mac terminal, but not in the Docker shell. Hence we have cross compiled.

Docker Compose with Golang and Docker on Mac

Finally, we want to use the power of docker-compose to make it easier to manage our containers. For this we add a docker-compose.yml file which includes the volume mapping and a command line, in this case:

command: sh -c "go get -d -v ./... && go build -v ./... "

Which gets the dependencies and builds the cross compiled binary for us. If we've modified the Dockerfile, rebuild the image with

Docker build . -t nicksgolang

Then run with (--build flag rebuilds too)

docker-compose up

Check in the current directory for the freshly generated executable.

QED

About


Languages

Language:Dockerfile 51.8%Language:Go 48.2%