Sunday, January 31, 2016

"FROM golang" -- revisited

In this post, we created an image that deals with go-based containers. When tagging it golang, building works out of the box for most Dockerfiles.
Now that golang has been ported to s390x, we can look at this again, creating a golang image that bases on golang rather than gccgo:

Golang is written in Go, so we first need a go compiler for bootstrapping -- we pick gccgo:
The first step is to create debian (jessie) image as described here.
Then, create a gccgo images as described here. Let's assume we have tagged it "gccgo".

To bootstrap the first golang compiler, put this Dockerfile into a subdirectory called golang-bootstrap:
FROM gccgo

RUN apt-get update \
        && apt-get install -y git
RUN cd ~ \
        && git clone https://github.com/linux-on-ibm-z/go.git \
        && cd go \
        && git checkout release-branch.go1.6 \
        && export GOROOT_BOOTSTRAP=/usr/local/gccgo/ \
        && cd src \
        && ./all.bash

# rest according to Dockerfile of golang:
ENV GOLANG_VERSION 1.6

ENV GOPATH /go
ENV PATH ~/go/bin:$GOPATH/bin:$PATH

WORKDIR $GOPATH
and run
docker build -t golang:bootstrap golang-bootstrap
This will get a fairly large image since gcc is still in place:
linux1@ibm-test-0126-0802:/data> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
golang              bootstrap           2036e5a5f52b        20 seconds ago      1.944 GB

...
Let's pull the go compiler out of that image using
docker run -ti golang:bootstrap bash -c "cd ~; tar czf /golang.tgz go"
That will run a container and create a tarball in it. We need to pinpoint the container:
linux1@ibm-test-0126-0802:/data> docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS               NAMES
94339ef0cba5        golang:bootstrap    "bash -c 'cd ~; tar c"   26 seconds ago      Exited (0) 6 seconds ago                          compassionate_nobel
...
So compassionate_nobel is the container we'll get the tarball from and put it in a new directory:
mkdir golang
docker cp compassionate_nobel:/golang.tgz golang/
Now the x86 golang image is based off the buildpack-deps image family. These images are being established for s390x at this time on Docker Hub, and the upcoming multi-arch registry support will pull them in transparently. As long as the images on Docker Hub are still somewhat experimental and multi-arch registry support is not yet available, we'll just pull in all the buildpack-deps content on our own -- it is a bunch of development tools. So golang/Dockerfile needs to look like this:

FROM debian:jessie
RUN apt-get update && \
        apt-get install -y --no-install-recommends \
                ca-certificates curl wget bzr git \
                mercurial openssh-client subversion \
                procps autoconf automake bzip2 file \
                g++ gcc imagemagick libbz2-dev libc6-dev \
                libcurl4-openssl-dev libffi-dev libgeoip-dev \
                libglib2.0-dev libjpeg-dev liblzma-dev \
                libmagickcore-dev libmagickwand-dev \
                libmysqlclient-dev libncurses-dev libpng-dev \
                libpq-dev libreadline-dev libsqlite3-dev \
                libssl-dev libtool libwebp-dev libxml2-dev \
                libxslt-dev libyaml-dev make patch xz-utils \
                zlib1g-dev

ADD golang.tgz /usr/local
ENV GOROOT /usr/local/go
ENV GOLANG_VERSION 1.6

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

WORKDIR $GOPATH
Then run
docker build -t golang golang
to get our golang image.

Let's see how we can work with this image:
git clone https://github.com/docker/distribution.git
Ok, checking out distribution/Dockerfile reveals distribution requires golang:1.5.3 at this time, so we'll tag it appropriately (assuming our 1.6 build satisfies the 1.5.3 requirements easily):
docker tag golang golang:1.5.3
docker build -t distribution distribution
docker run distribution

Note all the images built that way appear big, but the most part of that space (over one gigabyte) is common to all images, so you don't need to worry.

We can also manually compile:
docker run -ti golang bash
go get github.com/tools/godep
go get github.com/google/cadvisor
And you'll have cadvisor, a Docker monitoring tool. Find out the name of the container you're running in and extract the cadvisor binary from that container with
docker cp containername:/go/bin/cadvisor ~/
All the shared libaries required by the binary usually match. Run with:
~/cadvisor
Now you can connect to port 8080 of the Docker host -- make sure your firewall doesn't block this port and you'll have cadvisor monitoring. No worries if the web pages appear to be served slow -- it is like that, it doesn't want to comsume a lot of resources.

If you want to create a container based on that, check out this blog post. This method allows you to add the shared libraries of the original build environment, not depending on the host libraries having to match -- just leveraging what containers are useful for.

No comments:

Post a Comment